[Midnightbsd-cvs] src [10057] trunk/sys/dev: update ubsec and uart
laffer1 at midnightbsd.org
laffer1 at midnightbsd.org
Sun May 27 18:53:07 EDT 2018
Revision: 10057
http://svnweb.midnightbsd.org/src/?rev=10057
Author: laffer1
Date: 2018-05-27 18:53:06 -0400 (Sun, 27 May 2018)
Log Message:
-----------
update ubsec and uart
Modified Paths:
--------------
trunk/sys/dev/uart/uart.h
trunk/sys/dev/uart/uart_bus.h
trunk/sys/dev/uart/uart_bus_acpi.c
trunk/sys/dev/uart/uart_bus_ebus.c
trunk/sys/dev/uart/uart_bus_fdt.c
trunk/sys/dev/uart/uart_bus_isa.c
trunk/sys/dev/uart/uart_bus_pccard.c
trunk/sys/dev/uart/uart_bus_pci.c
trunk/sys/dev/uart/uart_bus_puc.c
trunk/sys/dev/uart/uart_bus_scc.c
trunk/sys/dev/uart/uart_core.c
trunk/sys/dev/uart/uart_cpu.h
trunk/sys/dev/uart/uart_cpu_pc98.c
trunk/sys/dev/uart/uart_cpu_powerpc.c
trunk/sys/dev/uart/uart_cpu_sparc64.c
trunk/sys/dev/uart/uart_dbg.c
trunk/sys/dev/uart/uart_dev_ns8250.c
trunk/sys/dev/uart/uart_dev_quicc.c
trunk/sys/dev/uart/uart_dev_sab82532.c
trunk/sys/dev/uart/uart_dev_z8530.c
trunk/sys/dev/uart/uart_if.m
trunk/sys/dev/uart/uart_kbd_sun.c
trunk/sys/dev/uart/uart_kbd_sun.h
trunk/sys/dev/uart/uart_kbd_sun_tables.h
trunk/sys/dev/uart/uart_subr.c
trunk/sys/dev/uart/uart_tty.c
trunk/sys/dev/ubsec/ubsec.c
trunk/sys/dev/ubsec/ubsecreg.h
trunk/sys/dev/ubsec/ubsecvar.h
Added Paths:
-----------
trunk/sys/dev/uart/uart_cpu_fdt.c
trunk/sys/dev/uart/uart_cpu_fdt.h
trunk/sys/dev/uart/uart_cpu_ia64.c
trunk/sys/dev/uart/uart_cpu_x86.c
trunk/sys/dev/uart/uart_dev_imx.c
trunk/sys/dev/uart/uart_dev_imx.h
trunk/sys/dev/uart/uart_dev_lpc.c
trunk/sys/dev/uart/uart_dev_msm.c
trunk/sys/dev/uart/uart_dev_msm.h
trunk/sys/dev/uart/uart_dev_ns8250.h
trunk/sys/dev/uart/uart_dev_pl011.c
trunk/sys/dev/uart/uart_dev_ti8250.c
trunk/sys/dev/uart/uart_ppstypes.h
Property Changed:
----------------
trunk/sys/dev/uart/uart_if.m
Modified: trunk/sys/dev/uart/uart.h
===================================================================
--- trunk/sys/dev/uart/uart.h 2018-05-27 22:50:50 UTC (rev 10056)
+++ trunk/sys/dev/uart/uart.h 2018-05-27 22:53:06 UTC (rev 10057)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 2003 Marcel Moolenaar
* All rights reserved.
@@ -23,7 +24,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/dev/uart/uart.h 283327 2015-05-23 20:54:25Z ian $
*/
#ifndef _DEV_UART_H_
@@ -66,6 +67,7 @@
extern struct uart_class uart_ns8250_class __attribute__((weak));
extern struct uart_class uart_quicc_class __attribute__((weak));
+extern struct uart_class uart_s3c2410_class __attribute__((weak));
extern struct uart_class uart_sab82532_class __attribute__((weak));
extern struct uart_class uart_sbbc_class __attribute__((weak));
extern struct uart_class uart_z8530_class __attribute__((weak));
Modified: trunk/sys/dev/uart/uart_bus.h
===================================================================
--- trunk/sys/dev/uart/uart_bus.h 2018-05-27 22:50:50 UTC (rev 10056)
+++ trunk/sys/dev/uart/uart_bus.h 2018-05-27 22:53:06 UTC (rev 10057)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 2003 Marcel Moolenaar
* All rights reserved.
@@ -23,7 +24,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/dev/uart/uart_bus.h 294229 2016-01-17 18:18:01Z ian $
*/
#ifndef _DEV_UART_BUS_H_
@@ -48,14 +49,6 @@
#define UART_STAT_OVERRUN 0x0400
#define UART_STAT_PARERR 0x0800
-#ifdef UART_PPS_ON_CTS
-#define UART_SIG_DPPS SER_DCTS
-#define UART_SIG_PPS SER_CTS
-#else
-#define UART_SIG_DPPS SER_DDCD
-#define UART_SIG_PPS SER_DCD
-#endif
-
/* UART_IOCTL() requests */
#define UART_IOCTL_BREAK 1
#define UART_IOCTL_IFLOW 2
@@ -87,6 +80,7 @@
struct resource *sc_ires; /* Interrupt resource. */
void *sc_icookie;
int sc_irid;
+ struct callout sc_timer;
int sc_callout:1; /* This UART is opened for callout. */
int sc_fastintr:1; /* This UART uses fast interrupts. */
@@ -97,6 +91,7 @@
int sc_polled:1; /* This UART has no interrupts. */
int sc_txbusy:1; /* This UART is transmitting. */
int sc_isquelch:1; /* This UART has input squelched. */
+ int sc_testintr:1; /* This UART is under int. testing. */
struct uart_devinfo *sc_sysdev; /* System device (or NULL). */
@@ -117,6 +112,8 @@
/* Pulse capturing support (PPS). */
struct pps_state sc_pps;
+ int sc_pps_mode;
+ sbintime_t sc_pps_captime;
/* Upper layer data. */
void *sc_softih;
@@ -133,7 +130,7 @@
};
extern devclass_t uart_devclass;
-extern char uart_driver_name[];
+extern const char uart_driver_name[];
int uart_bus_attach(device_t dev);
int uart_bus_detach(device_t dev);
@@ -147,6 +144,7 @@
int uart_tty_attach(struct uart_softc *);
int uart_tty_detach(struct uart_softc *);
+struct mtx *uart_tty_getlock(struct uart_softc *);
void uart_tty_intr(void *arg);
/*
@@ -155,6 +153,7 @@
static __inline int
uart_rx_empty(struct uart_softc *sc)
{
+
return ((sc->sc_rxget == sc->sc_rxput) ? 1 : 0);
}
@@ -161,8 +160,9 @@
static __inline int
uart_rx_full(struct uart_softc *sc)
{
- return ((sc->sc_rxput + 1 < sc->sc_rxbufsz)
- ? (sc->sc_rxput + 1 == sc->sc_rxget) : (sc->sc_rxget == 0));
+
+ return ((sc->sc_rxput + 1 < sc->sc_rxbufsz) ?
+ (sc->sc_rxput + 1 == sc->sc_rxget) : (sc->sc_rxget == 0));
}
static __inline int
Modified: trunk/sys/dev/uart/uart_bus_acpi.c
===================================================================
--- trunk/sys/dev/uart/uart_bus_acpi.c 2018-05-27 22:50:50 UTC (rev 10056)
+++ trunk/sys/dev/uart/uart_bus_acpi.c 2018-05-27 22:53:06 UTC (rev 10057)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 2001 M. Warner Losh. All rights reserved.
*
@@ -23,7 +24,7 @@
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/10/sys/dev/uart/uart_bus_acpi.c 315417 2017-03-16 15:43:32Z ian $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -64,6 +65,7 @@
{0x1005d041, "Generic IRDA-compatible device"}, /* PNP0510 */
{0x1105d041, "Generic IRDA-compatible device"}, /* PNP0511 */
{0x04f0235c, "Wacom Tablet PC Screen"}, /* WACF004 */
+ {0x0ef0235c, "Wacom Tablet PC Screen 00e"}, /* WACF00e */
{0xe502aa1a, "Wacom Tablet at FuS Lifebook T"}, /* FUJ02E5 */
{0}
};
Modified: trunk/sys/dev/uart/uart_bus_ebus.c
===================================================================
--- trunk/sys/dev/uart/uart_bus_ebus.c 2018-05-27 22:50:50 UTC (rev 10056)
+++ trunk/sys/dev/uart/uart_bus_ebus.c 2018-05-27 22:53:06 UTC (rev 10057)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 2001 by Thomas Moestl <tmm at FreeBSD.org>.
* All rights reserved.
@@ -25,7 +26,7 @@
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/10/sys/dev/uart/uart_bus_ebus.c 200926 2009-12-23 22:31:43Z marius $");
#include <sys/param.h>
#include <sys/systm.h>
Modified: trunk/sys/dev/uart/uart_bus_fdt.c
===================================================================
--- trunk/sys/dev/uart/uart_bus_fdt.c 2018-05-27 22:50:50 UTC (rev 10056)
+++ trunk/sys/dev/uart/uart_bus_fdt.c 2018-05-27 22:53:06 UTC (rev 10057)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 2009-2010 The FreeBSD Foundation
* All rights reserved.
@@ -28,8 +29,10 @@
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/10/sys/dev/uart/uart_bus_fdt.c 283481 2015-05-24 17:57:29Z ian $");
+#include "opt_platform.h"
+
#include <sys/param.h>
#include <sys/bus.h>
#include <sys/kernel.h>
@@ -36,7 +39,6 @@
#include <sys/module.h>
#include <machine/bus.h>
-#include <machine/fdt.h>
#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
@@ -44,6 +46,7 @@
#include <dev/uart/uart.h>
#include <dev/uart/uart_bus.h>
#include <dev/uart/uart_cpu.h>
+#include <dev/uart/uart_cpu_fdt.h>
static int uart_fdt_probe(device_t);
@@ -61,37 +64,46 @@
sizeof(struct uart_softc),
};
-static int
+int
uart_fdt_get_clock(phandle_t node, pcell_t *cell)
{
- pcell_t clock;
- if ((OF_getprop(node, "clock-frequency", &clock,
- sizeof(clock))) <= 0)
- return (ENXIO);
-
- if (clock == 0)
+ /* clock-frequency is a FreeBSD-only extention. */
+ if ((OF_getencprop(node, "clock-frequency", cell,
+ sizeof(*cell))) <= 0) {
/* Try to retrieve parent 'bus-frequency' */
/* XXX this should go to simple-bus fixup or so */
- if ((OF_getprop(OF_parent(node), "bus-frequency", &clock,
- sizeof(clock))) <= 0)
- clock = 0;
+ if ((OF_getencprop(OF_parent(node), "bus-frequency", cell,
+ sizeof(*cell))) <= 0)
+ *cell = 0;
+ }
- *cell = fdt32_to_cpu(clock);
return (0);
}
-static int
+int
uart_fdt_get_shift(phandle_t node, pcell_t *cell)
{
- pcell_t shift;
- if ((OF_getprop(node, "reg-shift", &shift, sizeof(shift))) <= 0)
- shift = 0;
- *cell = fdt32_to_cpu(shift);
+ if ((OF_getencprop(node, "reg-shift", cell, sizeof(*cell))) <= 0)
+ *cell = 0;
return (0);
}
+static uintptr_t
+uart_fdt_find_device(device_t dev)
+{
+ struct ofw_compat_data **cd;
+ const struct ofw_compat_data *ocd;
+
+ SET_FOREACH(cd, uart_fdt_class_and_device_set) {
+ ocd = ofw_bus_search_compatible(dev, *cd);
+ if (ocd->ocd_data != 0)
+ return (ocd->ocd_data);
+ }
+ return (0);
+}
+
static int
uart_fdt_probe(device_t dev)
{
@@ -100,11 +112,14 @@
pcell_t clock, shift;
int err;
- if (!ofw_bus_is_compatible(dev, "ns16550"))
+ sc = device_get_softc(dev);
+
+ if (!ofw_bus_status_okay(dev))
return (ENXIO);
- sc = device_get_softc(dev);
- sc->sc_class = &uart_ns8250_class;
+ sc->sc_class = (struct uart_class *)uart_fdt_find_device(dev);
+ if (sc->sc_class == NULL)
+ return (ENXIO);
node = ofw_bus_get_node(dev);
@@ -116,88 +131,4 @@
}
DRIVER_MODULE(uart, simplebus, uart_fdt_driver, uart_devclass, 0, 0);
-
-/*
- * UART console routines.
- */
-bus_space_tag_t uart_bus_space_io;
-bus_space_tag_t uart_bus_space_mem;
-
-int
-uart_cpu_eqres(struct uart_bas *b1, struct uart_bas *b2)
-{
-
- return ((b1->bsh == b2->bsh && b1->bst == b2->bst) ? 1 : 0);
-}
-
-int
-uart_cpu_getdev(int devtype, struct uart_devinfo *di)
-{
- char buf[64];
- struct uart_class *class;
- phandle_t node, chosen;
- pcell_t shift, br, rclk;
- u_long start, size;
- int err;
-
- uart_bus_space_mem = fdtbus_bs_tag;
- uart_bus_space_io = NULL;
-
- /* Allow overriding the FDT uning the environment. */
- class = &uart_ns8250_class;
- err = uart_getenv(devtype, di, class);
- if (!err)
- return (0);
-
- if (devtype != UART_DEV_CONSOLE)
- return (ENXIO);
-
- /*
- * Retrieve /chosen/std{in,out}.
- */
- if ((chosen = OF_finddevice("/chosen")) == 0)
- return (ENXIO);
- if (OF_getprop(chosen, "stdin", buf, sizeof(buf)) <= 0)
- return (ENXIO);
- if ((node = OF_finddevice(buf)) == 0)
- return (ENXIO);
- if (OF_getprop(chosen, "stdout", buf, sizeof(buf)) <= 0)
- return (ENXIO);
- if (OF_finddevice(buf) != node)
- /* Only stdin == stdout is supported. */
- return (ENXIO);
- /*
- * Retrieve serial attributes.
- */
- uart_fdt_get_shift(node, &shift);
-
- if (OF_getprop(node, "current-speed", &br, sizeof(br)) <= 0)
- br = 0;
- br = fdt32_to_cpu(br);
-
- if ((err = uart_fdt_get_clock(node, &rclk)) != 0)
- return (err);
- /*
- * Finalize configuration.
- */
- class = &uart_quicc_class;
- if (fdt_is_compatible(node, "ns16550"))
- class = &uart_ns8250_class;
-
- di->bas.chan = 0;
- di->bas.regshft = (u_int)shift;
- di->baudrate = 0;
- di->bas.rclk = (u_int)rclk;
- di->ops = uart_getops(class);
- di->databits = 8;
- di->stopbits = 1;
- di->parity = UART_PARITY_NONE;
- di->bas.bst = uart_bus_space_mem;
-
- err = fdt_regsize(node, &start, &size);
- if (err)
- return (ENXIO);
- start += fdt_immr_va;
-
- return (bus_space_map(di->bas.bst, start, size, 0, &di->bas.bsh));
-}
+DRIVER_MODULE(uart, ofwbus, uart_fdt_driver, uart_devclass, 0, 0);
Modified: trunk/sys/dev/uart/uart_bus_isa.c
===================================================================
--- trunk/sys/dev/uart/uart_bus_isa.c 2018-05-27 22:50:50 UTC (rev 10056)
+++ trunk/sys/dev/uart/uart_bus_isa.c 2018-05-27 22:53:06 UTC (rev 10057)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 2008 TAKAHASHI Yoshihiro
* Copyright (c) 2008 Marcel Moolenaar
@@ -26,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/10/sys/dev/uart/uart_bus_isa.c 315417 2017-03-16 15:43:32Z ian $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -142,7 +143,8 @@
{0x90307256, NULL}, /* USR3090 - USR ? */
{0x70917256, NULL}, /* USR9170 - U.S. Robotics 56K FAX INT */
{0x90917256, NULL}, /* USR9190 - USR 56k Voice INT */
- {0x04f0235c, NULL}, /* WACF004 - Wacom Tablet PC Screen*/
+ {0x04f0235c, NULL}, /* WACF004 - Wacom Tablet PC Screen */
+ {0x0ef0235c, NULL}, /* WACF00e - Wacom Tablet PC Screen 00e */
{0x0300695c, NULL}, /* WCI0003 - Fax/Voice/Modem/Speakphone/Asvd */
{0x01a0896a, NULL}, /* ZTIA001 - Zoom Internal V90 Faxmodem */
{0x61f7896a, NULL}, /* ZTIF761 - Zoom ComStar 33.6 */
Modified: trunk/sys/dev/uart/uart_bus_pccard.c
===================================================================
--- trunk/sys/dev/uart/uart_bus_pccard.c 2018-05-27 22:50:50 UTC (rev 10056)
+++ trunk/sys/dev/uart/uart_bus_pccard.c 2018-05-27 22:53:06 UTC (rev 10057)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 2001 M. Warner Losh. All rights reserved.
* Copyright (c) 2003 Norikatsu Shigemura, Takenori Watanabe All rights reserved.
@@ -24,7 +25,7 @@
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/10/sys/dev/uart/uart_bus_pccard.c 151791 2005-10-28 06:27:53Z marcel $");
#include <sys/param.h>
#include <sys/systm.h>
Modified: trunk/sys/dev/uart/uart_bus_pci.c
===================================================================
--- trunk/sys/dev/uart/uart_bus_pci.c 2018-05-27 22:50:50 UTC (rev 10056)
+++ trunk/sys/dev/uart/uart_bus_pci.c 2018-05-27 22:53:06 UTC (rev 10057)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 2006 Marcel Moolenaar
* Copyright (c) 2001 M. Warner Losh
@@ -25,7 +26,7 @@
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/10/sys/dev/uart/uart_bus_pci.c 319511 2017-06-03 02:47:30Z emaste $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -82,6 +83,7 @@
0x10 },
{ 0x103c, 0x1048, 0x103c, 0x1301, "HP Diva RMP3", 0x14 },
{ 0x103c, 0x1290, 0xffff, 0, "HP Auxiliary Diva Serial Port", 0x18 },
+{ 0x103c, 0x3301, 0xffff, 0, "HP iLO serial port", 0x10 },
{ 0x11c1, 0x0480, 0xffff, 0, "Agere Systems Venus Modem (V90, 56KFlex)", 0x14 },
{ 0x115d, 0x0103, 0xffff, 0, "Xircom Cardbus Ethernet + 56k Modem", 0x10 },
{ 0x1282, 0x6585, 0xffff, 0, "Davicom 56PDV PCI Modem", 0x10 },
@@ -111,9 +113,18 @@
8 * DEFAULT_RCLK },
{ 0x1415, 0x950b, 0xffff, 0, "Oxford Semiconductor OXCB950 Cardbus 16950 UART",
0x10, 16384000 },
+{ 0x1415, 0xc120, 0xffff, 0, "Oxford Semiconductor OXPCIe952 PCIe 16950 UART",
+ 0x10 },
{ 0x14e4, 0x4344, 0xffff, 0, "Sony Ericsson GC89 PC Card", 0x10},
{ 0x151f, 0x0000, 0xffff, 0, "TOPIC Semiconductor TP560 56k modem", 0x10 },
+{ 0x1fd4, 0x1999, 0x1fd4, 0x0001, "Sunix SER5xxxx Serial Port", 0x10,
+ 8 * DEFAULT_RCLK },
+{ 0x8086, 0x108f, 0xffff, 0, "Intel AMT - SOL", 0x10 },
{ 0x8086, 0x1c3d, 0xffff, 0, "Intel AMT - KT Controller", 0x10 },
+{ 0x8086, 0x1d3d, 0xffff, 0, "Intel C600/X79 Series Chipset KT Controller", 0x10 },
+{ 0x8086, 0x1e3d, 0xffff, 0, "Intel Panther Point KT Controller", 0x10 },
+{ 0x8086, 0x2a07, 0xffff, 0, "Intel AMT - PM965/GM965 KT Controller", 0x10 },
+{ 0x8086, 0x2a47, 0xffff, 0, "Mobile 4 Series Chipset KT Controller", 0x10 },
{ 0x8086, 0x2e17, 0xffff, 0, "4 Series Chipset Serial KT Controller", 0x10 },
{ 0x8086, 0x3b67, 0xffff, 0, "5 Series/3400 Series Chipset KT Controller",
0x10 },
@@ -121,6 +132,8 @@
{ 0x8086, 0x8812, 0xffff, 0, "Intel EG20T Serial Port 1", 0x10 },
{ 0x8086, 0x8813, 0xffff, 0, "Intel EG20T Serial Port 2", 0x10 },
{ 0x8086, 0x8814, 0xffff, 0, "Intel EG20T Serial Port 3", 0x10 },
+{ 0x8086, 0x8c3d, 0xffff, 0, "Intel Lynx Point KT Controller", 0x10 },
+{ 0x8086, 0x8cbd, 0xffff, 0, "Intel Wildcat Point KT Controller", 0x10 },
{ 0x9710, 0x9820, 0x1000, 1, "NetMos NM9820 Serial Port", 0x10 },
{ 0x9710, 0x9835, 0x1000, 1, "NetMos NM9835 Serial Port", 0x10 },
{ 0x9710, 0x9865, 0xa000, 0x1000, "NetMos NM9865 Serial Port", 0x10 },
@@ -130,6 +143,8 @@
"MosChip MCS9901 PCIe to Peripheral Controller", 0x10 },
{ 0x9710, 0x9904, 0xa000, 0x1000,
"MosChip MCS9904 PCIe to Peripheral Controller", 0x10 },
+{ 0x9710, 0x9922, 0xa000, 0x1000,
+ "MosChip MCS9922 PCIe to Peripheral Controller", 0x10 },
{ 0xdeaf, 0x9051, 0xffff, 0, "Middle Digital PC Weasel Serial Port", 0x10 },
{ 0xffff, 0, 0xffff, 0, NULL, 0, 0}
};
@@ -161,6 +176,7 @@
{
struct uart_softc *sc;
const struct pci_id *id;
+ int result;
sc = device_get_softc(dev);
@@ -173,9 +189,14 @@
return (ENXIO);
match:
+ result = uart_bus_probe(dev, 0, id->rclk, id->rid, 0);
+ /* Bail out on error. */
+ if (result > 0)
+ return (result);
+ /* Set/override the device description. */
if (id->desc)
device_set_desc(dev, id->desc);
- return (uart_bus_probe(dev, 0, id->rclk, id->rid, 0));
+ return (result);
}
DRIVER_MODULE(uart, pci, uart_pci_driver, uart_devclass, NULL, NULL);
Modified: trunk/sys/dev/uart/uart_bus_puc.c
===================================================================
--- trunk/sys/dev/uart/uart_bus_puc.c 2018-05-27 22:50:50 UTC (rev 10056)
+++ trunk/sys/dev/uart/uart_bus_puc.c 2018-05-27 22:53:06 UTC (rev 10057)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 2006 Marcel Moolenaar. All rights reserved.
* Copyright (c) 2002 JF Hay. All rights reserved.
@@ -25,7 +26,7 @@
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/10/sys/dev/uart/uart_bus_puc.c 158124 2006-04-28 21:21:53Z marcel $");
#include <sys/param.h>
#include <sys/systm.h>
Modified: trunk/sys/dev/uart/uart_bus_scc.c
===================================================================
--- trunk/sys/dev/uart/uart_bus_scc.c 2018-05-27 22:50:50 UTC (rev 10056)
+++ trunk/sys/dev/uart/uart_bus_scc.c 2018-05-27 22:53:06 UTC (rev 10057)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 2004-2006 Marcel Moolenaar
* All rights reserved.
@@ -25,7 +26,7 @@
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/10/sys/dev/uart/uart_bus_scc.c 176772 2008-03-03 18:20:17Z raj $");
#include <sys/param.h>
#include <sys/systm.h>
Modified: trunk/sys/dev/uart/uart_core.c
===================================================================
--- trunk/sys/dev/uart/uart_core.c 2018-05-27 22:50:50 UTC (rev 10056)
+++ trunk/sys/dev/uart/uart_core.c 2018-05-27 22:53:06 UTC (rev 10057)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 2003 Marcel Moolenaar
* All rights reserved.
@@ -25,7 +26,7 @@
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/10/sys/dev/uart/uart_core.c 294229 2016-01-17 18:18:01Z ian $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -39,6 +40,7 @@
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/reboot.h>
+#include <sys/sysctl.h>
#include <machine/bus.h>
#include <sys/rman.h>
#include <machine/resource.h>
@@ -47,11 +49,12 @@
#include <dev/uart/uart.h>
#include <dev/uart/uart_bus.h>
#include <dev/uart/uart_cpu.h>
+#include <dev/uart/uart_ppstypes.h>
#include "uart_if.h"
devclass_t uart_devclass;
-char uart_driver_name[] = "uart";
+const char uart_driver_name[] = "uart";
SLIST_HEAD(uart_devinfo_list, uart_devinfo) uart_sysdevs =
SLIST_HEAD_INITIALIZER(uart_sysdevs);
@@ -58,6 +61,163 @@
static MALLOC_DEFINE(M_UART, "UART", "UART driver");
+#ifndef UART_POLL_FREQ
+#define UART_POLL_FREQ 50
+#endif
+static int uart_poll_freq = UART_POLL_FREQ;
+TUNABLE_INT("debug.uart_poll_freq", &uart_poll_freq);
+
+static inline int
+uart_pps_mode_valid(int pps_mode)
+{
+ int opt;
+
+ switch(pps_mode & UART_PPS_SIGNAL_MASK) {
+ case UART_PPS_DISABLED:
+ case UART_PPS_CTS:
+ case UART_PPS_DCD:
+ break;
+ default:
+ return (false);
+ }
+
+ opt = pps_mode & UART_PPS_OPTION_MASK;
+ if ((opt & ~(UART_PPS_INVERT_PULSE | UART_PPS_NARROW_PULSE)) != 0)
+ return (false);
+
+ return (true);
+}
+
+static void
+uart_pps_print_mode(struct uart_softc *sc)
+{
+
+ device_printf(sc->sc_dev, "PPS capture mode: ");
+ switch(sc->sc_pps_mode) {
+ case UART_PPS_DISABLED:
+ printf("disabled");
+ case UART_PPS_CTS:
+ printf("CTS");
+ case UART_PPS_DCD:
+ printf("DCD");
+ default:
+ printf("invalid");
+ }
+ if (sc->sc_pps_mode & UART_PPS_INVERT_PULSE)
+ printf("-Inverted");
+ if (sc->sc_pps_mode & UART_PPS_NARROW_PULSE)
+ printf("-NarrowPulse");
+ printf("\n");
+}
+
+static int
+uart_pps_mode_sysctl(SYSCTL_HANDLER_ARGS)
+{
+ struct uart_softc *sc;
+ int err, tmp;
+
+ sc = arg1;
+ tmp = sc->sc_pps_mode;
+ err = sysctl_handle_int(oidp, &tmp, 0, req);
+ if (err != 0 || req->newptr == NULL)
+ return (err);
+ if (!uart_pps_mode_valid(tmp))
+ return (EINVAL);
+ sc->sc_pps_mode = tmp;
+ return(0);
+}
+
+static void
+uart_pps_process(struct uart_softc *sc, int ser_sig)
+{
+ sbintime_t now;
+ int is_assert, pps_sig;
+
+ /* Which signal is configured as PPS? Early out if none. */
+ switch(sc->sc_pps_mode & UART_PPS_SIGNAL_MASK) {
+ case UART_PPS_CTS:
+ pps_sig = SER_CTS;
+ break;
+ case UART_PPS_DCD:
+ pps_sig = SER_DCD;
+ break;
+ default:
+ return;
+ }
+
+ /* Early out if there is no change in the signal configured as PPS. */
+ if ((ser_sig & SER_DELTA(pps_sig)) == 0)
+ return;
+
+ /*
+ * In narrow-pulse mode we need to synthesize both capture and clear
+ * events from a single "delta occurred" indication from the uart
+ * hardware because the pulse width is too narrow to reliably detect
+ * both edges. However, when the pulse width is close to our interrupt
+ * processing latency we might intermittantly catch both edges. To
+ * guard against generating spurious events when that happens, we use a
+ * separate timer to ensure at least half a second elapses before we
+ * generate another event.
+ */
+ pps_capture(&sc->sc_pps);
+ if (sc->sc_pps_mode & UART_PPS_NARROW_PULSE) {
+ now = getsbinuptime();
+ if (now > sc->sc_pps_captime + 500 * SBT_1MS) {
+ sc->sc_pps_captime = now;
+ pps_event(&sc->sc_pps, PPS_CAPTUREASSERT);
+ pps_event(&sc->sc_pps, PPS_CAPTURECLEAR);
+ }
+ } else {
+ is_assert = ser_sig & pps_sig;
+ if (sc->sc_pps_mode & UART_PPS_INVERT_PULSE)
+ is_assert = !is_assert;
+ pps_event(&sc->sc_pps, is_assert ? PPS_CAPTUREASSERT :
+ PPS_CAPTURECLEAR);
+ }
+}
+
+static void
+uart_pps_init(struct uart_softc *sc)
+{
+ struct sysctl_ctx_list *ctx;
+ struct sysctl_oid *tree;
+
+ ctx = device_get_sysctl_ctx(sc->sc_dev);
+ tree = device_get_sysctl_tree(sc->sc_dev);
+
+ /*
+ * The historical default for pps capture mode is either DCD or CTS,
+ * depending on the UART_PPS_ON_CTS kernel option. Start with that,
+ * then try to fetch the tunable that overrides the mode for all uart
+ * devices, then try to fetch the sysctl-tunable that overrides the mode
+ * for one specific device.
+ */
+#ifdef UART_PPS_ON_CTS
+ sc->sc_pps_mode = UART_PPS_CTS;
+#else
+ sc->sc_pps_mode = UART_PPS_DCD;
+#endif
+ TUNABLE_INT_FETCH("hw.uart.pps_mode", &sc->sc_pps_mode);
+ SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "pps_mode",
+ CTLTYPE_INT | CTLFLAG_RWTUN, sc, 0, uart_pps_mode_sysctl, "I",
+ "pulse mode: 0/1/2=disabled/CTS/DCD; "
+ "add 0x10 to invert, 0x20 for narrow pulse");
+
+ if (!uart_pps_mode_valid(sc->sc_pps_mode)) {
+ device_printf(sc->sc_dev,
+ "Invalid pps_mode 0x%02x configured; disabling PPS capture\n",
+ sc->sc_pps_mode);
+ sc->sc_pps_mode = UART_PPS_DISABLED;
+ } else if (bootverbose) {
+ uart_pps_print_mode(sc);
+ }
+
+ sc->sc_pps.ppscap = PPS_CAPTUREBOTH;
+ sc->sc_pps.driver_mtx = uart_tty_getlock(sc);
+ sc->sc_pps.driver_abi = PPS_ABI_VERSION;
+ pps_init_abi(&sc->sc_pps);
+}
+
void
uart_add_sysdev(struct uart_devinfo *di)
{
@@ -131,7 +291,7 @@
* much of the data we can, but otherwise flush the receiver FIFO to
* create some breathing room. The net effect is that we avoid the
* overrun condition to happen for the next X characters, where X is
- * related to the FIFO size at the cost of loosing data right away.
+ * related to the FIFO size at the cost of losing data right away.
* So, instead of having multiple overrun interrupts in close proximity
* to each other and possibly pessimizing UART interrupt latency for
* other UARTs in a multiport configuration, we create a longer segment
@@ -186,7 +346,7 @@
* Line or modem status change (OOB signalling).
* We pass the signals to the software interrupt handler for further
* processing. Note that we merge the delta bits, but set the state
- * bits. This is to avoid loosing state transitions due to having more
+ * bits. This is to avoid losing state transitions due to having more
* than 1 hardware interrupt between software interrupts.
*/
static __inline int
@@ -197,12 +357,12 @@
sig = UART_GETSIG(sc);
+ /*
+ * Time pulse counting support, invoked whenever the PPS parameters are
+ * currently set to capture either edge of the signal.
+ */
if (sc->sc_pps.ppsparam.mode & PPS_CAPTUREBOTH) {
- if (sig & UART_SIG_DPPS) {
- pps_capture(&sc->sc_pps);
- pps_event(&sc->sc_pps, (sig & UART_SIG_PPS) ?
- PPS_CAPTUREASSERT : PPS_CAPTURECLEAR);
- }
+ uart_pps_process(sc, sig);
}
/*
@@ -242,10 +402,15 @@
uart_intr(void *arg)
{
struct uart_softc *sc = arg;
- int flag = 0, ipend;
+ int cnt, ipend, testintr;
- while (!sc->sc_leaving && (ipend = UART_IPEND(sc)) != 0) {
- flag = 1;
+ if (sc->sc_leaving)
+ return (FILTER_STRAY);
+
+ cnt = 0;
+ testintr = sc->sc_testintr;
+ while ((!testintr || cnt < 20) && (ipend = UART_IPEND(sc)) != 0) {
+ cnt++;
if (ipend & SER_INT_OVERRUN)
uart_intr_overrun(sc);
if (ipend & SER_INT_BREAK)
@@ -255,9 +420,17 @@
if (ipend & SER_INT_SIGCHG)
uart_intr_sigchg(sc);
if (ipend & SER_INT_TXIDLE)
- uart_intr_txidle(sc);
+ uart_intr_txidle(sc);
}
- return((flag)?FILTER_HANDLED:FILTER_STRAY);
+
+ if (sc->sc_polled) {
+ callout_reset(&sc->sc_timer, hz / uart_poll_freq,
+ (timeout_t *)uart_intr, sc);
+ }
+
+ return ((cnt == 0) ? FILTER_STRAY :
+ ((testintr && cnt == 20) ? FILTER_SCHEDULE_THREAD :
+ FILTER_HANDLED));
}
serdev_intr_t *
@@ -378,7 +551,7 @@
{
struct uart_softc *sc, *sc0;
const char *sep;
- int error;
+ int error, filt;
/*
* The sc_class field defines the type of UART we're going to work
@@ -395,9 +568,16 @@
sc = sc0;
/*
+ * Now that we know the softc for this device, connect the back
+ * pointer from the sysdev for this device, if any
+ */
+ if (sc->sc_sysdev != NULL)
+ sc->sc_sysdev->sc = sc;
+
+ /*
* Protect ourselves against interrupts while we're not completely
* finished attaching and initializing. We don't expect interrupts
- * until after UART_ATTACH() though.
+ * until after UART_ATTACH(), though.
*/
sc->sc_leaving = 1;
@@ -418,33 +598,13 @@
sc->sc_bas.bsh = rman_get_bushandle(sc->sc_rres);
sc->sc_bas.bst = rman_get_bustag(sc->sc_rres);
- sc->sc_irid = 0;
- sc->sc_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->sc_irid,
- RF_ACTIVE | RF_SHAREABLE);
- if (sc->sc_ires != NULL) {
- error = bus_setup_intr(dev,
- sc->sc_ires, INTR_TYPE_TTY,
- uart_intr, NULL, sc, &sc->sc_icookie);
- if (error)
- error = bus_setup_intr(dev,
- sc->sc_ires, INTR_TYPE_TTY | INTR_MPSAFE,
- NULL, (driver_intr_t *)uart_intr, sc, &sc->sc_icookie);
- else
- sc->sc_fastintr = 1;
-
- if (error) {
- device_printf(dev, "could not activate interrupt\n");
- bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irid,
- sc->sc_ires);
- sc->sc_ires = NULL;
- }
- }
- if (sc->sc_ires == NULL) {
- /* XXX no interrupt resource. Force polled mode. */
- sc->sc_polled = 1;
- }
-
- sc->sc_rxbufsz = 384;
+ /*
+ * Ensure there is room for at least three full FIFOs of data in the
+ * receive buffer (handles the case of low-level drivers with huge
+ * FIFOs), and also ensure that there is no less than the historical
+ * size of 384 bytes (handles the typical small-FIFO case).
+ */
+ sc->sc_rxbufsz = MAX(384, sc->sc_rxfifosz * 3);
sc->sc_rxbuf = malloc(sc->sc_rxbufsz * sizeof(*sc->sc_rxbuf),
M_UART, M_WAITOK);
sc->sc_txbuf = malloc(sc->sc_txfifosz * sizeof(*sc->sc_txbuf),
@@ -468,20 +628,6 @@
printf("\n");
}
- if (bootverbose && (sc->sc_fastintr || sc->sc_polled)) {
- sep = "";
- device_print_prettyname(dev);
- if (sc->sc_fastintr) {
- printf("%sfast interrupt", sep);
- sep = ", ";
- }
- if (sc->sc_polled) {
- printf("%spolled mode", sep);
- sep = ", ";
- }
- printf("\n");
- }
-
if (sc->sc_sysdev != NULL) {
if (sc->sc_sysdev->baudrate == 0) {
if (UART_IOCTL(sc, UART_IOCTL_BAUD,
@@ -507,19 +653,70 @@
sc->sc_sysdev->stopbits);
}
- sc->sc_pps.ppscap = PPS_CAPTUREBOTH;
- pps_init(&sc->sc_pps);
+ sc->sc_leaving = 0;
+ sc->sc_testintr = 1;
+ filt = uart_intr(sc);
+ sc->sc_testintr = 0;
- error = (sc->sc_sysdev != NULL && sc->sc_sysdev->attach != NULL)
- ? (*sc->sc_sysdev->attach)(sc) : uart_tty_attach(sc);
- if (error)
- goto fail;
+ /*
+ * Don't use interrupts if we couldn't clear any pending interrupt
+ * conditions. We may have broken H/W and polling is probably the
+ * safest thing to do.
+ */
+ if (filt != FILTER_SCHEDULE_THREAD) {
+ sc->sc_irid = 0;
+ sc->sc_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ,
+ &sc->sc_irid, RF_ACTIVE | RF_SHAREABLE);
+ }
+ if (sc->sc_ires != NULL) {
+ error = bus_setup_intr(dev, sc->sc_ires, INTR_TYPE_TTY,
+ uart_intr, NULL, sc, &sc->sc_icookie);
+ sc->sc_fastintr = (error == 0) ? 1 : 0;
+ if (!sc->sc_fastintr)
+ error = bus_setup_intr(dev, sc->sc_ires,
+ INTR_TYPE_TTY | INTR_MPSAFE, NULL,
+ (driver_intr_t *)uart_intr, sc, &sc->sc_icookie);
+
+ if (error) {
+ device_printf(dev, "could not activate interrupt\n");
+ bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irid,
+ sc->sc_ires);
+ sc->sc_ires = NULL;
+ }
+ }
+ if (sc->sc_ires == NULL) {
+ /* No interrupt resource. Force polled mode. */
+ sc->sc_polled = 1;
+ callout_init(&sc->sc_timer, 1);
+ }
+
+ if (bootverbose && (sc->sc_fastintr || sc->sc_polled)) {
+ sep = "";
+ device_print_prettyname(dev);
+ if (sc->sc_fastintr) {
+ printf("%sfast interrupt", sep);
+ sep = ", ";
+ }
+ if (sc->sc_polled) {
+ printf("%spolled mode (%dHz)", sep, uart_poll_freq);
+ sep = ", ";
+ }
+ printf("\n");
+ }
+
+ if (sc->sc_sysdev != NULL && sc->sc_sysdev->attach != NULL) {
+ if ((error = sc->sc_sysdev->attach(sc)) != 0)
+ goto fail;
+ } else {
+ if ((error = uart_tty_attach(sc)) != 0)
+ goto fail;
+ uart_pps_init(sc);
+ }
+
if (sc->sc_sysdev != NULL)
sc->sc_sysdev->hwmtx = sc->sc_hwmtx;
- sc->sc_leaving = 0;
- uart_intr(sc);
return (0);
fail:
@@ -586,3 +783,19 @@
sc = device_get_softc(dev);
return (UART_ATTACH(sc));
}
+
+void
+uart_grab(struct uart_devinfo *di)
+{
+
+ if (di->sc)
+ UART_GRAB(di->sc);
+}
+
+void
+uart_ungrab(struct uart_devinfo *di)
+{
+
+ if (di->sc)
+ UART_UNGRAB(di->sc);
+}
Modified: trunk/sys/dev/uart/uart_cpu.h
===================================================================
--- trunk/sys/dev/uart/uart_cpu.h 2018-05-27 22:50:50 UTC (rev 10056)
+++ trunk/sys/dev/uart/uart_cpu.h 2018-05-27 22:53:06 UTC (rev 10057)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 2003, 2004 Marcel Moolenaar
* All rights reserved.
@@ -23,7 +24,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/dev/uart/uart_cpu.h 262649 2014-03-01 04:16:54Z imp $
*/
#ifndef _DEV_UART_CPU_H_
@@ -33,6 +34,8 @@
#include <sys/lock.h>
#include <sys/mutex.h>
+struct uart_softc;
+
/*
* Low-level operations for use by console and/or debug port support.
*/
@@ -51,7 +54,6 @@
/*
* Console and debug port device info.
*/
-struct uart_softc;
struct uart_devinfo {
SLIST_ENTRY(uart_devinfo) next;
struct uart_ops *ops;
@@ -68,6 +70,7 @@
int (*detach)(struct uart_softc*);
void *cookie; /* Type dependent use. */
struct mtx *hwmtx;
+ struct uart_softc *sc; /* valid only from start of attach */
};
int uart_cpu_eqres(struct uart_bas *, struct uart_bas *);
@@ -167,4 +170,7 @@
return (di->ops->getc(&di->bas, di->hwmtx));
}
+void uart_grab(struct uart_devinfo *di);
+void uart_ungrab(struct uart_devinfo *di);
+
#endif /* _DEV_UART_CPU_H_ */
Added: trunk/sys/dev/uart/uart_cpu_fdt.c
===================================================================
--- trunk/sys/dev/uart/uart_cpu_fdt.c (rev 0)
+++ trunk/sys/dev/uart/uart_cpu_fdt.c 2018-05-27 22:53:06 UTC (rev 10057)
@@ -0,0 +1,212 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2009-2010 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Semihalf under sponsorship from
+ * the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/dev/uart/uart_cpu_fdt.c 283481 2015-05-24 17:57:29Z ian $");
+
+#include "opt_platform.h"
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/systm.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#include <dev/uart/uart.h>
+#include <dev/uart/uart_bus.h>
+#include <dev/uart/uart_cpu.h>
+#include <dev/uart/uart_cpu_fdt.h>
+
+/*
+ * UART console routines.
+ */
+bus_space_tag_t uart_bus_space_io;
+bus_space_tag_t uart_bus_space_mem;
+
+int
+uart_cpu_eqres(struct uart_bas *b1, struct uart_bas *b2)
+{
+
+ if (b1->bst != b2->bst)
+ return (0);
+ if (pmap_kextract(b1->bsh) == 0)
+ return (0);
+ if (pmap_kextract(b2->bsh) == 0)
+ return (0);
+ return ((pmap_kextract(b1->bsh) == pmap_kextract(b2->bsh)) ? 1 : 0);
+}
+
+static int
+phandle_chosen_propdev(phandle_t chosen, const char *name, phandle_t *node)
+{
+ char buf[64];
+
+ if (OF_getprop(chosen, name, buf, sizeof(buf)) <= 0)
+ return (ENXIO);
+ if ((*node = OF_finddevice(buf)) == -1)
+ return (ENXIO);
+
+ return (0);
+}
+
+static const struct ofw_compat_data *
+uart_fdt_find_compatible(phandle_t node, const struct ofw_compat_data *cd)
+{
+ const struct ofw_compat_data *ocd;
+
+ for (ocd = cd; ocd->ocd_str != NULL; ocd++) {
+ if (fdt_is_compatible(node, ocd->ocd_str))
+ return (ocd);
+ }
+ return (NULL);
+}
+
+static uintptr_t
+uart_fdt_find_by_node(phandle_t node, int class_list)
+{
+ struct ofw_compat_data **cd;
+ const struct ofw_compat_data *ocd;
+
+ if (class_list) {
+ SET_FOREACH(cd, uart_fdt_class_set) {
+ ocd = uart_fdt_find_compatible(node, *cd);
+ if ((ocd != NULL) && (ocd->ocd_data != 0))
+ return (ocd->ocd_data);
+ }
+ } else {
+ SET_FOREACH(cd, uart_fdt_class_and_device_set) {
+ ocd = uart_fdt_find_compatible(node, *cd);
+ if ((ocd != NULL) && (ocd->ocd_data != 0))
+ return (ocd->ocd_data);
+ }
+ }
+ return (0);
+}
+
+int
+uart_cpu_getdev(int devtype, struct uart_devinfo *di)
+{
+ const char *propnames[] = {"stdout-path", "linux,stdout-path", "stdout",
+ "stdin-path", "stdin", NULL};
+ const char **name;
+ struct uart_class *class;
+ phandle_t node, chosen;
+ pcell_t shift, br, rclk;
+ u_long start, size, pbase, psize;
+ int err;
+
+ uart_bus_space_mem = fdtbus_bs_tag;
+ uart_bus_space_io = NULL;
+
+ /* Allow overriding the FDT using the environment. */
+ class = &uart_ns8250_class;
+ err = uart_getenv(devtype, di, class);
+ if (!err)
+ return (0);
+
+ if (devtype != UART_DEV_CONSOLE)
+ return (ENXIO);
+
+ /*
+ * Retrieve /chosen/std{in,out}.
+ */
+ node = -1;
+ if ((chosen = OF_finddevice("/chosen")) != -1) {
+ for (name = propnames; *name != NULL; name++) {
+ if (phandle_chosen_propdev(chosen, *name, &node) == 0)
+ break;
+ }
+ }
+ if (chosen == -1 || *name == NULL)
+ node = OF_finddevice("serial0"); /* Last ditch */
+
+ if (node == -1) /* Can't find anything */
+ return (ENXIO);
+
+ /*
+ * Retrieve serial attributes.
+ */
+ uart_fdt_get_shift(node, &shift);
+ if (OF_getprop(node, "current-speed", &br, sizeof(br)) <= 0)
+ br = 0;
+ else
+ br = fdt32_to_cpu(br);
+
+ /*
+ * Check old style of UART definition first. Unfortunately, the common
+ * FDT processing is not possible if we have clock, power domains and
+ * pinmux stuff.
+ */
+ class = (struct uart_class *)uart_fdt_find_by_node(node, 0);
+ if (class != NULL) {
+ if ((err = uart_fdt_get_clock(node, &rclk)) != 0)
+ return (err);
+ } else {
+ /* Check class only linker set */
+ class =
+ (struct uart_class *)uart_fdt_find_by_node(node, 1);
+ if (class == NULL)
+ return (ENXIO);
+ rclk = 0;
+ }
+
+ /*
+ * Finalize configuration.
+ */
+ di->bas.chan = 0;
+ di->bas.regshft = (u_int)shift;
+ di->baudrate = br;
+ di->bas.rclk = (u_int)rclk;
+ di->ops = uart_getops(class);
+ di->databits = 8;
+ di->stopbits = 1;
+ di->parity = UART_PARITY_NONE;
+ di->bas.bst = uart_bus_space_mem;
+
+ err = fdt_regsize(node, &start, &size);
+ if (err)
+ return (ENXIO);
+ err = fdt_get_range(OF_parent(node), 0, &pbase, &psize);
+ if (err)
+ pbase = 0;
+
+ start += pbase;
+
+ return (bus_space_map(di->bas.bst, start, size, 0, &di->bas.bsh));
+}
Property changes on: trunk/sys/dev/uart/uart_cpu_fdt.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/dev/uart/uart_cpu_fdt.h
===================================================================
--- trunk/sys/dev/uart/uart_cpu_fdt.h (rev 0)
+++ trunk/sys/dev/uart/uart_cpu_fdt.h 2018-05-27 22:53:06 UTC (rev 10057)
@@ -0,0 +1,57 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright 2015 Michal Meloun
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/dev/uart/uart_cpu_fdt.h 283481 2015-05-24 17:57:29Z ian $
+ */
+
+#ifndef _DEV_UART_CPU_FDT_H_
+#define _DEV_UART_CPU_FDT_H_
+
+#include <sys/linker_set.h>
+
+#include <dev/ofw/ofw_bus_subr.h>
+
+/*
+ * If your UART driver implements only uart_class and uses uart_cpu_fdt.c
+ * for device instantiation, then use UART_FDT_CLASS_AND_DEVICE for its
+ * declaration
+ */
+SET_DECLARE(uart_fdt_class_and_device_set, struct ofw_compat_data );
+#define UART_FDT_CLASS_AND_DEVICE(data) \
+ DATA_SET(uart_fdt_class_and_device_set, data)
+
+/*
+ * If your UART driver implements uart_class and custom device layer,
+ * then use UART_FDT_CLASS for its declaration
+ */
+SET_DECLARE(uart_fdt_class_set, struct ofw_compat_data );
+#define UART_FDT_CLASS(data) \
+ DATA_SET(uart_fdt_class_set, data)
+
+int uart_fdt_get_clock(phandle_t node, pcell_t *cell);
+int uart_fdt_get_shift(phandle_t node, pcell_t *cell);
+
+#endif /* _DEV_UART_CPU_FDT_H_ */
Property changes on: trunk/sys/dev/uart/uart_cpu_fdt.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/dev/uart/uart_cpu_ia64.c
===================================================================
--- trunk/sys/dev/uart/uart_cpu_ia64.c (rev 0)
+++ trunk/sys/dev/uart/uart_cpu_ia64.c 2018-05-27 22:53:06 UTC (rev 10057)
@@ -0,0 +1,114 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2003, 2004 Marcel Moolenaar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/dev/uart/uart_cpu_ia64.c 168281 2007-04-02 22:00:22Z marcel $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+
+#include <machine/bus.h>
+#include <machine/dig64.h>
+#include <machine/md_var.h>
+#include <machine/vmparam.h>
+
+#include <dev/uart/uart.h>
+#include <dev/uart/uart_cpu.h>
+
+bus_space_tag_t uart_bus_space_io = IA64_BUS_SPACE_IO;
+bus_space_tag_t uart_bus_space_mem = IA64_BUS_SPACE_MEM;
+
+static int dig64_to_uart_parity[] = {
+ UART_PARITY_NONE, UART_PARITY_NONE, UART_PARITY_EVEN,
+ UART_PARITY_ODD, UART_PARITY_MARK, UART_PARITY_SPACE
+};
+
+int
+uart_cpu_eqres(struct uart_bas *b1, struct uart_bas *b2)
+{
+
+ return ((b1->bsh == b2->bsh && b1->bst == b2->bst) ? 1 : 0);
+}
+
+int
+uart_cpu_getdev(int devtype, struct uart_devinfo *di)
+{
+ struct dig64_hcdp_table *tbl;
+ struct dig64_hcdp_entry *ent;
+ struct uart_class *class;
+ bus_addr_t addr;
+ uint64_t hcdp;
+ unsigned int i;
+
+ class = &uart_ns8250_class;
+ if (class == NULL)
+ return (ENXIO);
+
+ /*
+ * Use the DIG64 HCDP table if present.
+ */
+ hcdp = ia64_get_hcdp();
+ if (hcdp != 0) {
+ tbl = (void*)IA64_PHYS_TO_RR7(hcdp);
+ for (i = 0; i < tbl->entries; i++) {
+ ent = tbl->entry + i;
+
+ if (devtype == UART_DEV_CONSOLE &&
+ ent->type != DIG64_HCDP_CONSOLE)
+ continue;
+
+ if (devtype == UART_DEV_DBGPORT &&
+ ent->type != DIG64_HCDP_DBGPORT)
+ continue;
+
+ addr = ent->address.addr_high;
+ addr = (addr << 32) + ent->address.addr_low;
+ di->ops = uart_getops(class);
+ di->bas.chan = 0;
+ di->bas.bst = (ent->address.addr_space == 0)
+ ? uart_bus_space_mem : uart_bus_space_io;
+ if (bus_space_map(di->bas.bst, addr,
+ uart_getrange(class), 0, &di->bas.bsh) != 0)
+ continue;
+ di->bas.regshft = 0;
+ di->bas.rclk = ent->pclock << 4;
+ /* We don't deal with 64-bit baud rates. */
+ di->baudrate = ent->baud_low;
+ di->databits = ent->databits;
+ di->stopbits = ent->stopbits;
+ di->parity = (ent->parity >= 6) ? UART_PARITY_NONE
+ : dig64_to_uart_parity[ent->parity];
+ return (0);
+ }
+
+ /* FALLTHROUGH */
+ }
+
+ /* Check the environment. */
+ return (uart_getenv(devtype, di, class));
+}
Property changes on: trunk/sys/dev/uart/uart_cpu_ia64.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Modified: trunk/sys/dev/uart/uart_cpu_pc98.c
===================================================================
--- trunk/sys/dev/uart/uart_cpu_pc98.c 2018-05-27 22:50:50 UTC (rev 10056)
+++ trunk/sys/dev/uart/uart_cpu_pc98.c 2018-05-27 22:53:06 UTC (rev 10057)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 2008 TAKAHASHI Yoshihiro
* Copyright (c) 2003 M. Warner Losh, Marcel Moolenaar
@@ -26,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/10/sys/dev/uart/uart_cpu_pc98.c 216592 2010-12-20 16:39:43Z tijl $");
#include <sys/param.h>
#include <sys/systm.h>
Modified: trunk/sys/dev/uart/uart_cpu_powerpc.c
===================================================================
--- trunk/sys/dev/uart/uart_cpu_powerpc.c 2018-05-27 22:50:50 UTC (rev 10056)
+++ trunk/sys/dev/uart/uart_cpu_powerpc.c 2018-05-27 22:53:06 UTC (rev 10057)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 2006 Marcel Moolenaar
* All rights reserved.
@@ -25,7 +26,7 @@
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/10/sys/dev/uart/uart_cpu_powerpc.c 266020 2014-05-14 14:17:51Z ian $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -61,21 +62,56 @@
input = OF_finddevice(buf);
if (input == -1)
return (ENXIO);
- if (OF_getprop(opts, outputdev, buf, sizeof(buf)) == -1)
- return (ENXIO);
- if (OF_finddevice(buf) != input)
- return (ENXIO);
+ if (outputdev != NULL) {
+ if (OF_getprop(opts, outputdev, buf, sizeof(buf)) == -1)
+ return (ENXIO);
+ if (OF_finddevice(buf) != input)
+ return (ENXIO);
+ }
+
*result = input;
return (0);
}
+static int
+ofw_get_console_phandle_path(phandle_t node, phandle_t *result,
+ const char *prop)
+{
+ union {
+ char buf[64];
+ phandle_t ref;
+ } field;
+ phandle_t output;
+ ssize_t size;
+
+ size = OF_getproplen(node, prop);
+ if (size == -1)
+ return (ENXIO);
+ OF_getprop(node, prop, &field, sizeof(field));
+
+ /* This property might be either a ihandle or path. Hooray. */
+
+ output = -1;
+ if (field.buf[size - 1] == 0)
+ output = OF_finddevice(field.buf);
+ if (output == -1 && size == 4)
+ output = OF_instance_to_package(field.ref);
+
+ if (output != -1) {
+ *result = output;
+ return (0);
+ }
+
+ return (ENXIO);
+}
+
int
uart_cpu_getdev(int devtype, struct uart_devinfo *di)
{
char buf[64];
struct uart_class *class;
- phandle_t input, opts;
+ phandle_t input, opts, chosen;
int error;
class = &uart_z8530_class;
@@ -82,21 +118,40 @@
if (class == NULL)
return (ENXIO);
- if ((opts = OF_finddevice("/options")) == -1)
- return (ENXIO);
+ opts = OF_finddevice("/options");
+ chosen = OF_finddevice("/chosen");
switch (devtype) {
case UART_DEV_CONSOLE:
- if (ofw_get_uart_console(opts, &input, "input-device",
- "output-device")) {
- /*
- * At least some G5 Xserves require that we
- * probe input-device-1 as well
- */
-
- if (ofw_get_uart_console(opts, &input, "input-device-1",
- "output-device-1"))
- return (ENXIO);
+ error = ENXIO;
+ if (chosen != -1 && error != 0)
+ error = ofw_get_uart_console(chosen, &input,
+ "stdout-path", NULL);
+ if (chosen != -1 && error != 0)
+ error = ofw_get_uart_console(chosen, &input,
+ "linux,stdout-path", NULL);
+ if (chosen != -1 && error != 0)
+ error = ofw_get_console_phandle_path(chosen, &input,
+ "stdout");
+ if (chosen != -1 && error != 0)
+ error = ofw_get_uart_console(chosen, &input,
+ "stdin-path", NULL);
+ if (chosen != -1 && error != 0)
+ error = ofw_get_console_phandle_path(chosen, &input,
+ "stdin");
+ if (opts != -1 && error != 0)
+ error = ofw_get_uart_console(opts, &input,
+ "input-device", "output-device");
+ if (opts != -1 && error != 0)
+ error = ofw_get_uart_console(opts, &input,
+ "input-device-1", "output-device-1");
+ if (error != 0) {
+ input = OF_finddevice("serial0"); /* Last ditch */
+ if (input == -1)
+ error = (ENXIO);
}
+
+ if (error != 0)
+ return (error);
break;
case UART_DEV_DBGPORT:
if (!getenv_string("hw.uart.dbgport", buf, sizeof(buf)))
@@ -113,14 +168,14 @@
return (ENXIO);
if (strcmp(buf, "serial") != 0)
return (ENXIO);
- if (OF_getprop(input, "name", buf, sizeof(buf)) == -1)
+ if (OF_getprop(input, "compatible", buf, sizeof(buf)) == -1)
return (ENXIO);
- if (strcmp(buf, "ch-a") == 0) {
+ if (strncmp(buf, "chrp,es", 7) == 0) {
class = &uart_z8530_class;
di->bas.regshft = 4;
di->bas.chan = 1;
- } else if (strcmp(buf,"serial") == 0) {
+ } else if (strcmp(buf,"ns16550") == 0 || strcmp(buf,"ns8250") == 0) {
class = &uart_ns8250_class;
di->bas.regshft = 0;
di->bas.chan = 0;
@@ -139,6 +194,8 @@
if (OF_getprop(input, "current-speed", &di->baudrate,
sizeof(di->baudrate)) == -1)
di->baudrate = 0;
+ OF_getprop(input, "reg-shift", &di->bas.regshft,
+ sizeof(di->bas.regshft));
di->databits = 8;
di->stopbits = 1;
@@ -145,3 +202,4 @@
di->parity = UART_PARITY_NONE;
return (0);
}
+
Modified: trunk/sys/dev/uart/uart_cpu_sparc64.c
===================================================================
--- trunk/sys/dev/uart/uart_cpu_sparc64.c 2018-05-27 22:50:50 UTC (rev 10056)
+++ trunk/sys/dev/uart/uart_cpu_sparc64.c 2018-05-27 22:53:06 UTC (rev 10057)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 2003, 2004 Marcel Moolenaar
* Copyright (c) 2004 - 2006 Marius Strobl <marius at FreeBSD.org>
@@ -26,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/10/sys/dev/uart/uart_cpu_sparc64.c 229272 2012-01-02 12:12:10Z ed $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -71,7 +72,7 @@
if ((aliases = OF_finddevice("/aliases")) != -1)
(void)OF_getprop(aliases, dev, alias, sizeof(alias));
len = strlen(alias);
- if ((p = rindex(alias, ':')) == NULL)
+ if ((p = strrchr(alias, ':')) == NULL)
return (0);
p++;
if (p - alias == len - 1 && (*p == 'a' || *p == 'b'))
Added: trunk/sys/dev/uart/uart_cpu_x86.c
===================================================================
--- trunk/sys/dev/uart/uart_cpu_x86.c (rev 0)
+++ trunk/sys/dev/uart/uart_cpu_x86.c 2018-05-27 22:53:06 UTC (rev 10057)
@@ -0,0 +1,108 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2003, 2004 Marcel Moolenaar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/dev/uart/uart_cpu_x86.c 234118 2012-04-11 02:42:01Z marcel $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+
+#include <machine/bus.h>
+
+#include <dev/uart/uart.h>
+#include <dev/uart/uart_cpu.h>
+
+bus_space_tag_t uart_bus_space_io = X86_BUS_SPACE_IO;
+bus_space_tag_t uart_bus_space_mem = X86_BUS_SPACE_MEM;
+
+int
+uart_cpu_eqres(struct uart_bas *b1, struct uart_bas *b2)
+{
+
+ return ((b1->bsh == b2->bsh && b1->bst == b2->bst) ? 1 : 0);
+}
+
+int
+uart_cpu_getdev(int devtype, struct uart_devinfo *di)
+{
+ struct uart_class *class;
+ unsigned int i, ivar;
+
+ class = &uart_ns8250_class;
+ if (class == NULL)
+ return (ENXIO);
+
+ /* Check the environment. */
+ if (uart_getenv(devtype, di, class) == 0)
+ return (0);
+
+ /*
+ * Scan the hints. We only try units 0 to 3 (inclusive). This
+ * covers the ISA legacy where 4 UARTs had their resources
+ * predefined.
+ */
+ for (i = 0; i < 4; i++) {
+ if (resource_int_value("uart", i, "flags", &ivar))
+ continue;
+ if (devtype == UART_DEV_CONSOLE && !UART_FLAGS_CONSOLE(ivar))
+ continue;
+ if (devtype == UART_DEV_DBGPORT && !UART_FLAGS_DBGPORT(ivar))
+ continue;
+ /*
+ * We have a possible device. Make sure it's enabled and
+ * that we have an I/O port.
+ */
+ if (resource_int_value("uart", i, "disabled", &ivar) == 0 &&
+ ivar != 0)
+ continue;
+ if (resource_int_value("uart", i, "port", &ivar) != 0 ||
+ ivar == 0)
+ continue;
+ /*
+ * Got it. Fill in the instance and return it. We only have
+ * ns8250 and successors on i386.
+ */
+ di->ops = uart_getops(class);
+ di->bas.chan = 0;
+ di->bas.bst = uart_bus_space_io;
+ if (bus_space_map(di->bas.bst, ivar, uart_getrange(class), 0,
+ &di->bas.bsh) != 0)
+ continue;
+ di->bas.regshft = 0;
+ di->bas.rclk = 0;
+ if (resource_int_value("uart", i, "baud", &ivar) != 0)
+ ivar = 0;
+ di->baudrate = ivar;
+ di->databits = 8;
+ di->stopbits = 1;
+ di->parity = UART_PARITY_NONE;
+ return (0);
+ }
+
+ return (ENXIO);
+}
Property changes on: trunk/sys/dev/uart/uart_cpu_x86.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Modified: trunk/sys/dev/uart/uart_dbg.c
===================================================================
--- trunk/sys/dev/uart/uart_dbg.c 2018-05-27 22:50:50 UTC (rev 10056)
+++ trunk/sys/dev/uart/uart_dbg.c 2018-05-27 22:53:06 UTC (rev 10057)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 2004 Marcel Moolenaar
* All rights reserved.
@@ -25,7 +26,7 @@
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/10/sys/dev/uart/uart_dbg.c 158950 2006-05-26 11:54:32Z phk $");
#include <sys/param.h>
#include <sys/systm.h>
Added: trunk/sys/dev/uart/uart_dev_imx.c
===================================================================
--- trunk/sys/dev/uart/uart_dev_imx.c (rev 0)
+++ trunk/sys/dev/uart/uart_dev_imx.c 2018-05-27 22:53:06 UTC (rev 10057)
@@ -0,0 +1,618 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Oleksandr Rybalko under sponsorship
+ * from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/dev/uart/uart_dev_imx.c 283327 2015-05-23 20:54:25Z ian $");
+
+#include "opt_ddb.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/kdb.h>
+#include <machine/bus.h>
+#include <machine/fdt.h>
+
+#include <dev/uart/uart.h>
+#include <dev/uart/uart_cpu.h>
+#include <dev/uart/uart_cpu_fdt.h>
+#include <dev/uart/uart_bus.h>
+#include <dev/uart/uart_dev_imx.h>
+#include "uart_if.h"
+
+#include <arm/freescale/imx/imx_ccmvar.h>
+
+/*
+ * The hardare FIFOs are 32 bytes. We want an interrupt when there are 24 bytes
+ * available to read or space for 24 more bytes to write. While 8 bytes of
+ * slack before over/underrun might seem excessive, the hardware can run at
+ * 5mbps, which means 2uS per char, so at full speed 8 bytes provides only 16uS
+ * to get into the interrupt handler and service the fifo.
+ */
+#define IMX_FIFOSZ 32
+#define IMX_RXFIFO_LEVEL 24
+#define IMX_TXFIFO_LEVEL 24
+
+/*
+ * Low-level UART interface.
+ */
+static int imx_uart_probe(struct uart_bas *bas);
+static void imx_uart_init(struct uart_bas *bas, int, int, int, int);
+static void imx_uart_term(struct uart_bas *bas);
+static void imx_uart_putc(struct uart_bas *bas, int);
+static int imx_uart_rxready(struct uart_bas *bas);
+static int imx_uart_getc(struct uart_bas *bas, struct mtx *);
+
+static struct uart_ops uart_imx_uart_ops = {
+ .probe = imx_uart_probe,
+ .init = imx_uart_init,
+ .term = imx_uart_term,
+ .putc = imx_uart_putc,
+ .rxready = imx_uart_rxready,
+ .getc = imx_uart_getc,
+};
+
+#if 0 /* Handy when debugging. */
+static void
+dumpregs(struct uart_bas *bas, const char * msg)
+{
+
+ if (!bootverbose)
+ return;
+ printf("%s bsh 0x%08lx UCR1 0x%08x UCR2 0x%08x "
+ "UCR3 0x%08x UCR4 0x%08x USR1 0x%08x USR2 0x%08x\n",
+ msg, bas->bsh,
+ GETREG(bas, REG(UCR1)), GETREG(bas, REG(UCR2)),
+ GETREG(bas, REG(UCR3)), GETREG(bas, REG(UCR4)),
+ GETREG(bas, REG(USR1)), GETREG(bas, REG(USR2)));
+}
+#endif
+
+static int
+imx_uart_probe(struct uart_bas *bas)
+{
+
+ return (0);
+}
+
+static u_int
+imx_uart_getbaud(struct uart_bas *bas)
+{
+ uint32_t rate, ubir, ubmr;
+ u_int baud, blo, bhi, i;
+ static const u_int predivs[] = {6, 5, 4, 3, 2, 1, 7, 1};
+ static const u_int std_rates[] = {
+ 9600, 14400, 19200, 38400, 57600, 115200, 230400, 460800, 921600
+ };
+
+ /*
+ * Get the baud rate the hardware is programmed for, then search the
+ * table of standard baud rates for a number that's within 3% of the
+ * actual rate the hardware is programmed for. It's more comforting to
+ * see that your console is running at 115200 than 114942. Note that
+ * here we cannot make a simplifying assumption that the predivider and
+ * numerator are 1 (like we do when setting the baud rate), because we
+ * don't know what u-boot might have set up.
+ */
+ i = (GETREG(bas, REG(UFCR)) & IMXUART_UFCR_RFDIV_MASK) >>
+ IMXUART_UFCR_RFDIV_SHIFT;
+ rate = imx_ccm_uart_hz() / predivs[i];
+ ubir = GETREG(bas, REG(UBIR)) + 1;
+ ubmr = GETREG(bas, REG(UBMR)) + 1;
+ baud = ((rate / 16 ) * ubir) / ubmr;
+
+ blo = (baud * 100) / 103;
+ bhi = (baud * 100) / 97;
+ for (i = 0; i < nitems(std_rates); i++) {
+ rate = std_rates[i];
+ if (rate >= blo && rate <= bhi) {
+ baud = rate;
+ break;
+ }
+ }
+
+ return (baud);
+}
+
+static void
+imx_uart_init(struct uart_bas *bas, int baudrate, int databits,
+ int stopbits, int parity)
+{
+ uint32_t baseclk, reg;
+
+ /* Enable the device and the RX/TX channels. */
+ SET(bas, REG(UCR1), FLD(UCR1, UARTEN));
+ SET(bas, REG(UCR2), FLD(UCR2, RXEN) | FLD(UCR2, TXEN));
+
+ if (databits == 7)
+ DIS(bas, UCR2, WS);
+ else
+ ENA(bas, UCR2, WS);
+
+ if (stopbits == 2)
+ ENA(bas, UCR2, STPB);
+ else
+ DIS(bas, UCR2, STPB);
+
+ switch (parity) {
+ case UART_PARITY_ODD:
+ DIS(bas, UCR2, PROE);
+ ENA(bas, UCR2, PREN);
+ break;
+ case UART_PARITY_EVEN:
+ ENA(bas, UCR2, PROE);
+ ENA(bas, UCR2, PREN);
+ break;
+ case UART_PARITY_MARK:
+ case UART_PARITY_SPACE:
+ /* FALLTHROUGH: Hardware doesn't support mark/space. */
+ case UART_PARITY_NONE:
+ default:
+ DIS(bas, UCR2, PREN);
+ break;
+ }
+
+ /*
+ * The hardware has an extremely flexible baud clock: it allows setting
+ * both the numerator and denominator of the divider, as well as a
+ * separate pre-divider. We simplify the problem of coming up with a
+ * workable pair of numbers by assuming a pre-divider and numerator of
+ * one because our base clock is so fast we can reach virtually any
+ * reasonable speed with a simple divisor. The numerator value actually
+ * includes the 16x over-sampling (so a value of 16 means divide by 1);
+ * the register value is the numerator-1, so we have a hard-coded 15.
+ * Note that a quirk of the hardware requires that both UBIR and UBMR be
+ * set back to back in order for the change to take effect.
+ */
+ if (baudrate > 0) {
+ baseclk = imx_ccm_uart_hz();
+ reg = GETREG(bas, REG(UFCR));
+ reg = (reg & ~IMXUART_UFCR_RFDIV_MASK) | IMXUART_UFCR_RFDIV_DIV1;
+ SETREG(bas, REG(UFCR), reg);
+ SETREG(bas, REG(UBIR), 15);
+ SETREG(bas, REG(UBMR), (baseclk / baudrate) - 1);
+ }
+
+ /*
+ * Program the tx lowater and rx hiwater levels at which fifo-service
+ * interrupts are signaled. The tx value is interpetted as "when there
+ * are only this many bytes remaining" (not "this many free").
+ */
+ reg = GETREG(bas, REG(UFCR));
+ reg &= ~(IMXUART_UFCR_TXTL_MASK | IMXUART_UFCR_RXTL_MASK);
+ reg |= (IMX_FIFOSZ - IMX_TXFIFO_LEVEL) << IMXUART_UFCR_TXTL_SHIFT;
+ reg |= IMX_RXFIFO_LEVEL << IMXUART_UFCR_RXTL_SHIFT;
+ SETREG(bas, REG(UFCR), reg);
+}
+
+static void
+imx_uart_term(struct uart_bas *bas)
+{
+
+}
+
+static void
+imx_uart_putc(struct uart_bas *bas, int c)
+{
+
+ while (!(IS(bas, USR1, TRDY)))
+ ;
+ SETREG(bas, REG(UTXD), c);
+}
+
+static int
+imx_uart_rxready(struct uart_bas *bas)
+{
+
+ return ((IS(bas, USR2, RDR)) ? 1 : 0);
+}
+
+static int
+imx_uart_getc(struct uart_bas *bas, struct mtx *hwmtx)
+{
+ int c;
+
+ uart_lock(hwmtx);
+ while (!(IS(bas, USR2, RDR)))
+ ;
+
+ c = GETREG(bas, REG(URXD));
+ uart_unlock(hwmtx);
+#if defined(KDB)
+ if (c & FLD(URXD, BRK)) {
+ if (kdb_break())
+ return (0);
+ }
+#endif
+ return (c & 0xff);
+}
+
+/*
+ * High-level UART interface.
+ */
+struct imx_uart_softc {
+ struct uart_softc base;
+};
+
+static int imx_uart_bus_attach(struct uart_softc *);
+static int imx_uart_bus_detach(struct uart_softc *);
+static int imx_uart_bus_flush(struct uart_softc *, int);
+static int imx_uart_bus_getsig(struct uart_softc *);
+static int imx_uart_bus_ioctl(struct uart_softc *, int, intptr_t);
+static int imx_uart_bus_ipend(struct uart_softc *);
+static int imx_uart_bus_param(struct uart_softc *, int, int, int, int);
+static int imx_uart_bus_probe(struct uart_softc *);
+static int imx_uart_bus_receive(struct uart_softc *);
+static int imx_uart_bus_setsig(struct uart_softc *, int);
+static int imx_uart_bus_transmit(struct uart_softc *);
+static void imx_uart_bus_grab(struct uart_softc *);
+static void imx_uart_bus_ungrab(struct uart_softc *);
+
+static kobj_method_t imx_uart_methods[] = {
+ KOBJMETHOD(uart_attach, imx_uart_bus_attach),
+ KOBJMETHOD(uart_detach, imx_uart_bus_detach),
+ KOBJMETHOD(uart_flush, imx_uart_bus_flush),
+ KOBJMETHOD(uart_getsig, imx_uart_bus_getsig),
+ KOBJMETHOD(uart_ioctl, imx_uart_bus_ioctl),
+ KOBJMETHOD(uart_ipend, imx_uart_bus_ipend),
+ KOBJMETHOD(uart_param, imx_uart_bus_param),
+ KOBJMETHOD(uart_probe, imx_uart_bus_probe),
+ KOBJMETHOD(uart_receive, imx_uart_bus_receive),
+ KOBJMETHOD(uart_setsig, imx_uart_bus_setsig),
+ KOBJMETHOD(uart_transmit, imx_uart_bus_transmit),
+ KOBJMETHOD(uart_grab, imx_uart_bus_grab),
+ KOBJMETHOD(uart_ungrab, imx_uart_bus_ungrab),
+ { 0, 0 }
+};
+
+static struct uart_class uart_imx_class = {
+ "imx",
+ imx_uart_methods,
+ sizeof(struct imx_uart_softc),
+ .uc_ops = &uart_imx_uart_ops,
+ .uc_range = 0x100,
+ .uc_rclk = 24000000 /* TODO: get value from CCM */
+};
+
+static struct ofw_compat_data compat_data[] = {
+ {"fsl,imx6q-uart", (uintptr_t)&uart_imx_class},
+ {"fsl,imx53-uart", (uintptr_t)&uart_imx_class},
+ {"fsl,imx51-uart", (uintptr_t)&uart_imx_class},
+ {"fsl,imx31-uart", (uintptr_t)&uart_imx_class},
+ {"fsl,imx27-uart", (uintptr_t)&uart_imx_class},
+ {"fsl,imx25-uart", (uintptr_t)&uart_imx_class},
+ {"fsl,imx21-uart", (uintptr_t)&uart_imx_class},
+ {NULL, (uintptr_t)NULL},
+};
+UART_FDT_CLASS_AND_DEVICE(compat_data);
+
+#define SIGCHG(c, i, s, d) \
+ if (c) { \
+ i |= (i & s) ? s : s | d; \
+ } else { \
+ i = (i & s) ? (i & ~s) | d : i; \
+ }
+
+static int
+imx_uart_bus_attach(struct uart_softc *sc)
+{
+ struct uart_bas *bas;
+ struct uart_devinfo *di;
+
+ bas = &sc->sc_bas;
+ if (sc->sc_sysdev != NULL) {
+ di = sc->sc_sysdev;
+ imx_uart_init(bas, di->baudrate, di->databits, di->stopbits,
+ di->parity);
+ } else {
+ imx_uart_init(bas, 115200, 8, 1, 0);
+ }
+
+ (void)imx_uart_bus_getsig(sc);
+
+ /* Clear all pending interrupts. */
+ SETREG(bas, REG(USR1), 0xffff);
+ SETREG(bas, REG(USR2), 0xffff);
+
+ DIS(bas, UCR4, DREN);
+ ENA(bas, UCR1, RRDYEN);
+ DIS(bas, UCR1, IDEN);
+ DIS(bas, UCR3, RXDSEN);
+ ENA(bas, UCR2, ATEN);
+ DIS(bas, UCR1, TXMPTYEN);
+ DIS(bas, UCR1, TRDYEN);
+ DIS(bas, UCR4, TCEN);
+ DIS(bas, UCR4, OREN);
+ ENA(bas, UCR4, BKEN);
+ DIS(bas, UCR4, WKEN);
+ DIS(bas, UCR1, ADEN);
+ DIS(bas, UCR3, ACIEN);
+ DIS(bas, UCR2, ESCI);
+ DIS(bas, UCR4, ENIRI);
+ DIS(bas, UCR3, AIRINTEN);
+ DIS(bas, UCR3, AWAKEN);
+ DIS(bas, UCR3, FRAERREN);
+ DIS(bas, UCR3, PARERREN);
+ DIS(bas, UCR1, RTSDEN);
+ DIS(bas, UCR2, RTSEN);
+ DIS(bas, UCR3, DTREN);
+ DIS(bas, UCR3, RI);
+ DIS(bas, UCR3, DCD);
+ DIS(bas, UCR3, DTRDEN);
+ ENA(bas, UCR2, IRTS);
+ ENA(bas, UCR3, RXDMUXSEL);
+
+ return (0);
+}
+
+static int
+imx_uart_bus_detach(struct uart_softc *sc)
+{
+
+ SETREG(&sc->sc_bas, REG(UCR4), 0);
+
+ return (0);
+}
+
+static int
+imx_uart_bus_flush(struct uart_softc *sc, int what)
+{
+
+ /* TODO */
+ return (0);
+}
+
+static int
+imx_uart_bus_getsig(struct uart_softc *sc)
+{
+ uint32_t new, old, sig;
+ uint8_t bes;
+
+ do {
+ old = sc->sc_hwsig;
+ sig = old;
+ uart_lock(sc->sc_hwmtx);
+ bes = GETREG(&sc->sc_bas, REG(USR2));
+ uart_unlock(sc->sc_hwmtx);
+ /* XXX: chip can show delta */
+ SIGCHG(bes & FLD(USR2, DCDIN), sig, SER_DCD, SER_DDCD);
+ new = sig & ~SER_MASK_DELTA;
+ } while (!atomic_cmpset_32(&sc->sc_hwsig, old, new));
+
+ return (sig);
+}
+
+static int
+imx_uart_bus_ioctl(struct uart_softc *sc, int request, intptr_t data)
+{
+ struct uart_bas *bas;
+ int error;
+
+ bas = &sc->sc_bas;
+ error = 0;
+ uart_lock(sc->sc_hwmtx);
+ switch (request) {
+ case UART_IOCTL_BREAK:
+ /* TODO */
+ break;
+ case UART_IOCTL_BAUD:
+ *(u_int*)data = imx_uart_getbaud(bas);
+ break;
+ default:
+ error = EINVAL;
+ break;
+ }
+ uart_unlock(sc->sc_hwmtx);
+
+ return (error);
+}
+
+static int
+imx_uart_bus_ipend(struct uart_softc *sc)
+{
+ struct uart_bas *bas;
+ int ipend;
+ uint32_t usr1, usr2;
+ uint32_t ucr1, ucr2, ucr4;
+
+ bas = &sc->sc_bas;
+ ipend = 0;
+
+ uart_lock(sc->sc_hwmtx);
+
+ /* Read pending interrupts */
+ usr1 = GETREG(bas, REG(USR1));
+ usr2 = GETREG(bas, REG(USR2));
+ /* ACK interrupts */
+ SETREG(bas, REG(USR1), usr1);
+ SETREG(bas, REG(USR2), usr2);
+
+ ucr1 = GETREG(bas, REG(UCR1));
+ ucr2 = GETREG(bas, REG(UCR2));
+ ucr4 = GETREG(bas, REG(UCR4));
+
+ /* If we have reached tx low-water, we can tx some more now. */
+ if ((usr1 & FLD(USR1, TRDY)) && (ucr1 & FLD(UCR1, TRDYEN))) {
+ DIS(bas, UCR1, TRDYEN);
+ ipend |= SER_INT_TXIDLE;
+ }
+
+ /*
+ * If we have reached the rx high-water, or if there are bytes in the rx
+ * fifo and no new data has arrived for 8 character periods (aging
+ * timer), we have input data to process.
+ */
+ if (((usr1 & FLD(USR1, RRDY)) && (ucr1 & FLD(UCR1, RRDYEN))) ||
+ ((usr1 & FLD(USR1, AGTIM)) && (ucr2 & FLD(UCR2, ATEN)))) {
+ DIS(bas, UCR1, RRDYEN);
+ DIS(bas, UCR2, ATEN);
+ ipend |= SER_INT_RXREADY;
+ }
+
+ /* A break can come in at any time, it never gets disabled. */
+ if ((usr2 & FLD(USR2, BRCD)) && (ucr4 & FLD(UCR4, BKEN)))
+ ipend |= SER_INT_BREAK;
+
+ uart_unlock(sc->sc_hwmtx);
+
+ return (ipend);
+}
+
+static int
+imx_uart_bus_param(struct uart_softc *sc, int baudrate, int databits,
+ int stopbits, int parity)
+{
+
+ uart_lock(sc->sc_hwmtx);
+ imx_uart_init(&sc->sc_bas, baudrate, databits, stopbits, parity);
+ uart_unlock(sc->sc_hwmtx);
+ return (0);
+}
+
+static int
+imx_uart_bus_probe(struct uart_softc *sc)
+{
+ int error;
+
+ error = imx_uart_probe(&sc->sc_bas);
+ if (error)
+ return (error);
+
+ /*
+ * On input we can read up to the full fifo size at once. On output, we
+ * want to write only as much as the programmed tx low water level,
+ * because that's all we can be certain we have room for in the fifo
+ * when we get a tx-ready interrupt.
+ */
+ sc->sc_rxfifosz = IMX_FIFOSZ;
+ sc->sc_txfifosz = IMX_TXFIFO_LEVEL;
+
+ device_set_desc(sc->sc_dev, "Freescale i.MX UART");
+ return (0);
+}
+
+static int
+imx_uart_bus_receive(struct uart_softc *sc)
+{
+ struct uart_bas *bas;
+ int xc, out;
+
+ bas = &sc->sc_bas;
+ uart_lock(sc->sc_hwmtx);
+
+ /*
+ * Empty the rx fifo. We get the RRDY interrupt when IMX_RXFIFO_LEVEL
+ * (the rx high-water level) is reached, but we set sc_rxfifosz to the
+ * full hardware fifo size, so we can safely process however much is
+ * there, not just the highwater size.
+ */
+ while (IS(bas, USR2, RDR)) {
+ if (uart_rx_full(sc)) {
+ /* No space left in input buffer */
+ sc->sc_rxbuf[sc->sc_rxput] = UART_STAT_OVERRUN;
+ break;
+ }
+ xc = GETREG(bas, REG(URXD));
+ out = xc & 0x000000ff;
+ if (xc & FLD(URXD, FRMERR))
+ out |= UART_STAT_FRAMERR;
+ if (xc & FLD(URXD, PRERR))
+ out |= UART_STAT_PARERR;
+ if (xc & FLD(URXD, OVRRUN))
+ out |= UART_STAT_OVERRUN;
+ if (xc & FLD(URXD, BRK))
+ out |= UART_STAT_BREAK;
+
+ uart_rx_put(sc, out);
+ }
+ ENA(bas, UCR1, RRDYEN);
+ ENA(bas, UCR2, ATEN);
+
+ uart_unlock(sc->sc_hwmtx);
+ return (0);
+}
+
+static int
+imx_uart_bus_setsig(struct uart_softc *sc, int sig)
+{
+
+ return (0);
+}
+
+static int
+imx_uart_bus_transmit(struct uart_softc *sc)
+{
+ struct uart_bas *bas = &sc->sc_bas;
+ int i;
+
+ bas = &sc->sc_bas;
+ uart_lock(sc->sc_hwmtx);
+
+ /*
+ * Fill the tx fifo. The uart core puts at most IMX_TXFIFO_LEVEL bytes
+ * into the txbuf (because that's what sc_txfifosz is set to), and
+ * because we got the TRDY (low-water reached) interrupt we know at
+ * least that much space is available in the fifo.
+ */
+ for (i = 0; i < sc->sc_txdatasz; i++) {
+ SETREG(bas, REG(UTXD), sc->sc_txbuf[i] & 0xff);
+ }
+ sc->sc_txbusy = 1;
+ ENA(bas, UCR1, TRDYEN);
+
+ uart_unlock(sc->sc_hwmtx);
+
+ return (0);
+}
+
+static void
+imx_uart_bus_grab(struct uart_softc *sc)
+{
+ struct uart_bas *bas = &sc->sc_bas;
+
+ bas = &sc->sc_bas;
+ uart_lock(sc->sc_hwmtx);
+ DIS(bas, UCR1, RRDYEN);
+ DIS(bas, UCR2, ATEN);
+ uart_unlock(sc->sc_hwmtx);
+}
+
+static void
+imx_uart_bus_ungrab(struct uart_softc *sc)
+{
+ struct uart_bas *bas = &sc->sc_bas;
+
+ bas = &sc->sc_bas;
+ uart_lock(sc->sc_hwmtx);
+ ENA(bas, UCR1, RRDYEN);
+ ENA(bas, UCR2, ATEN);
+ uart_unlock(sc->sc_hwmtx);
+}
Property changes on: trunk/sys/dev/uart/uart_dev_imx.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/dev/uart/uart_dev_imx.h
===================================================================
--- trunk/sys/dev/uart/uart_dev_imx.h (rev 0)
+++ trunk/sys/dev/uart/uart_dev_imx.h 2018-05-27 22:53:06 UTC (rev 10057)
@@ -0,0 +1,223 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Oleksandr Rybalko under sponsorship
+ * from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/dev/uart/uart_dev_imx.h 266372 2014-05-17 22:31:40Z ian $
+ */
+
+#ifndef _UART_DEV_IMX5XX_H
+#define _UART_DEV_IMX5XX_H
+
+#define IMXUART_URXD_REG 0x0000 /* UART Receiver Register */
+#define IMXUART_URXD_CHARRDY (1 << 15)
+#define IMXUART_URXD_ERR (1 << 14)
+#define IMXUART_URXD_OVRRUN (1 << 13)
+#define IMXUART_URXD_FRMERR (1 << 12)
+#define IMXUART_URXD_BRK (1 << 11)
+#define IMXUART_URXD_PRERR (1 << 10)
+#define IMXUART_URXD_RX_DATA_MASK 0xff
+
+#define IMXUART_UTXD_REG 0x0040 /* UART Transmitter Register */
+#define IMXUART_UTXD_TX_DATA_MASK 0xff
+
+#define IMXUART_UCR1_REG 0x0080 /* UART Control Register 1 */
+#define IMXUART_UCR1_ADEN (1 << 15)
+#define IMXUART_UCR1_ADBR (1 << 14)
+#define IMXUART_UCR1_TRDYEN (1 << 13)
+#define IMXUART_UCR1_IDEN (1 << 12)
+#define IMXUART_UCR1_ICD_MASK (3 << 10)
+#define IMXUART_UCR1_ICD_IDLE4 (0 << 10)
+#define IMXUART_UCR1_ICD_IDLE8 (1 << 10)
+#define IMXUART_UCR1_ICD_IDLE16 (2 << 10)
+#define IMXUART_UCR1_ICD_IDLE32 (3 << 10)
+#define IMXUART_UCR1_RRDYEN (1 << 9)
+#define IMXUART_UCR1_RXDMAEN (1 << 8)
+#define IMXUART_UCR1_IREN (1 << 7)
+#define IMXUART_UCR1_TXMPTYEN (1 << 6)
+#define IMXUART_UCR1_RTSDEN (1 << 5)
+#define IMXUART_UCR1_SNDBRK (1 << 4)
+#define IMXUART_UCR1_TXDMAEN (1 << 3)
+#define IMXUART_UCR1_ATDMAEN (1 << 2)
+#define IMXUART_UCR1_DOZE (1 << 1)
+#define IMXUART_UCR1_UARTEN (1 << 0)
+
+#define IMXUART_UCR2_REG 0x0084 /* UART Control Register 2 */
+#define IMXUART_UCR2_ESCI (1 << 15)
+#define IMXUART_UCR2_IRTS (1 << 14)
+#define IMXUART_UCR2_CTSC (1 << 13)
+#define IMXUART_UCR2_CTS (1 << 12)
+#define IMXUART_UCR2_ESCEN (1 << 11)
+#define IMXUART_UCR2_RTEC_MASK (3 << 9)
+#define IMXUART_UCR2_RTEC_REDGE (0 << 9)
+#define IMXUART_UCR2_RTEC_FEDGE (1 << 9)
+#define IMXUART_UCR2_RTEC_EDGE (2 << 9)
+#define IMXUART_UCR2_PREN (1 << 8)
+#define IMXUART_UCR2_PROE (1 << 7)
+#define IMXUART_UCR2_STPB (1 << 6)
+#define IMXUART_UCR2_WS (1 << 5)
+#define IMXUART_UCR2_RTSEN (1 << 4)
+#define IMXUART_UCR2_ATEN (1 << 3)
+#define IMXUART_UCR2_TXEN (1 << 2)
+#define IMXUART_UCR2_RXEN (1 << 1)
+#define IMXUART_UCR2_N_SRST (1 << 0)
+
+#define IMXUART_UCR3_REG 0x0088 /* UART Control Register 3 */
+#define IMXUART_UCR3_DPEC_MASK (3 << 14)
+#define IMXUART_UCR3_DPEC_REDGE (0 << 14)
+#define IMXUART_UCR3_DPEC_FEDGE (1 << 14)
+#define IMXUART_UCR3_DPEC_EDGE (2 << 14)
+#define IMXUART_UCR3_DTREN (1 << 13)
+#define IMXUART_UCR3_PARERREN (1 << 12)
+#define IMXUART_UCR3_FRAERREN (1 << 11)
+#define IMXUART_UCR3_DSR (1 << 10)
+#define IMXUART_UCR3_DCD (1 << 9)
+#define IMXUART_UCR3_RI (1 << 8)
+#define IMXUART_UCR3_ADNIMP (1 << 7)
+#define IMXUART_UCR3_RXDSEN (1 << 6)
+#define IMXUART_UCR3_AIRINTEN (1 << 5)
+#define IMXUART_UCR3_AWAKEN (1 << 4)
+#define IMXUART_UCR3_DTRDEN (1 << 3)
+#define IMXUART_UCR3_RXDMUXSEL (1 << 2)
+#define IMXUART_UCR3_INVT (1 << 1)
+#define IMXUART_UCR3_ACIEN (1 << 0)
+
+#define IMXUART_UCR4_REG 0x008c /* UART Control Register 4 */
+#define IMXUART_UCR4_CTSTL_MASK (0x3f << 10)
+#define IMXUART_UCR4_CTSTL_SHIFT 10
+#define IMXUART_UCR4_INVR (1 << 9)
+#define IMXUART_UCR4_ENIRI (1 << 8)
+#define IMXUART_UCR4_WKEN (1 << 7)
+#define IMXUART_UCR4_IDDMAEN (1 << 6)
+#define IMXUART_UCR4_IRSC (1 << 5)
+#define IMXUART_UCR4_LPBYP (1 << 4)
+#define IMXUART_UCR4_TCEN (1 << 3)
+#define IMXUART_UCR4_BKEN (1 << 2)
+#define IMXUART_UCR4_OREN (1 << 1)
+#define IMXUART_UCR4_DREN (1 << 0)
+
+#define IMXUART_UFCR_REG 0x0090 /* UART FIFO Control Register */
+#define IMXUART_UFCR_TXTL_MASK (0x3f << 10)
+#define IMXUART_UFCR_TXTL_SHIFT 10
+#define IMXUART_UFCR_RFDIV_MASK (0x07 << 7)
+#define IMXUART_UFCR_RFDIV_SHIFT 7
+#define IMXUART_UFCR_RFDIV_SHIFT 7
+#define IMXUART_UFCR_RFDIV_DIV6 (0 << 7)
+#define IMXUART_UFCR_RFDIV_DIV5 (1 << 7)
+#define IMXUART_UFCR_RFDIV_DIV4 (2 << 7)
+#define IMXUART_UFCR_RFDIV_DIV3 (3 << 7)
+#define IMXUART_UFCR_RFDIV_DIV2 (4 << 7)
+#define IMXUART_UFCR_RFDIV_DIV1 (5 << 7)
+#define IMXUART_UFCR_RFDIV_DIV7 (6 << 7)
+#define IMXUART_UFCR_DCEDTE (1 << 6)
+#define IMXUART_UFCR_RXTL_MASK 0x0000003f
+#define IMXUART_UFCR_RXTL_SHIFT 0
+
+#define IMXUART_USR1_REG 0x0094 /* UART Status Register 1 */
+#define IMXUART_USR1_PARITYERR (1 << 15)
+#define IMXUART_USR1_RTSS (1 << 14)
+#define IMXUART_USR1_TRDY (1 << 13)
+#define IMXUART_USR1_RTSD (1 << 12)
+#define IMXUART_USR1_ESCF (1 << 11)
+#define IMXUART_USR1_FRAMERR (1 << 10)
+#define IMXUART_USR1_RRDY (1 << 9)
+#define IMXUART_USR1_AGTIM (1 << 8)
+#define IMXUART_USR1_DTRD (1 << 7)
+#define IMXUART_USR1_RXDS (1 << 6)
+#define IMXUART_USR1_AIRINT (1 << 5)
+#define IMXUART_USR1_AWAKE (1 << 4)
+/* 6040 5008 XXX */
+
+#define IMXUART_USR2_REG 0x0098 /* UART Status Register 2 */
+#define IMXUART_USR2_ADET (1 << 15)
+#define IMXUART_USR2_TXFE (1 << 14)
+#define IMXUART_USR2_DTRF (1 << 13)
+#define IMXUART_USR2_IDLE (1 << 12)
+#define IMXUART_USR2_ACST (1 << 11)
+#define IMXUART_USR2_RIDELT (1 << 10)
+#define IMXUART_USR2_RIIN (1 << 9)
+#define IMXUART_USR2_IRINT (1 << 8)
+#define IMXUART_USR2_WAKE (1 << 7)
+#define IMXUART_USR2_DCDDELT (1 << 6)
+#define IMXUART_USR2_DCDIN (1 << 5)
+#define IMXUART_USR2_RTSF (1 << 4)
+#define IMXUART_USR2_TXDC (1 << 3)
+#define IMXUART_USR2_BRCD (1 << 2)
+#define IMXUART_USR2_ORE (1 << 1)
+#define IMXUART_USR2_RDR (1 << 0)
+
+#define IMXUART_UESC_REG 0x009c /* UART Escape Character Register */
+#define IMXUART_UESC_ESC_CHAR_MASK 0x000000ff
+
+#define IMXUART_UTIM_REG 0x00a0 /* UART Escape Timer Register */
+#define IMXUART_UTIM_TIM_MASK 0x00000fff
+
+#define IMXUART_UBIR_REG 0x00a4 /* UART BRM Incremental Register */
+#define IMXUART_UBIR_INC_MASK 0x0000ffff
+
+#define IMXUART_UBMR_REG 0x00a8 /* UART BRM Modulator Register */
+#define IMXUART_UBMR_MOD_MASK 0x0000ffff
+
+#define IMXUART_UBRC_REG 0x00ac /* UART Baud Rate Count Register */
+#define IMXUART_UBRC_BCNT_MASK 0x0000ffff
+
+#define IMXUART_ONEMS_REG 0x00b0 /* UART One Millisecond Register */
+#define IMXUART_ONEMS_ONEMS_MASK 0x00ffffff
+
+#define IMXUART_UTS_REG 0x00b4 /* UART Test Register */
+#define IMXUART_UTS_FRCPERR (1 << 13)
+#define IMXUART_UTS_LOOP (1 << 12)
+#define IMXUART_UTS_DBGEN (1 << 11)
+#define IMXUART_UTS_LOOPIR (1 << 10)
+#define IMXUART_UTS_RXDBG (1 << 9)
+#define IMXUART_UTS_TXEMPTY (1 << 6)
+#define IMXUART_UTS_RXEMPTY (1 << 5)
+#define IMXUART_UTS_TXFULL (1 << 4)
+#define IMXUART_UTS_RXFULL (1 << 3)
+#define IMXUART_UTS_SOFTRST (1 << 0)
+
+#define REG(_r) IMXUART_ ## _r ## _REG
+#define FLD(_r, _v) IMXUART_ ## _r ## _ ## _v
+
+#define GETREG(bas, reg) \
+ bus_space_read_4((bas)->bst, (bas)->bsh, (reg))
+#define SETREG(bas, reg, value) \
+ bus_space_write_4((bas)->bst, (bas)->bsh, (reg), (value))
+
+#define CLR(_bas, _r, _b) \
+ SETREG((_bas), (_r), GETREG((_bas), (_r)) & ~(_b))
+#define SET(_bas, _r, _b) \
+ SETREG((_bas), (_r), GETREG((_bas), (_r)) | (_b))
+#define IS_SET(_bas, _r, _b) \
+ ((GETREG((_bas), (_r)) & (_b)) ? 1 : 0)
+
+#define ENA(_bas, _r, _b) SET((_bas), REG(_r), FLD(_r, _b))
+#define DIS(_bas, _r, _b) CLR((_bas), REG(_r), FLD(_r, _b))
+#define IS(_bas, _r, _b) IS_SET((_bas), REG(_r), FLD(_r, _b))
+
+
+#endif /* _UART_DEV_IMX5XX_H */
Property changes on: trunk/sys/dev/uart/uart_dev_imx.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/dev/uart/uart_dev_lpc.c
===================================================================
--- trunk/sys/dev/uart/uart_dev_lpc.c (rev 0)
+++ trunk/sys/dev/uart/uart_dev_lpc.c 2018-05-27 22:53:06 UTC (rev 10057)
@@ -0,0 +1,935 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2003 Marcel Moolenaar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/dev/uart/uart_dev_lpc.c 283327 2015-05-23 20:54:25Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <machine/bus.h>
+#include <machine/fdt.h>
+
+#include <dev/uart/uart.h>
+#include <dev/uart/uart_cpu.h>
+#include <dev/uart/uart_cpu_fdt.h>
+#include <dev/uart/uart_bus.h>
+
+#include <dev/ic/ns16550.h>
+#include <arm/lpc/lpcreg.h>
+
+#include "uart_if.h"
+
+#define DEFAULT_RCLK (13 * 1000 * 1000)
+
+static bus_space_handle_t bsh_clkpwr;
+
+#define lpc_ns8250_get_clkreg(_bas, _reg) \
+ bus_space_read_4(fdtbus_bs_tag, bsh_clkpwr, (_reg))
+#define lpc_ns8250_set_clkreg(_bas, _reg, _val) \
+ bus_space_write_4(fdtbus_bs_tag, bsh_clkpwr, (_reg), (_val))
+
+/*
+ * Clear pending interrupts. THRE is cleared by reading IIR. Data
+ * that may have been received gets lost here.
+ */
+static void
+lpc_ns8250_clrint(struct uart_bas *bas)
+{
+ uint8_t iir, lsr;
+
+ iir = uart_getreg(bas, REG_IIR);
+ while ((iir & IIR_NOPEND) == 0) {
+ iir &= IIR_IMASK;
+ if (iir == IIR_RLS) {
+ lsr = uart_getreg(bas, REG_LSR);
+ if (lsr & (LSR_BI|LSR_FE|LSR_PE))
+ (void)uart_getreg(bas, REG_DATA);
+ } else if (iir == IIR_RXRDY || iir == IIR_RXTOUT)
+ (void)uart_getreg(bas, REG_DATA);
+ else if (iir == IIR_MLSC)
+ (void)uart_getreg(bas, REG_MSR);
+ uart_barrier(bas);
+ iir = uart_getreg(bas, REG_IIR);
+ }
+}
+
+static int
+lpc_ns8250_delay(struct uart_bas *bas)
+{
+ uint32_t uclk;
+ int x, y;
+
+ uclk = lpc_ns8250_get_clkreg(bas, LPC_CLKPWR_UART_U5CLK);
+
+ x = (uclk >> 8) & 0xff;
+ y = uclk & 0xff;
+
+ return (16000000 / (bas->rclk * x / y));
+}
+
+static void
+lpc_ns8250_divisor(int rclk, int baudrate, int *x, int *y)
+{
+
+ switch (baudrate) {
+ case 2400:
+ *x = 1;
+ *y = 255;
+ return;
+ case 4800:
+ *x = 1;
+ *y = 169;
+ return;
+ case 9600:
+ *x = 3;
+ *y = 254;
+ return;
+ case 19200:
+ *x = 3;
+ *y = 127;
+ return;
+ case 38400:
+ *x = 6;
+ *y = 127;
+ return;
+ case 57600:
+ *x = 9;
+ *y = 127;
+ return;
+ default:
+ case 115200:
+ *x = 19;
+ *y = 134;
+ return;
+ case 230400:
+ *x = 19;
+ *y = 67;
+ return;
+ case 460800:
+ *x = 38;
+ *y = 67;
+ return;
+ }
+}
+
+static int
+lpc_ns8250_drain(struct uart_bas *bas, int what)
+{
+ int delay, limit;
+
+ delay = lpc_ns8250_delay(bas);
+
+ if (what & UART_DRAIN_TRANSMITTER) {
+ /*
+ * Pick an arbitrary high limit to avoid getting stuck in
+ * an infinite loop when the hardware is broken. Make the
+ * limit high enough to handle large FIFOs.
+ */
+ limit = 10*1024;
+ while ((uart_getreg(bas, REG_LSR) & LSR_TEMT) == 0 && --limit)
+ DELAY(delay);
+ if (limit == 0) {
+ /* printf("lpc_ns8250: transmitter appears stuck... "); */
+ return (EIO);
+ }
+ }
+
+ if (what & UART_DRAIN_RECEIVER) {
+ /*
+ * Pick an arbitrary high limit to avoid getting stuck in
+ * an infinite loop when the hardware is broken. Make the
+ * limit high enough to handle large FIFOs and integrated
+ * UARTs. The HP rx2600 for example has 3 UARTs on the
+ * management board that tend to get a lot of data send
+ * to it when the UART is first activated.
+ */
+ limit=10*4096;
+ while ((uart_getreg(bas, REG_LSR) & LSR_RXRDY) && --limit) {
+ (void)uart_getreg(bas, REG_DATA);
+ uart_barrier(bas);
+ DELAY(delay << 2);
+ }
+ if (limit == 0) {
+ /* printf("lpc_ns8250: receiver appears broken... "); */
+ return (EIO);
+ }
+ }
+
+ return (0);
+}
+
+/*
+ * We can only flush UARTs with FIFOs. UARTs without FIFOs should be
+ * drained. WARNING: this function clobbers the FIFO setting!
+ */
+static void
+lpc_ns8250_flush(struct uart_bas *bas, int what)
+{
+ uint8_t fcr;
+
+ fcr = FCR_ENABLE;
+ if (what & UART_FLUSH_TRANSMITTER)
+ fcr |= FCR_XMT_RST;
+ if (what & UART_FLUSH_RECEIVER)
+ fcr |= FCR_RCV_RST;
+ uart_setreg(bas, REG_FCR, fcr);
+ uart_barrier(bas);
+}
+
+static int
+lpc_ns8250_param(struct uart_bas *bas, int baudrate, int databits, int stopbits,
+ int parity)
+{
+ int xdiv, ydiv;
+ uint8_t lcr;
+
+ lcr = 0;
+ if (databits >= 8)
+ lcr |= LCR_8BITS;
+ else if (databits == 7)
+ lcr |= LCR_7BITS;
+ else if (databits == 6)
+ lcr |= LCR_6BITS;
+ else
+ lcr |= LCR_5BITS;
+ if (stopbits > 1)
+ lcr |= LCR_STOPB;
+ lcr |= parity << 3;
+
+ /* Set baudrate. */
+ if (baudrate > 0) {
+ uart_setreg(bas, REG_LCR, lcr | LCR_DLAB);
+ uart_barrier(bas);
+ uart_setreg(bas, REG_DLL, 0x00);
+ uart_setreg(bas, REG_DLH, 0x00);
+ uart_barrier(bas);
+
+ lpc_ns8250_divisor(bas->rclk, baudrate, &xdiv, &ydiv);
+ lpc_ns8250_set_clkreg(bas,
+ LPC_CLKPWR_UART_U5CLK,
+ LPC_CLKPWR_UART_UCLK_X(xdiv) |
+ LPC_CLKPWR_UART_UCLK_Y(ydiv));
+ }
+
+ /* Set LCR and clear DLAB. */
+ uart_setreg(bas, REG_LCR, lcr);
+ uart_barrier(bas);
+ return (0);
+}
+
+/*
+ * Low-level UART interface.
+ */
+static int lpc_ns8250_probe(struct uart_bas *bas);
+static void lpc_ns8250_init(struct uart_bas *bas, int, int, int, int);
+static void lpc_ns8250_term(struct uart_bas *bas);
+static void lpc_ns8250_putc(struct uart_bas *bas, int);
+static int lpc_ns8250_rxready(struct uart_bas *bas);
+static int lpc_ns8250_getc(struct uart_bas *bas, struct mtx *);
+
+static struct uart_ops uart_lpc_ns8250_ops = {
+ .probe = lpc_ns8250_probe,
+ .init = lpc_ns8250_init,
+ .term = lpc_ns8250_term,
+ .putc = lpc_ns8250_putc,
+ .rxready = lpc_ns8250_rxready,
+ .getc = lpc_ns8250_getc,
+};
+
+static int
+lpc_ns8250_probe(struct uart_bas *bas)
+{
+#if 0
+ u_char val;
+
+ /* Check known 0 bits that don't depend on DLAB. */
+ val = uart_getreg(bas, REG_IIR);
+ if (val & 0x30)
+ return (ENXIO);
+ /*
+ * Bit 6 of the MCR (= 0x40) appears to be 1 for the Sun1699
+ * chip, but otherwise doesn't seem to have a function. In
+ * other words, uart(4) works regardless. Ignore that bit so
+ * the probe succeeds.
+ */
+ val = uart_getreg(bas, REG_MCR);
+ if (val & 0xa0)
+ return (ENXIO);
+#endif
+ return (0);
+}
+
+static void
+lpc_ns8250_init(struct uart_bas *bas, int baudrate, int databits, int stopbits,
+ int parity)
+{
+ u_char ier;
+ u_long clkmode;
+
+ /* Enable UART clock */
+ bus_space_map(fdtbus_bs_tag, LPC_CLKPWR_PHYS_BASE, LPC_CLKPWR_SIZE, 0,
+ &bsh_clkpwr);
+ clkmode = lpc_ns8250_get_clkreg(bas, LPC_UART_CLKMODE);
+ lpc_ns8250_set_clkreg(bas, LPC_UART_CLKMODE, clkmode |
+ LPC_UART_CLKMODE_UART5(1));
+
+#if 0
+ /* Work around H/W bug */
+ uart_setreg(bas, REG_DATA, 0x00);
+#endif
+ if (bas->rclk == 0)
+ bas->rclk = DEFAULT_RCLK;
+ lpc_ns8250_param(bas, baudrate, databits, stopbits, parity);
+
+ /* Disable all interrupt sources. */
+ /*
+ * We use 0xe0 instead of 0xf0 as the mask because the XScale PXA
+ * UARTs split the receive time-out interrupt bit out separately as
+ * 0x10. This gets handled by ier_mask and ier_rxbits below.
+ */
+ ier = uart_getreg(bas, REG_IER) & 0xe0;
+ uart_setreg(bas, REG_IER, ier);
+ uart_barrier(bas);
+
+ /* Disable the FIFO (if present). */
+ uart_setreg(bas, REG_FCR, 0);
+ uart_barrier(bas);
+
+ /* Set RTS & DTR. */
+ uart_setreg(bas, REG_MCR, MCR_IE | MCR_RTS | MCR_DTR);
+ uart_barrier(bas);
+
+ lpc_ns8250_clrint(bas);
+}
+
+static void
+lpc_ns8250_term(struct uart_bas *bas)
+{
+
+ /* Clear RTS & DTR. */
+ uart_setreg(bas, REG_MCR, MCR_IE);
+ uart_barrier(bas);
+}
+
+static void
+lpc_ns8250_putc(struct uart_bas *bas, int c)
+{
+ int limit;
+
+ limit = 250000;
+ while ((uart_getreg(bas, REG_LSR) & LSR_THRE) == 0 && --limit)
+ DELAY(4);
+ uart_setreg(bas, REG_DATA, c);
+ uart_barrier(bas);
+ limit = 250000;
+ while ((uart_getreg(bas, REG_LSR) & LSR_TEMT) == 0 && --limit)
+ DELAY(4);
+}
+
+static int
+lpc_ns8250_rxready(struct uart_bas *bas)
+{
+
+ return ((uart_getreg(bas, REG_LSR) & LSR_RXRDY) != 0 ? 1 : 0);
+}
+
+static int
+lpc_ns8250_getc(struct uart_bas *bas, struct mtx *hwmtx)
+{
+ int c;
+
+ uart_lock(hwmtx);
+
+ while ((uart_getreg(bas, REG_LSR) & LSR_RXRDY) == 0) {
+ uart_unlock(hwmtx);
+ DELAY(4);
+ uart_lock(hwmtx);
+ }
+
+ c = uart_getreg(bas, REG_DATA);
+
+ uart_unlock(hwmtx);
+
+ return (c);
+}
+
+/*
+ * High-level UART interface.
+ */
+struct lpc_ns8250_softc {
+ struct uart_softc base;
+ uint8_t fcr;
+ uint8_t ier;
+ uint8_t mcr;
+
+ uint8_t ier_mask;
+ uint8_t ier_rxbits;
+};
+
+static int lpc_ns8250_bus_attach(struct uart_softc *);
+static int lpc_ns8250_bus_detach(struct uart_softc *);
+static int lpc_ns8250_bus_flush(struct uart_softc *, int);
+static int lpc_ns8250_bus_getsig(struct uart_softc *);
+static int lpc_ns8250_bus_ioctl(struct uart_softc *, int, intptr_t);
+static int lpc_ns8250_bus_ipend(struct uart_softc *);
+static int lpc_ns8250_bus_param(struct uart_softc *, int, int, int, int);
+static int lpc_ns8250_bus_probe(struct uart_softc *);
+static int lpc_ns8250_bus_receive(struct uart_softc *);
+static int lpc_ns8250_bus_setsig(struct uart_softc *, int);
+static int lpc_ns8250_bus_transmit(struct uart_softc *);
+static void lpc_ns8250_bus_grab(struct uart_softc *);
+static void lpc_ns8250_bus_ungrab(struct uart_softc *);
+
+static kobj_method_t lpc_ns8250_methods[] = {
+ KOBJMETHOD(uart_attach, lpc_ns8250_bus_attach),
+ KOBJMETHOD(uart_detach, lpc_ns8250_bus_detach),
+ KOBJMETHOD(uart_flush, lpc_ns8250_bus_flush),
+ KOBJMETHOD(uart_getsig, lpc_ns8250_bus_getsig),
+ KOBJMETHOD(uart_ioctl, lpc_ns8250_bus_ioctl),
+ KOBJMETHOD(uart_ipend, lpc_ns8250_bus_ipend),
+ KOBJMETHOD(uart_param, lpc_ns8250_bus_param),
+ KOBJMETHOD(uart_probe, lpc_ns8250_bus_probe),
+ KOBJMETHOD(uart_receive, lpc_ns8250_bus_receive),
+ KOBJMETHOD(uart_setsig, lpc_ns8250_bus_setsig),
+ KOBJMETHOD(uart_transmit, lpc_ns8250_bus_transmit),
+ KOBJMETHOD(uart_grab, lpc_ns8250_bus_grab),
+ KOBJMETHOD(uart_ungrab, lpc_ns8250_bus_ungrab),
+ { 0, 0 }
+};
+
+static struct uart_class uart_lpc_class = {
+ "lpc_ns8250",
+ lpc_ns8250_methods,
+ sizeof(struct lpc_ns8250_softc),
+ .uc_ops = &uart_lpc_ns8250_ops,
+ .uc_range = 8,
+ .uc_rclk = DEFAULT_RCLK
+};
+
+static struct ofw_compat_data compat_data[] = {
+ {"lpc,uart", (uintptr_t)&uart_lpc_class},
+ {NULL, (uintptr_t)NULL},
+};
+UART_FDT_CLASS_AND_DEVICE(compat_data);
+
+#define SIGCHG(c, i, s, d) \
+ if (c) { \
+ i |= (i & s) ? s : s | d; \
+ } else { \
+ i = (i & s) ? (i & ~s) | d : i; \
+ }
+
+static int
+lpc_ns8250_bus_attach(struct uart_softc *sc)
+{
+ struct lpc_ns8250_softc *lpc_ns8250 = (struct lpc_ns8250_softc*)sc;
+ struct uart_bas *bas;
+ unsigned int ivar;
+
+ bas = &sc->sc_bas;
+
+ lpc_ns8250->mcr = uart_getreg(bas, REG_MCR);
+ lpc_ns8250->fcr = FCR_ENABLE | FCR_DMA;
+ if (!resource_int_value("uart", device_get_unit(sc->sc_dev), "flags",
+ &ivar)) {
+ if (UART_FLAGS_FCR_RX_LOW(ivar))
+ lpc_ns8250->fcr |= FCR_RX_LOW;
+ else if (UART_FLAGS_FCR_RX_MEDL(ivar))
+ lpc_ns8250->fcr |= FCR_RX_MEDL;
+ else if (UART_FLAGS_FCR_RX_HIGH(ivar))
+ lpc_ns8250->fcr |= FCR_RX_HIGH;
+ else
+ lpc_ns8250->fcr |= FCR_RX_MEDH;
+ } else
+ lpc_ns8250->fcr |= FCR_RX_HIGH;
+
+ /* Get IER mask */
+ ivar = 0xf0;
+ resource_int_value("uart", device_get_unit(sc->sc_dev), "ier_mask",
+ &ivar);
+ lpc_ns8250->ier_mask = (uint8_t)(ivar & 0xff);
+
+ /* Get IER RX interrupt bits */
+ ivar = IER_EMSC | IER_ERLS | IER_ERXRDY;
+ resource_int_value("uart", device_get_unit(sc->sc_dev), "ier_rxbits",
+ &ivar);
+ lpc_ns8250->ier_rxbits = (uint8_t)(ivar & 0xff);
+
+ uart_setreg(bas, REG_FCR, lpc_ns8250->fcr);
+ uart_barrier(bas);
+ lpc_ns8250_bus_flush(sc, UART_FLUSH_RECEIVER|UART_FLUSH_TRANSMITTER);
+
+ if (lpc_ns8250->mcr & MCR_DTR)
+ sc->sc_hwsig |= SER_DTR;
+ if (lpc_ns8250->mcr & MCR_RTS)
+ sc->sc_hwsig |= SER_RTS;
+ lpc_ns8250_bus_getsig(sc);
+
+ lpc_ns8250_clrint(bas);
+ lpc_ns8250->ier = uart_getreg(bas, REG_IER) & lpc_ns8250->ier_mask;
+ lpc_ns8250->ier |= lpc_ns8250->ier_rxbits;
+ uart_setreg(bas, REG_IER, lpc_ns8250->ier);
+ uart_barrier(bas);
+
+ return (0);
+}
+
+static int
+lpc_ns8250_bus_detach(struct uart_softc *sc)
+{
+ struct lpc_ns8250_softc *lpc_ns8250;
+ struct uart_bas *bas;
+ u_char ier;
+
+ lpc_ns8250 = (struct lpc_ns8250_softc *)sc;
+ bas = &sc->sc_bas;
+ ier = uart_getreg(bas, REG_IER) & lpc_ns8250->ier_mask;
+ uart_setreg(bas, REG_IER, ier);
+ uart_barrier(bas);
+ lpc_ns8250_clrint(bas);
+ return (0);
+}
+
+static int
+lpc_ns8250_bus_flush(struct uart_softc *sc, int what)
+{
+ struct lpc_ns8250_softc *lpc_ns8250 = (struct lpc_ns8250_softc*)sc;
+ struct uart_bas *bas;
+ int error;
+
+ bas = &sc->sc_bas;
+ uart_lock(sc->sc_hwmtx);
+ if (sc->sc_rxfifosz > 1) {
+ lpc_ns8250_flush(bas, what);
+ uart_setreg(bas, REG_FCR, lpc_ns8250->fcr);
+ uart_barrier(bas);
+ error = 0;
+ } else
+ error = lpc_ns8250_drain(bas, what);
+ uart_unlock(sc->sc_hwmtx);
+ return (error);
+}
+
+static int
+lpc_ns8250_bus_getsig(struct uart_softc *sc)
+{
+ uint32_t new, old, sig;
+ uint8_t msr;
+
+ do {
+ old = sc->sc_hwsig;
+ sig = old;
+ uart_lock(sc->sc_hwmtx);
+ msr = uart_getreg(&sc->sc_bas, REG_MSR);
+ uart_unlock(sc->sc_hwmtx);
+ SIGCHG(msr & MSR_DSR, sig, SER_DSR, SER_DDSR);
+ SIGCHG(msr & MSR_CTS, sig, SER_CTS, SER_DCTS);
+ SIGCHG(msr & MSR_DCD, sig, SER_DCD, SER_DDCD);
+ SIGCHG(msr & MSR_RI, sig, SER_RI, SER_DRI);
+ new = sig & ~SER_MASK_DELTA;
+ } while (!atomic_cmpset_32(&sc->sc_hwsig, old, new));
+ return (sig);
+}
+
+static int
+lpc_ns8250_bus_ioctl(struct uart_softc *sc, int request, intptr_t data)
+{
+ struct uart_bas *bas;
+ int baudrate, divisor, error;
+ uint8_t efr, lcr;
+
+ bas = &sc->sc_bas;
+ error = 0;
+ uart_lock(sc->sc_hwmtx);
+ switch (request) {
+ case UART_IOCTL_BREAK:
+ lcr = uart_getreg(bas, REG_LCR);
+ if (data)
+ lcr |= LCR_SBREAK;
+ else
+ lcr &= ~LCR_SBREAK;
+ uart_setreg(bas, REG_LCR, lcr);
+ uart_barrier(bas);
+ break;
+ case UART_IOCTL_IFLOW:
+ lcr = uart_getreg(bas, REG_LCR);
+ uart_barrier(bas);
+ uart_setreg(bas, REG_LCR, 0xbf);
+ uart_barrier(bas);
+ efr = uart_getreg(bas, REG_EFR);
+ if (data)
+ efr |= EFR_RTS;
+ else
+ efr &= ~EFR_RTS;
+ uart_setreg(bas, REG_EFR, efr);
+ uart_barrier(bas);
+ uart_setreg(bas, REG_LCR, lcr);
+ uart_barrier(bas);
+ break;
+ case UART_IOCTL_OFLOW:
+ lcr = uart_getreg(bas, REG_LCR);
+ uart_barrier(bas);
+ uart_setreg(bas, REG_LCR, 0xbf);
+ uart_barrier(bas);
+ efr = uart_getreg(bas, REG_EFR);
+ if (data)
+ efr |= EFR_CTS;
+ else
+ efr &= ~EFR_CTS;
+ uart_setreg(bas, REG_EFR, efr);
+ uart_barrier(bas);
+ uart_setreg(bas, REG_LCR, lcr);
+ uart_barrier(bas);
+ break;
+ case UART_IOCTL_BAUD:
+ lcr = uart_getreg(bas, REG_LCR);
+ uart_setreg(bas, REG_LCR, lcr | LCR_DLAB);
+ uart_barrier(bas);
+ divisor = uart_getreg(bas, REG_DLL) |
+ (uart_getreg(bas, REG_DLH) << 8);
+ uart_barrier(bas);
+ uart_setreg(bas, REG_LCR, lcr);
+ uart_barrier(bas);
+ baudrate = (divisor > 0) ? bas->rclk / divisor / 16 : 0;
+ if (baudrate > 0)
+ *(int*)data = baudrate;
+ else
+ error = ENXIO;
+ break;
+ default:
+ error = EINVAL;
+ break;
+ }
+ uart_unlock(sc->sc_hwmtx);
+ return (error);
+}
+
+static int
+lpc_ns8250_bus_ipend(struct uart_softc *sc)
+{
+ struct uart_bas *bas;
+ struct lpc_ns8250_softc *lpc_ns8250;
+ int ipend;
+ uint8_t iir, lsr;
+
+ lpc_ns8250 = (struct lpc_ns8250_softc *)sc;
+ bas = &sc->sc_bas;
+ uart_lock(sc->sc_hwmtx);
+ iir = uart_getreg(bas, REG_IIR);
+ if (iir & IIR_NOPEND) {
+ uart_unlock(sc->sc_hwmtx);
+ return (0);
+ }
+ ipend = 0;
+ if (iir & IIR_RXRDY) {
+ lsr = uart_getreg(bas, REG_LSR);
+ if (lsr & LSR_OE)
+ ipend |= SER_INT_OVERRUN;
+ if (lsr & LSR_BI)
+ ipend |= SER_INT_BREAK;
+ if (lsr & LSR_RXRDY)
+ ipend |= SER_INT_RXREADY;
+ } else {
+ if (iir & IIR_TXRDY) {
+ ipend |= SER_INT_TXIDLE;
+ uart_setreg(bas, REG_IER, lpc_ns8250->ier);
+ } else
+ ipend |= SER_INT_SIGCHG;
+ }
+ if (ipend == 0)
+ lpc_ns8250_clrint(bas);
+ uart_unlock(sc->sc_hwmtx);
+ return (ipend);
+}
+
+static int
+lpc_ns8250_bus_param(struct uart_softc *sc, int baudrate, int databits,
+ int stopbits, int parity)
+{
+ struct uart_bas *bas;
+ int error;
+
+ bas = &sc->sc_bas;
+ uart_lock(sc->sc_hwmtx);
+ error = lpc_ns8250_param(bas, baudrate, databits, stopbits, parity);
+ uart_unlock(sc->sc_hwmtx);
+ return (error);
+}
+
+static int
+lpc_ns8250_bus_probe(struct uart_softc *sc)
+{
+ struct lpc_ns8250_softc *lpc_ns8250;
+ struct uart_bas *bas;
+ int count, delay, error, limit;
+ uint8_t lsr, mcr, ier;
+
+ lpc_ns8250 = (struct lpc_ns8250_softc *)sc;
+ bas = &sc->sc_bas;
+
+ error = lpc_ns8250_probe(bas);
+ if (error)
+ return (error);
+
+ mcr = MCR_IE;
+ if (sc->sc_sysdev == NULL) {
+ /* By using lpc_ns8250_init() we also set DTR and RTS. */
+ lpc_ns8250_init(bas, 115200, 8, 1, UART_PARITY_NONE);
+ } else
+ mcr |= MCR_DTR | MCR_RTS;
+
+ error = lpc_ns8250_drain(bas, UART_DRAIN_TRANSMITTER);
+ if (error)
+ return (error);
+
+ /*
+ * Set loopback mode. This avoids having garbage on the wire and
+ * also allows us send and receive data. We set DTR and RTS to
+ * avoid the possibility that automatic flow-control prevents
+ * any data from being sent.
+ */
+ uart_setreg(bas, REG_MCR, MCR_LOOPBACK | MCR_IE | MCR_DTR | MCR_RTS);
+ uart_barrier(bas);
+
+ /*
+ * Enable FIFOs. And check that the UART has them. If not, we're
+ * done. Since this is the first time we enable the FIFOs, we reset
+ * them.
+ */
+ uart_setreg(bas, REG_FCR, FCR_ENABLE);
+ uart_barrier(bas);
+ if (!(uart_getreg(bas, REG_IIR) & IIR_FIFO_MASK)) {
+ /*
+ * NS16450 or INS8250. We don't bother to differentiate
+ * between them. They're too old to be interesting.
+ */
+ uart_setreg(bas, REG_MCR, mcr);
+ uart_barrier(bas);
+ sc->sc_rxfifosz = sc->sc_txfifosz = 1;
+ device_set_desc(sc->sc_dev, "8250 or 16450 or compatible");
+ return (0);
+ }
+
+ uart_setreg(bas, REG_FCR, FCR_ENABLE | FCR_XMT_RST | FCR_RCV_RST);
+ uart_barrier(bas);
+
+ count = 0;
+ delay = lpc_ns8250_delay(bas);
+
+ /* We have FIFOs. Drain the transmitter and receiver. */
+ error = lpc_ns8250_drain(bas, UART_DRAIN_RECEIVER|UART_DRAIN_TRANSMITTER);
+ if (error) {
+ uart_setreg(bas, REG_MCR, mcr);
+ uart_setreg(bas, REG_FCR, 0);
+ uart_barrier(bas);
+ goto done;
+ }
+
+ /*
+ * We should have a sufficiently clean "pipe" to determine the
+ * size of the FIFOs. We send as much characters as is reasonable
+ * and wait for the overflow bit in the LSR register to be
+ * asserted, counting the characters as we send them. Based on
+ * that count we know the FIFO size.
+ */
+ do {
+ uart_setreg(bas, REG_DATA, 0);
+ uart_barrier(bas);
+ count++;
+
+ limit = 30;
+ lsr = 0;
+ /*
+ * LSR bits are cleared upon read, so we must accumulate
+ * them to be able to test LSR_OE below.
+ */
+ while (((lsr |= uart_getreg(bas, REG_LSR)) & LSR_TEMT) == 0 &&
+ --limit)
+ DELAY(delay);
+ if (limit == 0) {
+ ier = uart_getreg(bas, REG_IER) & lpc_ns8250->ier_mask;
+ uart_setreg(bas, REG_IER, ier);
+ uart_setreg(bas, REG_MCR, mcr);
+ uart_setreg(bas, REG_FCR, 0);
+ uart_barrier(bas);
+ count = 0;
+ goto done;
+ }
+ } while ((lsr & LSR_OE) == 0 && count < 130);
+ count--;
+
+ uart_setreg(bas, REG_MCR, mcr);
+
+ /* Reset FIFOs. */
+ lpc_ns8250_flush(bas, UART_FLUSH_RECEIVER|UART_FLUSH_TRANSMITTER);
+
+done:
+ sc->sc_rxfifosz = 64;
+ device_set_desc(sc->sc_dev, "LPC32x0 UART with FIFOs");
+
+ /*
+ * Force the Tx FIFO size to 16 bytes for now. We don't program the
+ * Tx trigger. Also, we assume that all data has been sent when the
+ * interrupt happens.
+ */
+ sc->sc_txfifosz = 16;
+
+#if 0
+ /*
+ * XXX there are some issues related to hardware flow control and
+ * it's likely that uart(4) is the cause. This basicly needs more
+ * investigation, but we avoid using for hardware flow control
+ * until then.
+ */
+ /* 16650s or higher have automatic flow control. */
+ if (sc->sc_rxfifosz > 16) {
+ sc->sc_hwiflow = 1;
+ sc->sc_hwoflow = 1;
+ }
+#endif
+ return (0);
+}
+
+static int
+lpc_ns8250_bus_receive(struct uart_softc *sc)
+{
+ struct uart_bas *bas;
+ int xc;
+ uint8_t lsr;
+
+ bas = &sc->sc_bas;
+ uart_lock(sc->sc_hwmtx);
+ lsr = uart_getreg(bas, REG_LSR);
+ while (lsr & LSR_RXRDY) {
+ if (uart_rx_full(sc)) {
+ sc->sc_rxbuf[sc->sc_rxput] = UART_STAT_OVERRUN;
+ break;
+ }
+ xc = uart_getreg(bas, REG_DATA);
+ if (lsr & LSR_FE)
+ xc |= UART_STAT_FRAMERR;
+ if (lsr & LSR_PE)
+ xc |= UART_STAT_PARERR;
+ uart_rx_put(sc, xc);
+ lsr = uart_getreg(bas, REG_LSR);
+ }
+ /* Discard everything left in the Rx FIFO. */
+ while (lsr & LSR_RXRDY) {
+ (void)uart_getreg(bas, REG_DATA);
+ uart_barrier(bas);
+ lsr = uart_getreg(bas, REG_LSR);
+ }
+ uart_unlock(sc->sc_hwmtx);
+ return (0);
+}
+
+static int
+lpc_ns8250_bus_setsig(struct uart_softc *sc, int sig)
+{
+ struct lpc_ns8250_softc *lpc_ns8250 = (struct lpc_ns8250_softc*)sc;
+ struct uart_bas *bas;
+ uint32_t new, old;
+
+ bas = &sc->sc_bas;
+ do {
+ old = sc->sc_hwsig;
+ new = old;
+ if (sig & SER_DDTR) {
+ SIGCHG(sig & SER_DTR, new, SER_DTR,
+ SER_DDTR);
+ }
+ if (sig & SER_DRTS) {
+ SIGCHG(sig & SER_RTS, new, SER_RTS,
+ SER_DRTS);
+ }
+ } while (!atomic_cmpset_32(&sc->sc_hwsig, old, new));
+ uart_lock(sc->sc_hwmtx);
+ lpc_ns8250->mcr &= ~(MCR_DTR|MCR_RTS);
+ if (new & SER_DTR)
+ lpc_ns8250->mcr |= MCR_DTR;
+ if (new & SER_RTS)
+ lpc_ns8250->mcr |= MCR_RTS;
+ uart_setreg(bas, REG_MCR, lpc_ns8250->mcr);
+ uart_barrier(bas);
+ uart_unlock(sc->sc_hwmtx);
+ return (0);
+}
+
+static int
+lpc_ns8250_bus_transmit(struct uart_softc *sc)
+{
+ struct lpc_ns8250_softc *lpc_ns8250 = (struct lpc_ns8250_softc*)sc;
+ struct uart_bas *bas;
+ int i;
+
+ bas = &sc->sc_bas;
+ uart_lock(sc->sc_hwmtx);
+ while ((uart_getreg(bas, REG_LSR) & LSR_THRE) == 0)
+ ;
+ uart_setreg(bas, REG_IER, lpc_ns8250->ier | IER_ETXRDY);
+ uart_barrier(bas);
+ for (i = 0; i < sc->sc_txdatasz; i++) {
+ uart_setreg(bas, REG_DATA, sc->sc_txbuf[i]);
+ uart_barrier(bas);
+ }
+ sc->sc_txbusy = 1;
+ uart_unlock(sc->sc_hwmtx);
+ return (0);
+}
+
+void
+lpc_ns8250_bus_grab(struct uart_softc *sc)
+{
+ struct uart_bas *bas = &sc->sc_bas;
+
+ /*
+ * turn off all interrupts to enter polling mode. Leave the
+ * saved mask alone. We'll restore whatever it was in ungrab.
+ * All pending interupt signals are reset when IER is set to 0.
+ */
+ uart_lock(sc->sc_hwmtx);
+ uart_setreg(bas, REG_IER, 0);
+ uart_barrier(bas);
+ uart_unlock(sc->sc_hwmtx);
+}
+
+void
+lpc_ns8250_bus_ungrab(struct uart_softc *sc)
+{
+ struct lpc_ns8250_softc *lpc_ns8250 = (struct lpc_ns8250_softc*)sc;
+ struct uart_bas *bas = &sc->sc_bas;
+
+ /*
+ * Restore previous interrupt mask
+ */
+ uart_lock(sc->sc_hwmtx);
+ uart_setreg(bas, REG_IER, lpc_ns8250->ier);
+ uart_barrier(bas);
+ uart_unlock(sc->sc_hwmtx);
+}
Property changes on: trunk/sys/dev/uart/uart_dev_lpc.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/dev/uart/uart_dev_msm.c
===================================================================
--- trunk/sys/dev/uart/uart_dev_msm.c (rev 0)
+++ trunk/sys/dev/uart/uart_dev_msm.c 2018-05-27 22:53:06 UTC (rev 10057)
@@ -0,0 +1,576 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2014 Ganbold Tsagaankhuu <ganbold at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* Qualcomm MSM7K/8K uart driver */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/dev/uart/uart_dev_msm.c 283327 2015-05-23 20:54:25Z ian $");
+
+#include "opt_ddb.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/kdb.h>
+#include <machine/bus.h>
+#include <machine/fdt.h>
+
+#include <dev/uart/uart.h>
+#include <dev/uart/uart_cpu.h>
+#include <dev/uart/uart_cpu_fdt.h>
+#include <dev/uart/uart_bus.h>
+#include <dev/uart/uart_dev_msm.h>
+
+#include "uart_if.h"
+
+#define DEF_CLK 7372800
+
+#define GETREG(bas, reg) \
+ bus_space_read_4((bas)->bst, (bas)->bsh, (reg))
+#define SETREG(bas, reg, value) \
+ bus_space_write_4((bas)->bst, (bas)->bsh, (reg), (value))
+
+static int msm_uart_param(struct uart_bas *, int, int, int, int);
+
+/*
+ * Low-level UART interface.
+ */
+static int msm_probe(struct uart_bas *bas);
+static void msm_init(struct uart_bas *bas, int, int, int, int);
+static void msm_term(struct uart_bas *bas);
+static void msm_putc(struct uart_bas *bas, int);
+static int msm_rxready(struct uart_bas *bas);
+static int msm_getc(struct uart_bas *bas, struct mtx *mtx);
+
+extern SLIST_HEAD(uart_devinfo_list, uart_devinfo) uart_sysdevs;
+
+static int
+msm_uart_param(struct uart_bas *bas, int baudrate, int databits,
+ int stopbits, int parity)
+{
+ int ulcon;
+
+ ulcon = 0;
+
+ switch (databits) {
+ case 5:
+ ulcon |= (UART_DM_5_BPS << 4);
+ break;
+ case 6:
+ ulcon |= (UART_DM_6_BPS << 4);
+ break;
+ case 7:
+ ulcon |= (UART_DM_7_BPS << 4);
+ break;
+ case 8:
+ ulcon |= (UART_DM_8_BPS << 4);
+ break;
+ default:
+ return (EINVAL);
+ }
+
+ switch (parity) {
+ case UART_PARITY_NONE:
+ ulcon |= UART_DM_NO_PARITY;
+ break;
+ case UART_PARITY_ODD:
+ ulcon |= UART_DM_ODD_PARITY;
+ break;
+ case UART_PARITY_EVEN:
+ ulcon |= UART_DM_EVEN_PARITY;
+ break;
+ case UART_PARITY_SPACE:
+ ulcon |= UART_DM_SPACE_PARITY;
+ break;
+ case UART_PARITY_MARK:
+ default:
+ return (EINVAL);
+ }
+
+ switch (stopbits) {
+ case 1:
+ ulcon |= (UART_DM_SBL_1 << 2);
+ break;
+ case 2:
+ ulcon |= (UART_DM_SBL_2 << 2);
+ break;
+ default:
+ return (EINVAL);
+ }
+ uart_setreg(bas, UART_DM_MR2, ulcon);
+
+ /* Set 115200 for both TX and RX. */;
+ uart_setreg(bas, UART_DM_CSR, UART_DM_CSR_115200);
+ uart_barrier(bas);
+
+ return (0);
+}
+
+struct uart_ops uart_msm_ops = {
+ .probe = msm_probe,
+ .init = msm_init,
+ .term = msm_term,
+ .putc = msm_putc,
+ .rxready = msm_rxready,
+ .getc = msm_getc,
+};
+
+static int
+msm_probe(struct uart_bas *bas)
+{
+
+ return (0);
+}
+
+static void
+msm_init(struct uart_bas *bas, int baudrate, int databits, int stopbits,
+ int parity)
+{
+
+ if (bas->rclk == 0)
+ bas->rclk = DEF_CLK;
+
+ KASSERT(bas->rclk != 0, ("msm_init: Invalid rclk"));
+
+ /* Set default parameters */
+ msm_uart_param(bas, baudrate, databits, stopbits, parity);
+
+ /*
+ * Configure UART mode registers MR1 and MR2.
+ * Hardware flow control isn't supported.
+ */
+ uart_setreg(bas, UART_DM_MR1, 0x0);
+
+ /* Reset interrupt mask register. */
+ uart_setreg(bas, UART_DM_IMR, 0);
+
+ /*
+ * Configure Tx and Rx watermarks configuration registers.
+ * TX watermark value is set to 0 - interrupt is generated when
+ * FIFO level is less than or equal to 0.
+ */
+ uart_setreg(bas, UART_DM_TFWR, UART_DM_TFW_VALUE);
+
+ /* Set RX watermark value */
+ uart_setreg(bas, UART_DM_RFWR, UART_DM_RFW_VALUE);
+
+ /*
+ * Configure Interrupt Programming Register.
+ * Set initial Stale timeout value.
+ */
+ uart_setreg(bas, UART_DM_IPR, UART_DM_STALE_TIMEOUT_LSB);
+
+ /* Disable IRDA mode */
+ uart_setreg(bas, UART_DM_IRDA, 0x0);
+
+ /*
+ * Configure and enable sim interface if required.
+ * Configure hunt character value in HCR register.
+ * Keep it in reset state.
+ */
+ uart_setreg(bas, UART_DM_HCR, 0x0);
+
+ /* Issue soft reset command */
+ SETREG(bas, UART_DM_CR, UART_DM_RESET_TX);
+ SETREG(bas, UART_DM_CR, UART_DM_RESET_RX);
+ SETREG(bas, UART_DM_CR, UART_DM_RESET_ERROR_STATUS);
+ SETREG(bas, UART_DM_CR, UART_DM_RESET_BREAK_INT);
+ SETREG(bas, UART_DM_CR, UART_DM_RESET_STALE_INT);
+
+ /* Enable/Disable Rx/Tx DM interfaces */
+ /* Disable Data Mover for now. */
+ uart_setreg(bas, UART_DM_DMEN, 0x0);
+
+ /* Enable transmitter and receiver */
+ uart_setreg(bas, UART_DM_CR, UART_DM_CR_RX_ENABLE);
+ uart_setreg(bas, UART_DM_CR, UART_DM_CR_TX_ENABLE);
+
+ uart_barrier(bas);
+}
+
+static void
+msm_term(struct uart_bas *bas)
+{
+
+ /* XXX */
+}
+
+static void
+msm_putc(struct uart_bas *bas, int c)
+{
+ int limit;
+
+ /*
+ * Write to NO_CHARS_FOR_TX register the number of characters
+ * to be transmitted. However, before writing TX_FIFO must
+ * be empty as indicated by TX_READY interrupt in IMR register
+ */
+
+ /*
+ * Check if transmit FIFO is empty.
+ * If not wait for TX_READY interrupt.
+ */
+ limit = 1000;
+ if (!(uart_getreg(bas, UART_DM_SR) & UART_DM_SR_TXEMT)) {
+ while ((uart_getreg(bas, UART_DM_ISR) & UART_DM_TX_READY) == 0
+ && --limit)
+ DELAY(4);
+ }
+ /* FIFO is ready, write number of characters to be written */
+ uart_setreg(bas, UART_DM_NO_CHARS_FOR_TX, 1);
+
+ /* Wait till TX FIFO has space */
+ while ((uart_getreg(bas, UART_DM_SR) & UART_DM_SR_TXRDY) == 0)
+ DELAY(4);
+
+ /* TX FIFO has space. Write char */
+ SETREG(bas, UART_DM_TF(0), (c & 0xff));
+}
+
+static int
+msm_rxready(struct uart_bas *bas)
+{
+
+ /* Wait for a character to come ready */
+ return ((uart_getreg(bas, UART_DM_SR) & UART_DM_SR_RXRDY) ==
+ UART_DM_SR_RXRDY);
+}
+
+static int
+msm_getc(struct uart_bas *bas, struct mtx *mtx)
+{
+ int c;
+
+ uart_lock(mtx);
+
+ /* Wait for a character to come ready */
+ while ((uart_getreg(bas, UART_DM_SR) & UART_DM_SR_RXRDY) !=
+ UART_DM_SR_RXRDY)
+ DELAY(4);
+
+ /* Check for Overrun error. If so reset Error Status */
+ if (uart_getreg(bas, UART_DM_SR) & UART_DM_SR_UART_OVERRUN)
+ uart_setreg(bas, UART_DM_CR, UART_DM_RESET_ERROR_STATUS);
+
+ /* Read char */
+ c = uart_getreg(bas, UART_DM_RF(0));
+
+ uart_unlock(mtx);
+
+ return (c);
+}
+
+/*
+ * High-level UART interface.
+ */
+struct msm_uart_softc {
+ struct uart_softc base;
+ uint32_t ier;
+};
+
+static int msm_bus_probe(struct uart_softc *sc);
+static int msm_bus_attach(struct uart_softc *sc);
+static int msm_bus_flush(struct uart_softc *, int);
+static int msm_bus_getsig(struct uart_softc *);
+static int msm_bus_ioctl(struct uart_softc *, int, intptr_t);
+static int msm_bus_ipend(struct uart_softc *);
+static int msm_bus_param(struct uart_softc *, int, int, int, int);
+static int msm_bus_receive(struct uart_softc *);
+static int msm_bus_setsig(struct uart_softc *, int);
+static int msm_bus_transmit(struct uart_softc *);
+static void msm_bus_grab(struct uart_softc *);
+static void msm_bus_ungrab(struct uart_softc *);
+
+static kobj_method_t msm_methods[] = {
+ KOBJMETHOD(uart_probe, msm_bus_probe),
+ KOBJMETHOD(uart_attach, msm_bus_attach),
+ KOBJMETHOD(uart_flush, msm_bus_flush),
+ KOBJMETHOD(uart_getsig, msm_bus_getsig),
+ KOBJMETHOD(uart_ioctl, msm_bus_ioctl),
+ KOBJMETHOD(uart_ipend, msm_bus_ipend),
+ KOBJMETHOD(uart_param, msm_bus_param),
+ KOBJMETHOD(uart_receive, msm_bus_receive),
+ KOBJMETHOD(uart_setsig, msm_bus_setsig),
+ KOBJMETHOD(uart_transmit, msm_bus_transmit),
+ KOBJMETHOD(uart_grab, msm_bus_grab),
+ KOBJMETHOD(uart_ungrab, msm_bus_ungrab),
+ {0, 0 }
+};
+
+int
+msm_bus_probe(struct uart_softc *sc)
+{
+
+ sc->sc_txfifosz = 64;
+ sc->sc_rxfifosz = 64;
+
+ device_set_desc(sc->sc_dev, "Qualcomm HSUART");
+
+ return (0);
+}
+
+static int
+msm_bus_attach(struct uart_softc *sc)
+{
+ struct msm_uart_softc *u = (struct msm_uart_softc *)sc;
+ struct uart_bas *bas = &sc->sc_bas;
+
+ sc->sc_hwiflow = 0;
+ sc->sc_hwoflow = 0;
+
+ /* Set TX_READY, TXLEV, RXLEV, RXSTALE */
+ u->ier = UART_DM_IMR_ENABLED;
+
+ /* Configure Interrupt Mask register IMR */
+ uart_setreg(bas, UART_DM_IMR, u->ier);
+
+ return (0);
+}
+
+/*
+ * Write the current transmit buffer to the TX FIFO.
+ */
+static int
+msm_bus_transmit(struct uart_softc *sc)
+{
+ struct msm_uart_softc *u = (struct msm_uart_softc *)sc;
+ struct uart_bas *bas = &sc->sc_bas;
+ int i;
+
+ uart_lock(sc->sc_hwmtx);
+
+ /* Write some data */
+ for (i = 0; i < sc->sc_txdatasz; i++) {
+ /* Write TX data */
+ msm_putc(bas, sc->sc_txbuf[i]);
+ uart_barrier(bas);
+ }
+
+ /* TX FIFO is empty now, enable TX_READY interrupt */
+ u->ier |= UART_DM_TX_READY;
+ SETREG(bas, UART_DM_IMR, u->ier);
+ uart_barrier(bas);
+
+ /*
+ * Inform upper layer that it is transmitting data to hardware,
+ * this will be cleared when TXIDLE interrupt occurs.
+ */
+ sc->sc_txbusy = 1;
+ uart_unlock(sc->sc_hwmtx);
+
+ return (0);
+}
+
+static int
+msm_bus_setsig(struct uart_softc *sc, int sig)
+{
+
+ return (0);
+}
+
+static int
+msm_bus_receive(struct uart_softc *sc)
+{
+ struct msm_uart_softc *u = (struct msm_uart_softc *)sc;
+ struct uart_bas *bas;
+ int c;
+
+ bas = &sc->sc_bas;
+ uart_lock(sc->sc_hwmtx);
+
+ /* Initialize Receive Path and interrupt */
+ SETREG(bas, UART_DM_CR, UART_DM_RESET_STALE_INT);
+ SETREG(bas, UART_DM_CR, UART_DM_STALE_EVENT_ENABLE);
+ u->ier |= UART_DM_RXLEV;
+ SETREG(bas, UART_DM_IMR, u->ier);
+
+ /* Loop over until we are full, or no data is available */
+ while (uart_getreg(bas, UART_DM_SR) & UART_DM_SR_RXRDY) {
+ if (uart_rx_full(sc)) {
+ /* No space left in input buffer */
+ sc->sc_rxbuf[sc->sc_rxput] = UART_STAT_OVERRUN;
+ break;
+ }
+
+ /* Read RX FIFO */
+ c = uart_getreg(bas, UART_DM_RF(0));
+ uart_barrier(bas);
+
+ uart_rx_put(sc, c);
+ }
+
+ uart_unlock(sc->sc_hwmtx);
+
+ return (0);
+}
+
+static int
+msm_bus_param(struct uart_softc *sc, int baudrate, int databits,
+ int stopbits, int parity)
+{
+ int error;
+
+ if (sc->sc_bas.rclk == 0)
+ sc->sc_bas.rclk = DEF_CLK;
+
+ KASSERT(sc->sc_bas.rclk != 0, ("msm_init: Invalid rclk"));
+
+ uart_lock(sc->sc_hwmtx);
+ error = msm_uart_param(&sc->sc_bas, baudrate, databits, stopbits,
+ parity);
+ uart_unlock(sc->sc_hwmtx);
+
+ return (error);
+}
+
+static int
+msm_bus_ipend(struct uart_softc *sc)
+{
+ struct msm_uart_softc *u = (struct msm_uart_softc *)sc;
+ struct uart_bas *bas = &sc->sc_bas;
+ uint32_t isr;
+ int ipend;
+
+ uart_lock(sc->sc_hwmtx);
+
+ /* Get ISR status */
+ isr = GETREG(bas, UART_DM_MISR);
+
+ ipend = 0;
+
+ /* Uart RX starting, notify upper layer */
+ if (isr & UART_DM_RXLEV) {
+ u->ier &= ~UART_DM_RXLEV;
+ SETREG(bas, UART_DM_IMR, u->ier);
+ uart_barrier(bas);
+ ipend |= SER_INT_RXREADY;
+ }
+
+ /* Stale RX interrupt */
+ if (isr & UART_DM_RXSTALE) {
+ /* Disable and reset it */
+ SETREG(bas, UART_DM_CR, UART_DM_STALE_EVENT_DISABLE);
+ SETREG(bas, UART_DM_CR, UART_DM_RESET_STALE_INT);
+ uart_barrier(bas);
+ ipend |= SER_INT_RXREADY;
+ }
+
+ /* TX READY interrupt */
+ if (isr & UART_DM_TX_READY) {
+ /* Clear TX Ready */
+ SETREG(bas, UART_DM_CR, UART_DM_CLEAR_TX_READY);
+
+ /* Disable TX_READY */
+ u->ier &= ~UART_DM_TX_READY;
+ SETREG(bas, UART_DM_IMR, u->ier);
+ uart_barrier(bas);
+
+ if (sc->sc_txbusy != 0)
+ ipend |= SER_INT_TXIDLE;
+ }
+
+ if (isr & UART_DM_TXLEV) {
+ /* TX FIFO is empty */
+ u->ier &= ~UART_DM_TXLEV;
+ SETREG(bas, UART_DM_IMR, u->ier);
+ uart_barrier(bas);
+
+ if (sc->sc_txbusy != 0)
+ ipend |= SER_INT_TXIDLE;
+ }
+
+ uart_unlock(sc->sc_hwmtx);
+ return (ipend);
+}
+
+static int
+msm_bus_flush(struct uart_softc *sc, int what)
+{
+
+ return (0);
+}
+
+static int
+msm_bus_getsig(struct uart_softc *sc)
+{
+
+ return (0);
+}
+
+static int
+msm_bus_ioctl(struct uart_softc *sc, int request, intptr_t data)
+{
+
+ return (EINVAL);
+}
+
+static void
+msm_bus_grab(struct uart_softc *sc)
+{
+ struct uart_bas *bas = &sc->sc_bas;
+
+ /*
+ * XXX: Turn off all interrupts to enter polling mode. Leave the
+ * saved mask alone. We'll restore whatever it was in ungrab.
+ */
+ uart_lock(sc->sc_hwmtx);
+ SETREG(bas, UART_DM_CR, UART_DM_RESET_STALE_INT);
+ SETREG(bas, UART_DM_IMR, 0);
+ uart_barrier(bas);
+ uart_unlock(sc->sc_hwmtx);
+}
+
+static void
+msm_bus_ungrab(struct uart_softc *sc)
+{
+ struct msm_uart_softc *u = (struct msm_uart_softc *)sc;
+ struct uart_bas *bas = &sc->sc_bas;
+
+ /*
+ * Restore previous interrupt mask
+ */
+ uart_lock(sc->sc_hwmtx);
+ SETREG(bas, UART_DM_IMR, u->ier);
+ uart_barrier(bas);
+ uart_unlock(sc->sc_hwmtx);
+}
+
+static struct uart_class uart_msm_class = {
+ "msm",
+ msm_methods,
+ sizeof(struct msm_uart_softc),
+ .uc_ops = &uart_msm_ops,
+ .uc_range = 8,
+ .uc_rclk = DEF_CLK,
+};
+
+static struct ofw_compat_data compat_data[] = {
+ {"qcom,msm-uartdm", (uintptr_t)&uart_msm_class},
+ {NULL, (uintptr_t)NULL},
+};
+UART_FDT_CLASS_AND_DEVICE(compat_data);
Property changes on: trunk/sys/dev/uart/uart_dev_msm.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/dev/uart/uart_dev_msm.h
===================================================================
--- trunk/sys/dev/uart/uart_dev_msm.h (rev 0)
+++ trunk/sys/dev/uart/uart_dev_msm.h 2018-05-27 22:53:06 UTC (rev 10057)
@@ -0,0 +1,230 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2014 Ganbold Tsagaankhuu <ganbold at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/dev/uart/uart_dev_msm.h 283321 2015-05-23 19:27:04Z ian $
+ */
+
+#ifndef _UART_DM_H_
+#define _UART_DM_H_
+
+#define UART_DM_EXTR_BITS(value, start_pos, end_pos) \
+ ((value << (32 - end_pos)) >> (32 - (end_pos - start_pos)))
+
+/* UART Parity Mode */
+enum UART_DM_PARITY_MODE {
+ UART_DM_NO_PARITY,
+ UART_DM_ODD_PARITY,
+ UART_DM_EVEN_PARITY,
+ UART_DM_SPACE_PARITY
+};
+
+/* UART Stop Bit Length */
+enum UART_DM_STOP_BIT_LEN {
+ UART_DM_SBL_9_16,
+ UART_DM_SBL_1,
+ UART_DM_SBL_1_9_16,
+ UART_DM_SBL_2
+};
+
+/* UART Bits per Char */
+enum UART_DM_BITS_PER_CHAR {
+ UART_DM_5_BPS,
+ UART_DM_6_BPS,
+ UART_DM_7_BPS,
+ UART_DM_8_BPS
+};
+
+/* 8-N-1 Configuration */
+#define UART_DM_8_N_1_MODE (UART_DM_NO_PARITY | \
+ (UART_DM_SBL_1 << 2) | \
+ (UART_DM_8_BPS << 4))
+
+/* UART_DM Registers */
+
+/* UART Operational Mode Registers (HSUART) */
+#define UART_DM_MR1 0x00
+#define UART_DM_MR1_AUTO_RFR_LEVEL1_BMSK 0xffffff00
+#define UART_DM_MR1_AUTO_RFR_LEVEL0_BMSK 0x3f
+#define UART_DM_MR1_CTS_CTL_BMSK 0x40
+#define UART_DM_MR1_RX_RDY_CTL_BMSK 0x80
+
+#define UART_DM_MR2 0x04
+#define UART_DM_MR2_ERROR_MODE_BMSK 0x40
+#define UART_DM_MR2_BITS_PER_CHAR_BMSK 0x30
+#define UART_DM_MR2_STOP_BIT_LEN_BMSK 0x0c
+#define UART_DM_MR2_PARITY_MODE_BMSK 0x03
+#define UART_DM_RXBRK_ZERO_CHAR_OFF (1 << 8)
+#define UART_DM_LOOPBACK (1 << 7)
+
+/* UART Clock Selection Register, write only */
+#define UART_DM_CSR 0x08
+#define UART_DM_CSR_115200 0xff
+#define UART_DM_CSR_57600 0xee
+#define UART_DM_CSR_38400 0xdd
+#define UART_DM_CSR_28800 0xcc
+#define UART_DM_CSR_19200 0xbb
+#define UART_DM_CSR_14400 0xaa
+#define UART_DM_CSR_9600 0x99
+#define UART_DM_CSR_7200 0x88
+#define UART_DM_CSR_4800 0x77
+#define UART_DM_CSR_3600 0x66
+#define UART_DM_CSR_2400 0x55
+#define UART_DM_CSR_1200 0x44
+#define UART_DM_CSR_600 0x33
+#define UART_DM_CSR_300 0x22
+#define UART_DM_CSR_150 0x11
+#define UART_DM_CSR_75 0x00
+
+/* UART DM TX FIFO Registers - 4, write only */
+#define UART_DM_TF(x) (0x70 + (4 * (x)))
+
+/* UART Command Register, write only */
+#define UART_DM_CR 0x10
+#define UART_DM_CR_RX_ENABLE (1 << 0)
+#define UART_DM_CR_RX_DISABLE (1 << 1)
+#define UART_DM_CR_TX_ENABLE (1 << 2)
+#define UART_DM_CR_TX_DISABLE (1 << 3)
+
+/* UART_DM_CR channel command bit value (register field is bits 8:4) */
+#define UART_DM_RESET_RX 0x10
+#define UART_DM_RESET_TX 0x20
+#define UART_DM_RESET_ERROR_STATUS 0x30
+#define UART_DM_RESET_BREAK_INT 0x40
+#define UART_DM_START_BREAK 0x50
+#define UART_DM_STOP_BREAK 0x60
+#define UART_DM_RESET_CTS 0x70
+#define UART_DM_RESET_STALE_INT 0x80
+#define UART_DM_RFR_LOW 0xD0
+#define UART_DM_RFR_HIGH 0xE0
+#define UART_DM_CR_PROTECTION_EN 0x100
+#define UART_DM_STALE_EVENT_ENABLE 0x500
+#define UART_DM_STALE_EVENT_DISABLE 0x600
+#define UART_DM_FORCE_STALE_EVENT 0x400
+#define UART_DM_CLEAR_TX_READY 0x300
+#define UART_DM_RESET_TX_ERROR 0x800
+#define UART_DM_RESET_TX_DONE 0x810
+
+/* UART Interrupt Mask Register */
+#define UART_DM_IMR 0x14
+/* these can be used for both ISR and IMR registers */
+#define UART_DM_TXLEV (1 << 0)
+#define UART_DM_RXHUNT (1 << 1)
+#define UART_DM_RXBRK_CHNG (1 << 2)
+#define UART_DM_RXSTALE (1 << 3)
+#define UART_DM_RXLEV (1 << 4)
+#define UART_DM_DELTA_CTS (1 << 5)
+#define UART_DM_CURRENT_CTS (1 << 6)
+#define UART_DM_TX_READY (1 << 7)
+#define UART_DM_TX_ERROR (1 << 8)
+#define UART_DM_TX_DONE (1 << 9)
+#define UART_DM_RXBREAK_START (1 << 10)
+#define UART_DM_RXBREAK_END (1 << 11)
+#define UART_DM_PAR_FRAME_ERR_IRQ (1 << 12)
+
+#define UART_DM_IMR_ENABLED (UART_DM_TX_READY | \
+ UART_DM_TXLEV | \
+ UART_DM_RXLEV | \
+ UART_DM_RXSTALE)
+
+/* UART Interrupt Programming Register */
+#define UART_DM_IPR 0x18
+#define UART_DM_STALE_TIMEOUT_LSB 0x0f
+#define UART_DM_STALE_TIMEOUT_MSB 0x00
+#define UART_DM_IPR_STALE_TIMEOUT_MSB_BMSK 0xffffff80
+#define UART_DM_IPR_STALE_LSB_BMSK 0x1f
+
+/* UART Transmit/Receive FIFO Watermark Register */
+#define UART_DM_TFWR 0x1c
+/* Interrupt is generated when FIFO level is less than or equal to this value */
+#define UART_DM_TFW_VALUE 0
+
+#define UART_DM_RFWR 0x20
+/* Interrupt generated when no of words in RX FIFO is greater than this value */
+#define UART_DM_RFW_VALUE 0
+
+/* UART Hunt Character Register */
+#define UART_DM_HCR 0x24
+
+/* Used for RX transfer initialization */
+#define UART_DM_DMRX 0x34
+/* Default DMRX value - any value bigger than FIFO size would be fine */
+#define UART_DM_DMRX_DEF_VALUE 0x220
+
+/* Register to enable IRDA function */
+#define UART_DM_IRDA 0x38
+
+/* UART Data Mover Enable Register */
+#define UART_DM_DMEN 0x3c
+
+/* Number of characters for Transmission */
+#define UART_DM_NO_CHARS_FOR_TX 0x40
+
+/* UART RX FIFO Base Address */
+#define UART_DM_BADR 0x44
+
+#define UART_DM_SIM_CFG_ADDR 0x80
+
+/* Read only registers */
+/* UART Status Register */
+#define UART_DM_SR 0x08
+/* register field mask mapping */
+#define UART_DM_SR_RXRDY (1 << 0)
+#define UART_DM_SR_RXFULL (1 << 1)
+#define UART_DM_SR_TXRDY (1 << 2)
+#define UART_DM_SR_TXEMT (1 << 3)
+#define UART_DM_SR_UART_OVERRUN (1 << 4)
+#define UART_DM_SR_PAR_FRAME_ERR (1 << 5)
+#define UART_DM_RX_BREAK (1 << 6)
+#define UART_DM_HUNT_CHAR (1 << 7)
+#define UART_DM_RX_BRK_START_LAST (1 << 8)
+
+/* UART Receive FIFO Registers - 4 in numbers */
+#define UART_DM_RF(x) (0x70 + (4 * (x)))
+
+/* UART Masked Interrupt Status Register */
+#define UART_DM_MISR 0x10
+
+/* UART Interrupt Status Register */
+#define UART_DM_ISR 0x14
+
+/* Number of characters received since the end of last RX transfer */
+#define UART_DM_RX_TOTAL_SNAP 0x38
+
+/* UART TX FIFO Status Register */
+#define UART_DM_TXFS 0x4c
+#define UART_DM_TXFS_STATE_LSB(x) UART_DM_EXTR_BITS(x,0,6)
+#define UART_DM_TXFS_STATE_MSB(x) UART_DM_EXTR_BITS(x,14,31)
+#define UART_DM_TXFS_BUF_STATE(x) UART_DM_EXTR_BITS(x,7,9)
+#define UART_DM_TXFS_ASYNC_STATE(x) UART_DM_EXTR_BITS(x,10,13)
+
+/* UART RX FIFO Status Register */
+#define UART_DM_RXFS 0x50
+#define UART_DM_RXFS_STATE_LSB(x) UART_DM_EXTR_BITS(x,0,6)
+#define UART_DM_RXFS_STATE_MSB(x) UART_DM_EXTR_BITS(x,14,31)
+#define UART_DM_RXFS_BUF_STATE(x) UART_DM_EXTR_BITS(x,7,9)
+#define UART_DM_RXFS_ASYNC_STATE(x) UART_DM_EXTR_BITS(x,10,13)
+
+#endif /* _UART_DM_H_ */
Property changes on: trunk/sys/dev/uart/uart_dev_msm.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Modified: trunk/sys/dev/uart/uart_dev_ns8250.c
===================================================================
--- trunk/sys/dev/uart/uart_dev_ns8250.c 2018-05-27 22:50:50 UTC (rev 10056)
+++ trunk/sys/dev/uart/uart_dev_ns8250.c 2018-05-27 22:53:06 UTC (rev 10057)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 2003 Marcel Moolenaar
* All rights reserved.
@@ -24,8 +25,10 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include "opt_platform.h"
+
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/10/sys/dev/uart/uart_dev_ns8250.c 294229 2016-01-17 18:18:01Z ian $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -35,9 +38,20 @@
#include <sys/sysctl.h>
#include <machine/bus.h>
+#ifdef FDT
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#endif
+
#include <dev/uart/uart.h>
#include <dev/uart/uart_cpu.h>
+#ifdef FDT
+#include <dev/uart/uart_cpu_fdt.h>
+#endif
#include <dev/uart/uart_bus.h>
+#include <dev/uart/uart_dev_ns8250.h>
+#include <dev/uart/uart_ppstypes.h>
#include <dev/ic/ns16550.h>
@@ -45,6 +59,11 @@
#define DEFAULT_RCLK 1843200
+static int broken_txfifo = 0;
+SYSCTL_INT(_hw, OID_AUTO, broken_txfifo, CTLFLAG_RW | CTLFLAG_TUN,
+ &broken_txfifo, 0, "UART FIFO has QEMU emulation bug");
+TUNABLE_INT("hw.broken_txfifo", &broken_txfifo);
+
/*
* Clear pending interrupts. THRE is cleared by reading IIR. Data
* that may have been received gets lost here.
@@ -226,7 +245,7 @@
static int ns8250_rxready(struct uart_bas *bas);
static int ns8250_getc(struct uart_bas *bas, struct mtx *);
-static struct uart_ops uart_ns8250_ops = {
+struct uart_ops uart_ns8250_ops = {
.probe = ns8250_probe,
.init = ns8250_init,
.term = ns8250_term,
@@ -339,31 +358,6 @@
return (c);
}
-/*
- * High-level UART interface.
- */
-struct ns8250_softc {
- struct uart_softc base;
- uint8_t fcr;
- uint8_t ier;
- uint8_t mcr;
-
- uint8_t ier_mask;
- uint8_t ier_rxbits;
-};
-
-static int ns8250_bus_attach(struct uart_softc *);
-static int ns8250_bus_detach(struct uart_softc *);
-static int ns8250_bus_flush(struct uart_softc *, int);
-static int ns8250_bus_getsig(struct uart_softc *);
-static int ns8250_bus_ioctl(struct uart_softc *, int, intptr_t);
-static int ns8250_bus_ipend(struct uart_softc *);
-static int ns8250_bus_param(struct uart_softc *, int, int, int, int);
-static int ns8250_bus_probe(struct uart_softc *);
-static int ns8250_bus_receive(struct uart_softc *);
-static int ns8250_bus_setsig(struct uart_softc *, int);
-static int ns8250_bus_transmit(struct uart_softc *);
-
static kobj_method_t ns8250_methods[] = {
KOBJMETHOD(uart_attach, ns8250_bus_attach),
KOBJMETHOD(uart_detach, ns8250_bus_detach),
@@ -376,6 +370,8 @@
KOBJMETHOD(uart_receive, ns8250_bus_receive),
KOBJMETHOD(uart_setsig, ns8250_bus_setsig),
KOBJMETHOD(uart_transmit, ns8250_bus_transmit),
+ KOBJMETHOD(uart_grab, ns8250_bus_grab),
+ KOBJMETHOD(uart_ungrab, ns8250_bus_ungrab),
{ 0, 0 }
};
@@ -388,20 +384,75 @@
.uc_rclk = DEFAULT_RCLK
};
-#define SIGCHG(c, i, s, d) \
- if (c) { \
- i |= (i & s) ? s : s | d; \
- } else { \
- i = (i & s) ? (i & ~s) | d : i; \
+#ifdef FDT
+static struct ofw_compat_data compat_data[] = {
+ {"ns16550", (uintptr_t)&uart_ns8250_class},
+ {NULL, (uintptr_t)NULL},
+};
+UART_FDT_CLASS_AND_DEVICE(compat_data);
+#endif
+
+/* Use token-pasting to form SER_ and MSR_ named constants. */
+#define SER(sig) SER_##sig
+#define SERD(sig) SER_D##sig
+#define MSR(sig) MSR_##sig
+#define MSRD(sig) MSR_D##sig
+
+/*
+ * Detect signal changes using software delta detection. The previous state of
+ * the signals is in 'var' the new hardware state is in 'msr', and 'sig' is the
+ * short name (DCD, CTS, etc) of the signal bit being processed; 'var' gets the
+ * new state of both the signal and the delta bits.
+ */
+#define SIGCHGSW(var, msr, sig) \
+ if ((msr) & MSR(sig)) { \
+ if ((var & SER(sig)) == 0) \
+ var |= SERD(sig) | SER(sig); \
+ } else { \
+ if ((var & SER(sig)) != 0) \
+ var = SERD(sig) | (var & ~SER(sig)); \
}
-static int
+/*
+ * Detect signal changes using the hardware msr delta bits. This is currently
+ * used only when PPS timing information is being captured using the "narrow
+ * pulse" option. With a narrow PPS pulse the signal may not still be asserted
+ * by time the interrupt handler is invoked. The hardware will latch the fact
+ * that it changed in the delta bits.
+ */
+#define SIGCHGHW(var, msr, sig) \
+ if ((msr) & MSRD(sig)) { \
+ if (((msr) & MSR(sig)) != 0) \
+ var |= SERD(sig) | SER(sig); \
+ else \
+ var = SERD(sig) | (var & ~SER(sig)); \
+ }
+
+int
ns8250_bus_attach(struct uart_softc *sc)
{
struct ns8250_softc *ns8250 = (struct ns8250_softc*)sc;
struct uart_bas *bas;
unsigned int ivar;
+#ifdef FDT
+ phandle_t node;
+ pcell_t cell;
+#endif
+ ns8250->busy_detect = 0;
+
+#ifdef FDT
+ /*
+ * Check whether uart requires to read USR reg when IIR_BUSY and
+ * has broken txfifo.
+ */
+ node = ofw_bus_get_node(sc->sc_dev);
+ if ((OF_getprop(node, "busy-detect", &cell, sizeof(cell))) > 0)
+ ns8250->busy_detect = 1;
+ if ((OF_getprop(node, "broken-txfifo", &cell, sizeof(cell))) > 0)
+ broken_txfifo = 1;
+#endif
+
bas = &sc->sc_bas;
ns8250->mcr = uart_getreg(bas, REG_MCR);
@@ -446,11 +497,23 @@
ns8250->ier |= ns8250->ier_rxbits;
uart_setreg(bas, REG_IER, ns8250->ier);
uart_barrier(bas);
-
+
+ /*
+ * Timing of the H/W access was changed with r253161 of uart_core.c
+ * It has been observed that an ITE IT8513E would signal a break
+ * condition with pretty much every character it received, unless
+ * it had enough time to settle between ns8250_bus_attach() and
+ * ns8250_bus_ipend() -- which it accidentally had before r253161.
+ * It's not understood why the UART chip behaves this way and it
+ * could very well be that the DELAY make the H/W work in the same
+ * accidental manner as before. More analysis is warranted, but
+ * at least now we fixed a known regression.
+ */
+ DELAY(200);
return (0);
}
-static int
+int
ns8250_bus_detach(struct uart_softc *sc)
{
struct ns8250_softc *ns8250;
@@ -466,7 +529,7 @@
return (0);
}
-static int
+int
ns8250_bus_flush(struct uart_softc *sc, int what)
{
struct ns8250_softc *ns8250 = (struct ns8250_softc*)sc;
@@ -486,12 +549,23 @@
return (error);
}
-static int
+int
ns8250_bus_getsig(struct uart_softc *sc)
{
- uint32_t new, old, sig;
+ uint32_t old, sig;
uint8_t msr;
+ /*
+ * The delta bits are reputed to be broken on some hardware, so use
+ * software delta detection by default. Use the hardware delta bits
+ * when capturing PPS pulses which are too narrow for software detection
+ * to see the edges. Hardware delta for RI doesn't work like the
+ * others, so always use software for it. Other threads may be changing
+ * other (non-MSR) bits in sc_hwsig, so loop until it can succesfully
+ * update without other changes happening. Note that the SIGCHGxx()
+ * macros carefully preserve the delta bits when we have to loop several
+ * times and a signal transitions between iterations.
+ */
do {
old = sc->sc_hwsig;
sig = old;
@@ -498,16 +572,21 @@
uart_lock(sc->sc_hwmtx);
msr = uart_getreg(&sc->sc_bas, REG_MSR);
uart_unlock(sc->sc_hwmtx);
- SIGCHG(msr & MSR_DSR, sig, SER_DSR, SER_DDSR);
- SIGCHG(msr & MSR_CTS, sig, SER_CTS, SER_DCTS);
- SIGCHG(msr & MSR_DCD, sig, SER_DCD, SER_DDCD);
- SIGCHG(msr & MSR_RI, sig, SER_RI, SER_DRI);
- new = sig & ~SER_MASK_DELTA;
- } while (!atomic_cmpset_32(&sc->sc_hwsig, old, new));
+ if (sc->sc_pps_mode & UART_PPS_NARROW_PULSE) {
+ SIGCHGHW(sig, msr, DSR);
+ SIGCHGHW(sig, msr, CTS);
+ SIGCHGHW(sig, msr, DCD);
+ } else {
+ SIGCHGSW(sig, msr, DSR);
+ SIGCHGSW(sig, msr, CTS);
+ SIGCHGSW(sig, msr, DCD);
+ }
+ SIGCHGSW(sig, msr, RI);
+ } while (!atomic_cmpset_32(&sc->sc_hwsig, old, sig & ~SER_MASK_DELTA));
return (sig);
}
-static int
+int
ns8250_bus_ioctl(struct uart_softc *sc, int request, intptr_t data)
{
struct uart_bas *bas;
@@ -580,16 +659,24 @@
return (error);
}
-static int
+int
ns8250_bus_ipend(struct uart_softc *sc)
{
struct uart_bas *bas;
+ struct ns8250_softc *ns8250;
int ipend;
uint8_t iir, lsr;
+ ns8250 = (struct ns8250_softc *)sc;
bas = &sc->sc_bas;
uart_lock(sc->sc_hwmtx);
iir = uart_getreg(bas, REG_IIR);
+
+ if (ns8250->busy_detect && (iir & IIR_BUSY) == IIR_BUSY) {
+ (void)uart_getreg(bas, DW_REG_USR);
+ uart_unlock(sc->sc_hwmtx);
+ return (0);
+ }
if (iir & IIR_NOPEND) {
uart_unlock(sc->sc_hwmtx);
return (0);
@@ -604,9 +691,10 @@
if (lsr & LSR_RXRDY)
ipend |= SER_INT_RXREADY;
} else {
- if (iir & IIR_TXRDY)
+ if (iir & IIR_TXRDY) {
ipend |= SER_INT_TXIDLE;
- else
+ uart_setreg(bas, REG_IER, ns8250->ier);
+ } else
ipend |= SER_INT_SIGCHG;
}
if (ipend == 0)
@@ -615,21 +703,45 @@
return (ipend);
}
-static int
+int
ns8250_bus_param(struct uart_softc *sc, int baudrate, int databits,
int stopbits, int parity)
{
+ struct ns8250_softc *ns8250;
struct uart_bas *bas;
- int error;
+ int error, limit;
+ ns8250 = (struct ns8250_softc*)sc;
bas = &sc->sc_bas;
uart_lock(sc->sc_hwmtx);
+ /*
+ * When using DW UART with BUSY detection it is necessary to wait
+ * until all serial transfers are finished before manipulating the
+ * line control. LCR will not be affected when UART is busy.
+ */
+ if (ns8250->busy_detect != 0) {
+ /*
+ * Pick an arbitrary high limit to avoid getting stuck in
+ * an infinite loop in case when the hardware is broken.
+ */
+ limit = 10 * 1024;
+ while (((uart_getreg(bas, DW_REG_USR) & USR_BUSY) != 0) &&
+ --limit)
+ DELAY(4);
+
+ if (limit <= 0) {
+ /* UART appears to be stuck */
+ uart_unlock(sc->sc_hwmtx);
+ return (EIO);
+ }
+ }
+
error = ns8250_param(bas, baudrate, databits, stopbits, parity);
uart_unlock(sc->sc_hwmtx);
return (error);
}
-static int
+int
ns8250_bus_probe(struct uart_softc *sc)
{
struct ns8250_softc *ns8250;
@@ -779,7 +891,7 @@
return (0);
}
-static int
+int
ns8250_bus_receive(struct uart_softc *sc)
{
struct uart_bas *bas;
@@ -812,7 +924,7 @@
return (0);
}
-static int
+int
ns8250_bus_setsig(struct uart_softc *sc, int sig)
{
struct ns8250_softc *ns8250 = (struct ns8250_softc*)sc;
@@ -824,12 +936,10 @@
old = sc->sc_hwsig;
new = old;
if (sig & SER_DDTR) {
- SIGCHG(sig & SER_DTR, new, SER_DTR,
- SER_DDTR);
+ new = (new & ~SER_DTR) | (sig & (SER_DTR | SER_DDTR));
}
if (sig & SER_DRTS) {
- SIGCHG(sig & SER_RTS, new, SER_RTS,
- SER_DRTS);
+ new = (new & ~SER_RTS) | (sig & (SER_RTS | SER_DRTS));
}
} while (!atomic_cmpset_32(&sc->sc_hwsig, old, new));
uart_lock(sc->sc_hwmtx);
@@ -844,12 +954,7 @@
return (0);
}
-static int broken_txfifo = 0;
-SYSCTL_INT(_hw, OID_AUTO, broken_txfifo, CTLFLAG_RW | CTLFLAG_TUN,
- &broken_txfifo, 0, "UART FIFO has QEMU emulation bug");
-TUNABLE_INT("hw.broken_txfifo", &broken_txfifo);
-
-static int
+int
ns8250_bus_transmit(struct uart_softc *sc)
{
struct ns8250_softc *ns8250 = (struct ns8250_softc*)sc;
@@ -875,3 +980,34 @@
uart_sched_softih(sc, SER_INT_TXIDLE);
return (0);
}
+
+void
+ns8250_bus_grab(struct uart_softc *sc)
+{
+ struct uart_bas *bas = &sc->sc_bas;
+
+ /*
+ * turn off all interrupts to enter polling mode. Leave the
+ * saved mask alone. We'll restore whatever it was in ungrab.
+ * All pending interupt signals are reset when IER is set to 0.
+ */
+ uart_lock(sc->sc_hwmtx);
+ uart_setreg(bas, REG_IER, 0);
+ uart_barrier(bas);
+ uart_unlock(sc->sc_hwmtx);
+}
+
+void
+ns8250_bus_ungrab(struct uart_softc *sc)
+{
+ struct ns8250_softc *ns8250 = (struct ns8250_softc*)sc;
+ struct uart_bas *bas = &sc->sc_bas;
+
+ /*
+ * Restore previous interrupt mask
+ */
+ uart_lock(sc->sc_hwmtx);
+ uart_setreg(bas, REG_IER, ns8250->ier);
+ uart_barrier(bas);
+ uart_unlock(sc->sc_hwmtx);
+}
Added: trunk/sys/dev/uart/uart_dev_ns8250.h
===================================================================
--- trunk/sys/dev/uart/uart_dev_ns8250.h (rev 0)
+++ trunk/sys/dev/uart/uart_dev_ns8250.h 2018-05-27 22:53:06 UTC (rev 10057)
@@ -0,0 +1,63 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2003 Marcel Moolenaar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/dev/uart/uart_dev_ns8250.h 262649 2014-03-01 04:16:54Z imp $
+ */
+
+#ifndef _DEV_UART_DEV_NS8250_H_
+#define _DEV_UART_DEV_NS8250_H_
+
+/*
+ * High-level UART interface.
+ */
+struct ns8250_softc {
+ struct uart_softc base;
+ uint8_t fcr;
+ uint8_t ier;
+ uint8_t mcr;
+
+ uint8_t ier_mask;
+ uint8_t ier_rxbits;
+ uint8_t busy_detect;
+};
+
+extern struct uart_ops uart_ns8250_ops;
+
+int ns8250_bus_attach(struct uart_softc *);
+int ns8250_bus_detach(struct uart_softc *);
+int ns8250_bus_flush(struct uart_softc *, int);
+int ns8250_bus_getsig(struct uart_softc *);
+int ns8250_bus_ioctl(struct uart_softc *, int, intptr_t);
+int ns8250_bus_ipend(struct uart_softc *);
+int ns8250_bus_param(struct uart_softc *, int, int, int, int);
+int ns8250_bus_probe(struct uart_softc *);
+int ns8250_bus_receive(struct uart_softc *);
+int ns8250_bus_setsig(struct uart_softc *, int);
+int ns8250_bus_transmit(struct uart_softc *);
+void ns8250_bus_grab(struct uart_softc *);
+void ns8250_bus_ungrab(struct uart_softc *);
+
+#endif /* _DEV_UART_DEV_NS8250_H_ */
Property changes on: trunk/sys/dev/uart/uart_dev_ns8250.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/dev/uart/uart_dev_pl011.c
===================================================================
--- trunk/sys/dev/uart/uart_dev_pl011.c (rev 0)
+++ trunk/sys/dev/uart/uart_dev_pl011.c 2018-05-27 22:53:06 UTC (rev 10057)
@@ -0,0 +1,497 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012 Semihalf.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/dev/uart/uart_dev_pl011.c 283327 2015-05-23 20:54:25Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/bus.h>
+#include <machine/bus.h>
+
+#include <dev/uart/uart.h>
+#include <dev/uart/uart_cpu.h>
+#include <dev/uart/uart_cpu_fdt.h>
+#include <dev/uart/uart_bus.h>
+#include "uart_if.h"
+
+#include <sys/kdb.h>
+
+/* PL011 UART registers and masks*/
+#define UART_DR 0x00 /* Data register */
+#define DR_FE (1 << 8) /* Framing error */
+#define DR_PE (1 << 9) /* Parity error */
+#define DR_BE (1 << 10) /* Break error */
+#define DR_OE (1 << 11) /* Overrun error */
+
+#define UART_FR 0x06 /* Flag register */
+#define FR_TXFF (1 << 5) /* Transmit FIFO/reg full */
+#define FR_RXFF (1 << 6) /* Receive FIFO/reg full */
+#define FR_TXFE (1 << 7) /* Transmit FIFO/reg empty */
+
+#define UART_IBRD 0x09 /* Integer baud rate register */
+#define IBRD_BDIVINT 0xffff /* Significant part of int. divisor value */
+
+#define UART_FBRD 0x0a /* Fractional baud rate register */
+#define FBRD_BDIVFRAC 0x3f /* Significant part of frac. divisor value */
+
+#define UART_LCR_H 0x0b /* Line control register */
+#define LCR_H_WLEN8 (0x3 << 5)
+#define LCR_H_WLEN7 (0x2 << 5)
+#define LCR_H_WLEN6 (0x1 << 5)
+#define LCR_H_FEN (1 << 4) /* FIFO mode enable */
+#define LCR_H_STP2 (1 << 3) /* 2 stop frames at the end */
+#define LCR_H_EPS (1 << 2) /* Even parity select */
+#define LCR_H_PEN (1 << 1) /* Parity enable */
+
+#define UART_CR 0x0c /* Control register */
+#define CR_RXE (1 << 9) /* Receive enable */
+#define CR_TXE (1 << 8) /* Transmit enable */
+#define CR_UARTEN (1 << 0) /* UART enable */
+
+#define UART_IMSC 0x0e /* Interrupt mask set/clear register */
+#define IMSC_MASK_ALL 0x7ff /* Mask all interrupts */
+
+#define UART_RIS 0x0f /* Raw interrupt status register */
+#define UART_RXREADY (1 << 4) /* RX buffer full */
+#define UART_TXEMPTY (1 << 5) /* TX buffer empty */
+#define RIS_RTIM (1 << 6) /* Receive timeout */
+#define RIS_FE (1 << 7) /* Framing error interrupt status */
+#define RIS_PE (1 << 8) /* Parity error interrupt status */
+#define RIS_BE (1 << 9) /* Break error interrupt status */
+#define RIS_OE (1 << 10) /* Overrun interrupt status */
+
+#define UART_MIS 0x10 /* Masked interrupt status register */
+#define UART_ICR 0x11 /* Interrupt clear register */
+
+/*
+ * FIXME: actual register size is SoC-dependent, we need to handle it
+ */
+#define __uart_getreg(bas, reg) \
+ bus_space_read_4((bas)->bst, (bas)->bsh, uart_regofs(bas, reg))
+#define __uart_setreg(bas, reg, value) \
+ bus_space_write_4((bas)->bst, (bas)->bsh, uart_regofs(bas, reg), value)
+
+/*
+ * Low-level UART interface.
+ */
+static int uart_pl011_probe(struct uart_bas *bas);
+static void uart_pl011_init(struct uart_bas *bas, int, int, int, int);
+static void uart_pl011_term(struct uart_bas *bas);
+static void uart_pl011_putc(struct uart_bas *bas, int);
+static int uart_pl011_rxready(struct uart_bas *bas);
+static int uart_pl011_getc(struct uart_bas *bas, struct mtx *);
+
+static struct uart_ops uart_pl011_ops = {
+ .probe = uart_pl011_probe,
+ .init = uart_pl011_init,
+ .term = uart_pl011_term,
+ .putc = uart_pl011_putc,
+ .rxready = uart_pl011_rxready,
+ .getc = uart_pl011_getc,
+};
+
+static int
+uart_pl011_probe(struct uart_bas *bas)
+{
+
+ return (0);
+}
+
+static void
+uart_pl011_param(struct uart_bas *bas, int baudrate, int databits, int stopbits,
+ int parity)
+{
+ uint32_t ctrl, line;
+ uint32_t baud;
+
+ /*
+ * Zero all settings to make sure
+ * UART is disabled and not configured
+ */
+ ctrl = line = 0x0;
+ __uart_setreg(bas, UART_CR, ctrl);
+
+ /* As we know UART is disabled we may setup the line */
+ switch (databits) {
+ case 7:
+ line |= LCR_H_WLEN7;
+ break;
+ case 6:
+ line |= LCR_H_WLEN6;
+ break;
+ case 8:
+ default:
+ line |= LCR_H_WLEN8;
+ break;
+ }
+
+ if (stopbits == 2)
+ line |= LCR_H_STP2;
+ else
+ line &= ~LCR_H_STP2;
+
+ if (parity)
+ line |= LCR_H_PEN;
+ else
+ line &= ~LCR_H_PEN;
+
+ /* Configure the rest */
+ line &= ~LCR_H_FEN;
+ ctrl |= (CR_RXE | CR_TXE | CR_UARTEN);
+
+ if (bas->rclk != 0 && baudrate != 0) {
+ baud = bas->rclk * 4 / baudrate;
+ __uart_setreg(bas, UART_IBRD, ((uint32_t)(baud >> 6)) & IBRD_BDIVINT);
+ __uart_setreg(bas, UART_FBRD, (uint32_t)(baud & 0x3F) & FBRD_BDIVFRAC);
+ }
+
+ /* Add config. to line before reenabling UART */
+ __uart_setreg(bas, UART_LCR_H, (__uart_getreg(bas, UART_LCR_H) &
+ ~0xff) | line);
+
+ __uart_setreg(bas, UART_CR, ctrl);
+}
+
+static void
+uart_pl011_init(struct uart_bas *bas, int baudrate, int databits, int stopbits,
+ int parity)
+{
+ /* Mask all interrupts */
+ __uart_setreg(bas, UART_IMSC, __uart_getreg(bas, UART_IMSC) &
+ ~IMSC_MASK_ALL);
+
+ uart_pl011_param(bas, baudrate, databits, stopbits, parity);
+}
+
+static void
+uart_pl011_term(struct uart_bas *bas)
+{
+}
+
+static void
+uart_pl011_putc(struct uart_bas *bas, int c)
+{
+
+ /* Wait when TX FIFO full. Push character otherwise. */
+ while (__uart_getreg(bas, UART_FR) & FR_TXFF)
+ ;
+ __uart_setreg(bas, UART_DR, c & 0xff);
+}
+
+static int
+uart_pl011_rxready(struct uart_bas *bas)
+{
+
+ return (__uart_getreg(bas, UART_FR) & FR_RXFF);
+}
+
+static int
+uart_pl011_getc(struct uart_bas *bas, struct mtx *hwmtx)
+{
+ int c;
+
+ while (!uart_pl011_rxready(bas))
+ ;
+ c = __uart_getreg(bas, UART_DR) & 0xff;
+
+ return (c);
+}
+
+/*
+ * High-level UART interface.
+ */
+struct uart_pl011_softc {
+ struct uart_softc base;
+ uint8_t fcr;
+ uint8_t ier;
+ uint8_t mcr;
+
+ uint8_t ier_mask;
+ uint8_t ier_rxbits;
+};
+
+static int uart_pl011_bus_attach(struct uart_softc *);
+static int uart_pl011_bus_detach(struct uart_softc *);
+static int uart_pl011_bus_flush(struct uart_softc *, int);
+static int uart_pl011_bus_getsig(struct uart_softc *);
+static int uart_pl011_bus_ioctl(struct uart_softc *, int, intptr_t);
+static int uart_pl011_bus_ipend(struct uart_softc *);
+static int uart_pl011_bus_param(struct uart_softc *, int, int, int, int);
+static int uart_pl011_bus_probe(struct uart_softc *);
+static int uart_pl011_bus_receive(struct uart_softc *);
+static int uart_pl011_bus_setsig(struct uart_softc *, int);
+static int uart_pl011_bus_transmit(struct uart_softc *);
+static void uart_pl011_bus_grab(struct uart_softc *);
+static void uart_pl011_bus_ungrab(struct uart_softc *);
+
+static kobj_method_t uart_pl011_methods[] = {
+ KOBJMETHOD(uart_attach, uart_pl011_bus_attach),
+ KOBJMETHOD(uart_detach, uart_pl011_bus_detach),
+ KOBJMETHOD(uart_flush, uart_pl011_bus_flush),
+ KOBJMETHOD(uart_getsig, uart_pl011_bus_getsig),
+ KOBJMETHOD(uart_ioctl, uart_pl011_bus_ioctl),
+ KOBJMETHOD(uart_ipend, uart_pl011_bus_ipend),
+ KOBJMETHOD(uart_param, uart_pl011_bus_param),
+ KOBJMETHOD(uart_probe, uart_pl011_bus_probe),
+ KOBJMETHOD(uart_receive, uart_pl011_bus_receive),
+ KOBJMETHOD(uart_setsig, uart_pl011_bus_setsig),
+ KOBJMETHOD(uart_transmit, uart_pl011_bus_transmit),
+ KOBJMETHOD(uart_grab, uart_pl011_bus_grab),
+ KOBJMETHOD(uart_ungrab, uart_pl011_bus_ungrab),
+
+ { 0, 0 }
+};
+
+static struct uart_class uart_pl011_class = {
+ "uart_pl011",
+ uart_pl011_methods,
+ sizeof(struct uart_pl011_softc),
+ .uc_ops = &uart_pl011_ops,
+ .uc_range = 0x48,
+ .uc_rclk = 0
+};
+
+static struct ofw_compat_data compat_data[] = {
+ {"arm,pl011", (uintptr_t)&uart_pl011_class},
+ {NULL, (uintptr_t)NULL},
+};
+UART_FDT_CLASS_AND_DEVICE(compat_data);
+
+static int
+uart_pl011_bus_attach(struct uart_softc *sc)
+{
+ struct uart_bas *bas;
+ int reg;
+
+ bas = &sc->sc_bas;
+
+ /* Enable interrupts */
+ reg = (UART_RXREADY | RIS_RTIM | UART_TXEMPTY);
+ __uart_setreg(bas, UART_IMSC, reg);
+
+ /* Clear interrupts */
+ __uart_setreg(bas, UART_ICR, IMSC_MASK_ALL);
+
+ return (0);
+}
+
+static int
+uart_pl011_bus_detach(struct uart_softc *sc)
+{
+
+ return (0);
+}
+
+static int
+uart_pl011_bus_flush(struct uart_softc *sc, int what)
+{
+
+ return (0);
+}
+
+static int
+uart_pl011_bus_getsig(struct uart_softc *sc)
+{
+
+ return (0);
+}
+
+static int
+uart_pl011_bus_ioctl(struct uart_softc *sc, int request, intptr_t data)
+{
+ struct uart_bas *bas;
+ int error;
+
+ bas = &sc->sc_bas;
+ error = 0;
+ uart_lock(sc->sc_hwmtx);
+ switch (request) {
+ case UART_IOCTL_BREAK:
+ break;
+ case UART_IOCTL_BAUD:
+ *(int*)data = 115200;
+ break;
+ default:
+ error = EINVAL;
+ break;
+ }
+ uart_unlock(sc->sc_hwmtx);
+
+ return (error);
+}
+
+static int
+uart_pl011_bus_ipend(struct uart_softc *sc)
+{
+ struct uart_bas *bas;
+ uint32_t ints;
+ int ipend;
+ int reg;
+
+ bas = &sc->sc_bas;
+ uart_lock(sc->sc_hwmtx);
+ ints = __uart_getreg(bas, UART_MIS);
+ ipend = 0;
+
+ if (ints & (UART_RXREADY | RIS_RTIM))
+ ipend |= SER_INT_RXREADY;
+ if (ints & RIS_BE)
+ ipend |= SER_INT_BREAK;
+ if (ints & RIS_OE)
+ ipend |= SER_INT_OVERRUN;
+ if (ints & UART_TXEMPTY) {
+ if (sc->sc_txbusy)
+ ipend |= SER_INT_TXIDLE;
+
+ /* Disable TX interrupt */
+ reg = __uart_getreg(bas, UART_IMSC);
+ reg &= ~(UART_TXEMPTY);
+ __uart_setreg(bas, UART_IMSC, reg);
+ }
+
+ uart_unlock(sc->sc_hwmtx);
+
+ return (ipend);
+}
+
+static int
+uart_pl011_bus_param(struct uart_softc *sc, int baudrate, int databits,
+ int stopbits, int parity)
+{
+
+ uart_lock(sc->sc_hwmtx);
+ uart_pl011_param(&sc->sc_bas, baudrate, databits, stopbits, parity);
+ uart_unlock(sc->sc_hwmtx);
+
+ return (0);
+}
+
+static int
+uart_pl011_bus_probe(struct uart_softc *sc)
+{
+
+ device_set_desc(sc->sc_dev, "PrimeCell UART (PL011)");
+
+ sc->sc_rxfifosz = 1;
+ sc->sc_txfifosz = 1;
+
+ return (0);
+}
+
+static int
+uart_pl011_bus_receive(struct uart_softc *sc)
+{
+ struct uart_bas *bas;
+ uint32_t ints, xc;
+ int rx;
+
+ bas = &sc->sc_bas;
+ uart_lock(sc->sc_hwmtx);
+
+ ints = __uart_getreg(bas, UART_MIS);
+ while (ints & (UART_RXREADY | RIS_RTIM)) {
+ if (uart_rx_full(sc)) {
+ sc->sc_rxbuf[sc->sc_rxput] = UART_STAT_OVERRUN;
+ break;
+ }
+ xc = __uart_getreg(bas, UART_DR);
+ rx = xc & 0xff;
+
+ if (xc & DR_FE)
+ rx |= UART_STAT_FRAMERR;
+ if (xc & DR_PE)
+ rx |= UART_STAT_PARERR;
+
+ __uart_setreg(bas, UART_ICR, (UART_RXREADY | RIS_RTIM));
+
+ uart_rx_put(sc, rx);
+ ints = __uart_getreg(bas, UART_MIS);
+ }
+
+ uart_unlock(sc->sc_hwmtx);
+
+ return (0);
+}
+
+static int
+uart_pl011_bus_setsig(struct uart_softc *sc, int sig)
+{
+
+ return (0);
+}
+
+static int
+uart_pl011_bus_transmit(struct uart_softc *sc)
+{
+ struct uart_bas *bas;
+ int reg;
+ int i;
+
+ bas = &sc->sc_bas;
+ uart_lock(sc->sc_hwmtx);
+
+ for (i = 0; i < sc->sc_txdatasz; i++) {
+ __uart_setreg(bas, UART_DR, sc->sc_txbuf[i]);
+ uart_barrier(bas);
+ }
+ sc->sc_txbusy = 1;
+
+ /* Enable TX interrupt */
+ reg = __uart_getreg(bas, UART_IMSC);
+ reg |= (UART_TXEMPTY);
+ __uart_setreg(bas, UART_IMSC, reg);
+
+ uart_unlock(sc->sc_hwmtx);
+
+ return (0);
+}
+
+static void
+uart_pl011_bus_grab(struct uart_softc *sc)
+{
+ struct uart_bas *bas;
+
+ bas = &sc->sc_bas;
+ uart_lock(sc->sc_hwmtx);
+ __uart_setreg(bas, UART_IMSC, /* Switch to RX polling while grabbed */
+ ~UART_RXREADY & __uart_getreg(bas, UART_IMSC));
+ uart_unlock(sc->sc_hwmtx);
+}
+
+static void
+uart_pl011_bus_ungrab(struct uart_softc *sc)
+{
+ struct uart_bas *bas;
+
+ bas = &sc->sc_bas;
+ uart_lock(sc->sc_hwmtx);
+ __uart_setreg(bas, UART_IMSC, /* Switch to RX interrupts while not grabbed */
+ UART_RXREADY | __uart_getreg(bas, UART_IMSC));
+ uart_unlock(sc->sc_hwmtx);
+}
Property changes on: trunk/sys/dev/uart/uart_dev_pl011.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Modified: trunk/sys/dev/uart/uart_dev_quicc.c
===================================================================
--- trunk/sys/dev/uart/uart_dev_quicc.c 2018-05-27 22:50:50 UTC (rev 10056)
+++ trunk/sys/dev/uart/uart_dev_quicc.c 2018-05-27 22:53:06 UTC (rev 10057)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 2006 Juniper Networks
* All rights reserved.
@@ -25,7 +26,7 @@
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/10/sys/dev/uart/uart_dev_quicc.c 262649 2014-03-01 04:16:54Z imp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -245,6 +246,8 @@
static int quicc_bus_receive(struct uart_softc *);
static int quicc_bus_setsig(struct uart_softc *, int);
static int quicc_bus_transmit(struct uart_softc *);
+static void quicc_bus_grab(struct uart_softc *);
+static void quicc_bus_ungrab(struct uart_softc *);
static kobj_method_t quicc_methods[] = {
KOBJMETHOD(uart_attach, quicc_bus_attach),
@@ -258,6 +261,8 @@
KOBJMETHOD(uart_receive, quicc_bus_receive),
KOBJMETHOD(uart_setsig, quicc_bus_setsig),
KOBJMETHOD(uart_transmit, quicc_bus_transmit),
+ KOBJMETHOD(uart_grab, quicc_bus_grab),
+ KOBJMETHOD(uart_ungrab, quicc_bus_ungrab),
{ 0, 0 }
};
@@ -293,9 +298,6 @@
quicc_setup(bas, 9600, 8, 1, UART_PARITY_NONE);
}
- sc->sc_rxfifosz = 1;
- sc->sc_txfifosz = 1;
-
/* Enable interrupts on the receive buffer. */
rb = quicc_read2(bas, QUICC_PRAM_SCC_RBASE(bas->chan - 1));
st = quicc_read2(bas, rb);
@@ -417,6 +419,9 @@
if (error)
return (error);
+ sc->sc_rxfifosz = 1;
+ sc->sc_txfifosz = 1;
+
snprintf(buf, sizeof(buf), "quicc, channel %d", sc->sc_bas.chan);
device_set_desc_copy(sc->sc_dev, buf);
return (0);
@@ -485,3 +490,34 @@
uart_unlock(sc->sc_hwmtx);
return (0);
}
+
+static void
+quicc_bus_grab(struct uart_softc *sc)
+{
+ struct uart_bas *bas;
+ uint16_t st, rb;
+
+ /* Disable interrupts on the receive buffer. */
+ bas = &sc->sc_bas;
+ uart_lock(sc->sc_hwmtx);
+ rb = quicc_read2(bas, QUICC_PRAM_SCC_RBASE(bas->chan - 1));
+ st = quicc_read2(bas, rb);
+ quicc_write2(bas, rb, st & ~0x9000);
+ uart_unlock(sc->sc_hwmtx);
+}
+
+static void
+quicc_bus_ungrab(struct uart_softc *sc)
+{
+ struct uart_bas *bas;
+ uint16_t st, rb;
+
+ /* Enable interrupts on the receive buffer. */
+ bas = &sc->sc_bas;
+ uart_lock(sc->sc_hwmtx);
+ rb = quicc_read2(bas, QUICC_PRAM_SCC_RBASE(bas->chan - 1));
+ st = quicc_read2(bas, rb);
+ quicc_write2(bas, rb, st | 0x9000);
+ uart_unlock(sc->sc_hwmtx);
+}
+
Modified: trunk/sys/dev/uart/uart_dev_sab82532.c
===================================================================
--- trunk/sys/dev/uart/uart_dev_sab82532.c 2018-05-27 22:50:50 UTC (rev 10056)
+++ trunk/sys/dev/uart/uart_dev_sab82532.c 2018-05-27 22:53:06 UTC (rev 10057)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 2003 Marcel Moolenaar
* All rights reserved.
@@ -25,7 +26,7 @@
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/10/sys/dev/uart/uart_dev_sab82532.c 262649 2014-03-01 04:16:54Z imp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -365,6 +366,8 @@
static int sab82532_bus_receive(struct uart_softc *);
static int sab82532_bus_setsig(struct uart_softc *, int);
static int sab82532_bus_transmit(struct uart_softc *);
+static void sab82532_bus_grab(struct uart_softc *);
+static void sab82532_bus_ungrab(struct uart_softc *);
static kobj_method_t sab82532_methods[] = {
KOBJMETHOD(uart_attach, sab82532_bus_attach),
@@ -378,6 +381,8 @@
KOBJMETHOD(uart_receive, sab82532_bus_receive),
KOBJMETHOD(uart_setsig, sab82532_bus_setsig),
KOBJMETHOD(uart_transmit, sab82532_bus_transmit),
+ KOBJMETHOD(uart_grab, sab82532_bus_grab),
+ KOBJMETHOD(uart_ungrab, sab82532_bus_ungrab),
{ 0, 0 }
};
@@ -407,9 +412,6 @@
if (sc->sc_sysdev == NULL)
sab82532_init(bas, 9600, 8, 1, UART_PARITY_NONE);
- sc->sc_rxfifosz = 32;
- sc->sc_txfifosz = 32;
-
imr0 = SAB_IMR0_TCD|SAB_IMR0_TIME|SAB_IMR0_CDSC|SAB_IMR0_RFO|
SAB_IMR0_RPF;
uart_setreg(bas, SAB_IMR0, 0xff & ~imr0);
@@ -592,6 +594,9 @@
if (error)
return (error);
+ sc->sc_rxfifosz = 32;
+ sc->sc_txfifosz = 32;
+
ch = sc->sc_bas.chan - 1 + 'A';
switch (uart_getreg(&sc->sc_bas, SAB_VSTR) & SAB_VSTR_VMASK) {
@@ -724,3 +729,32 @@
uart_unlock(sc->sc_hwmtx);
return (0);
}
+
+static void
+sab82532_bus_grab(struct uart_softc *sc)
+{
+ struct uart_bas *bas;
+ uint8_t imr0;
+
+ bas = &sc->sc_bas;
+ imr0 = SAB_IMR0_TIME|SAB_IMR0_CDSC|SAB_IMR0_RFO; /* No TCD or RPF */
+ uart_lock(sc->sc_hwmtx);
+ uart_setreg(bas, SAB_IMR0, 0xff & ~imr0);
+ uart_barrier(bas);
+ uart_unlock(sc->sc_hwmtx);
+}
+
+static void
+sab82532_bus_ungrab(struct uart_softc *sc)
+{
+ struct uart_bas *bas;
+ uint8_t imr0;
+
+ bas = &sc->sc_bas;
+ imr0 = SAB_IMR0_TCD|SAB_IMR0_TIME|SAB_IMR0_CDSC|SAB_IMR0_RFO|
+ SAB_IMR0_RPF;
+ uart_lock(sc->sc_hwmtx);
+ uart_setreg(bas, SAB_IMR0, 0xff & ~imr0);
+ uart_barrier(bas);
+ uart_unlock(sc->sc_hwmtx);
+}
Added: trunk/sys/dev/uart/uart_dev_ti8250.c
===================================================================
--- trunk/sys/dev/uart/uart_dev_ti8250.c (rev 0)
+++ trunk/sys/dev/uart/uart_dev_ti8250.c 2018-05-27 22:53:06 UTC (rev 10057)
@@ -0,0 +1,147 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 Ian Lepore
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "opt_platform.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/dev/uart/uart_dev_ti8250.c 283327 2015-05-23 20:54:25Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+#include <sys/sysctl.h>
+#include <machine/bus.h>
+
+#include <arm/ti/ti_prcm.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <dev/uart/uart.h>
+#include <dev/uart/uart_cpu.h>
+#include <dev/uart/uart_cpu_fdt.h>
+#include <dev/uart/uart_bus.h>
+#include <dev/uart/uart_dev_ns8250.h>
+
+#include "uart_if.h"
+
+/*
+ * High-level UART interface.
+ */
+struct ti8250_softc {
+ struct ns8250_softc ns8250_base;
+ /*uint32_t mystuff;*/
+};
+
+#define MDR1_REG 8
+#define MDR1_MODE_UART 0
+#define MDR1_MODE_DISABLE 7
+#define SYSCC_REG 15
+#define SYSCC_SOFTRESET (1 << 1)
+#define SYSS_REG 16
+#define SYSS_STATUS_RESETDONE (1 << 0)
+
+static int
+ti8250_bus_probe(struct uart_softc *sc)
+{
+ int status;
+ int devid;
+ clk_ident_t clkid;
+ pcell_t prop;
+ phandle_t node;
+
+ /*
+ * Get the device id from FDT. If it's not there we can't turn on the
+ * right clocks, so bail, unless we're doing unit 0. We assume that's
+ * the serial console, whose clock isn't controllable anyway, and we
+ * sure don't want to break the console because of a config error.
+ */
+ node = ofw_bus_get_node(sc->sc_dev);
+ if ((OF_getprop(node, "uart-device-id", &prop, sizeof(prop))) <= 0) {
+ device_printf(sc->sc_dev,
+ "missing uart-device-id attribute in FDT\n");
+ if (device_get_unit(sc->sc_dev) != 0)
+ return (ENXIO);
+ devid = 0;
+ } else
+ devid = fdt32_to_cpu(prop);
+
+ /* Enable clocks for this device. We can't continue if that fails. */
+ clkid = UART0_CLK + devid;
+ if ((status = ti_prcm_clk_enable(clkid)) != 0)
+ return (status);
+
+ /*
+ * Set the hardware to disabled mode, do a full device reset, then set
+ * it to uart mode. Most devices will be reset-and-disabled already,
+ * but you never know what a bootloader might have done.
+ */
+ uart_setreg(&sc->sc_bas, MDR1_REG, MDR1_MODE_DISABLE);
+ uart_setreg(&sc->sc_bas, SYSCC_REG, SYSCC_SOFTRESET);
+ while (uart_getreg(&sc->sc_bas, SYSS_REG) & SYSS_STATUS_RESETDONE)
+ continue;
+ uart_setreg(&sc->sc_bas, MDR1_REG, MDR1_MODE_UART);
+
+ status = ns8250_bus_probe(sc);
+ if (status == 0)
+ device_set_desc(sc->sc_dev, "TI UART (16550 compatible)");
+
+ return (status);
+}
+
+static kobj_method_t ti8250_methods[] = {
+ KOBJMETHOD(uart_probe, ti8250_bus_probe),
+
+ KOBJMETHOD(uart_attach, ns8250_bus_attach),
+ KOBJMETHOD(uart_detach, ns8250_bus_detach),
+ KOBJMETHOD(uart_flush, ns8250_bus_flush),
+ KOBJMETHOD(uart_getsig, ns8250_bus_getsig),
+ KOBJMETHOD(uart_ioctl, ns8250_bus_ioctl),
+ KOBJMETHOD(uart_ipend, ns8250_bus_ipend),
+ KOBJMETHOD(uart_param, ns8250_bus_param),
+ KOBJMETHOD(uart_receive, ns8250_bus_receive),
+ KOBJMETHOD(uart_setsig, ns8250_bus_setsig),
+ KOBJMETHOD(uart_transmit, ns8250_bus_transmit),
+ KOBJMETHOD_END
+};
+
+static struct uart_class uart_ti8250_class = {
+ "ti8250",
+ ti8250_methods,
+ sizeof(struct ti8250_softc),
+ .uc_ops = &uart_ns8250_ops,
+ .uc_range = 0x88,
+ .uc_rclk = 48000000
+};
+static struct ofw_compat_data compat_data[] = {
+ {"ti,ns16550", (uintptr_t)&uart_ti8250_class},
+ {NULL, (uintptr_t)NULL},
+};
+UART_FDT_CLASS_AND_DEVICE(compat_data);
Property changes on: trunk/sys/dev/uart/uart_dev_ti8250.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Modified: trunk/sys/dev/uart/uart_dev_z8530.c
===================================================================
--- trunk/sys/dev/uart/uart_dev_z8530.c 2018-05-27 22:50:50 UTC (rev 10056)
+++ trunk/sys/dev/uart/uart_dev_z8530.c 2018-05-27 22:53:06 UTC (rev 10057)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 2003 Marcel Moolenaar
* All rights reserved.
@@ -25,7 +26,7 @@
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/10/sys/dev/uart/uart_dev_z8530.c 262649 2014-03-01 04:16:54Z imp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -281,6 +282,8 @@
static int z8530_bus_receive(struct uart_softc *);
static int z8530_bus_setsig(struct uart_softc *, int);
static int z8530_bus_transmit(struct uart_softc *);
+static void z8530_bus_grab(struct uart_softc *);
+static void z8530_bus_ungrab(struct uart_softc *);
static kobj_method_t z8530_methods[] = {
KOBJMETHOD(uart_attach, z8530_bus_attach),
@@ -294,6 +297,8 @@
KOBJMETHOD(uart_receive, z8530_bus_receive),
KOBJMETHOD(uart_setsig, z8530_bus_setsig),
KOBJMETHOD(uart_transmit, z8530_bus_transmit),
+ KOBJMETHOD(uart_grab, z8530_bus_grab),
+ KOBJMETHOD(uart_ungrab, z8530_bus_ungrab),
{ 0, 0 }
};
@@ -332,9 +337,6 @@
}
z8530->txidle = 1; /* Report SER_INT_TXIDLE. */
- sc->sc_rxfifosz = 3;
- sc->sc_txfifosz = 1;
-
(void)z8530_bus_getsig(sc);
uart_setmreg(bas, WR_IC, IC_BRK | IC_CTS | IC_DCD);
@@ -515,6 +517,9 @@
if (error)
return (error);
+ sc->sc_rxfifosz = 3;
+ sc->sc_txfifosz = 1;
+
ch = sc->sc_bas.chan - 1 + 'A';
snprintf(buf, sizeof(buf), "z8530, channel %c", ch);
@@ -621,3 +626,27 @@
uart_unlock(sc->sc_hwmtx);
return (0);
}
+
+static void
+z8530_bus_grab(struct uart_softc *sc)
+{
+ struct uart_bas *bas;
+
+ bas = &sc->sc_bas;
+ uart_lock(sc->sc_hwmtx);
+ uart_setmreg(bas, WR_IDT, IDT_XIE | IDT_TIE);
+ uart_barrier(bas);
+ uart_unlock(sc->sc_hwmtx);
+}
+
+static void
+z8530_bus_ungrab(struct uart_softc *sc)
+{
+ struct uart_bas *bas;
+
+ bas = &sc->sc_bas;
+ uart_lock(sc->sc_hwmtx);
+ uart_setmreg(bas, WR_IDT, IDT_XIE | IDT_TIE | IDT_RIA);
+ uart_barrier(bas);
+ uart_unlock(sc->sc_hwmtx);
+}
Modified: trunk/sys/dev/uart/uart_if.m
===================================================================
--- trunk/sys/dev/uart/uart_if.m 2018-05-27 22:50:50 UTC (rev 10056)
+++ trunk/sys/dev/uart/uart_if.m 2018-05-27 22:53:06 UTC (rev 10057)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
#-
# Copyright (c) 2003 Marcel Moolenaar
# All rights reserved.
@@ -23,9 +24,10 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
-# $MidnightBSD$
+# $FreeBSD: stable/10/sys/dev/uart/uart_if.m 262649 2014-03-01 04:16:54Z imp $
#include <sys/param.h>
+#include <sys/systm.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/bus.h>
@@ -140,3 +142,19 @@
METHOD int transmit {
struct uart_softc *this;
};
+
+# grab() - Up call from the console to the upper layers of the driver when
+# the kernel asks to grab the console. This is valid only for console
+# drivers. This method is responsible for transitioning the hardware
+# from an interrupt driven state to a polled state that works with the
+# low-level console interface defined for this device. The kernel
+# currently only calls this when it wants to grab input from the
+# console. Output can still happen asyncrhonously to these calls.
+METHOD void grab {
+ struct uart_softc *this;
+};
+
+# ungrab() - Undoes the effects of grab().
+METHOD void ungrab {
+ struct uart_softc *this;
+};
Property changes on: trunk/sys/dev/uart/uart_if.m
___________________________________________________________________
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Modified: trunk/sys/dev/uart/uart_kbd_sun.c
===================================================================
--- trunk/sys/dev/uart/uart_kbd_sun.c 2018-05-27 22:50:50 UTC (rev 10056)
+++ trunk/sys/dev/uart/uart_kbd_sun.c 2018-05-27 22:53:06 UTC (rev 10057)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 2003 Jake Burkholder.
* All rights reserved.
@@ -25,7 +26,7 @@
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/10/sys/dev/uart/uart_kbd_sun.c 224126 2011-07-17 08:19:19Z ed $");
#include "opt_compat.h"
#include "opt_kbd.h"
Modified: trunk/sys/dev/uart/uart_kbd_sun.h
===================================================================
--- trunk/sys/dev/uart/uart_kbd_sun.h 2018-05-27 22:50:50 UTC (rev 10056)
+++ trunk/sys/dev/uart/uart_kbd_sun.h 2018-05-27 22:53:06 UTC (rev 10057)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 2002 Jason L. Wright (jason at thought.net)
* All rights reserved.
@@ -32,7 +33,7 @@
* Agency (DARPA) and Air Force Research Laboratory, Air Force
* Materiel Command, USAF, under agreement number F30602-01-2-0537.
*
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/dev/uart/uart_kbd_sun.h 163890 2006-11-02 00:01:15Z marius $
*/
/* keyboard commands (host->kbd) */
Modified: trunk/sys/dev/uart/uart_kbd_sun_tables.h
===================================================================
--- trunk/sys/dev/uart/uart_kbd_sun_tables.h 2018-05-27 22:50:50 UTC (rev 10056)
+++ trunk/sys/dev/uart/uart_kbd_sun_tables.h 2018-05-27 22:53:06 UTC (rev 10057)
@@ -1,8 +1,9 @@
+/* $MidnightBSD$ */
/*
* Automatically generated from sun.us.unix.kbd.
* DO NOT EDIT!
*
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/dev/uart/uart_kbd_sun_tables.h 122470 2003-11-11 07:33:24Z jake $
*/
static keymap_t keymap_sun_us_unix_kbd = { 0x80, {
/* alt
Added: trunk/sys/dev/uart/uart_ppstypes.h
===================================================================
--- trunk/sys/dev/uart/uart_ppstypes.h (rev 0)
+++ trunk/sys/dev/uart/uart_ppstypes.h 2018-05-27 22:53:06 UTC (rev 10057)
@@ -0,0 +1,47 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2015 Ian Lepore
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/dev/uart/uart_ppstypes.h 294229 2016-01-17 18:18:01Z ian $
+ */
+
+#ifndef _DEV_UART_PPSTYPES_H_
+#define _DEV_UART_PPSTYPES_H_
+
+/*
+ * These constants are shared by several drivers including uart and usb_serial.
+ */
+
+#define UART_PPS_SIGNAL_MASK 0x0f
+#define UART_PPS_OPTION_MASK 0xf0
+
+#define UART_PPS_DISABLED 0x00
+#define UART_PPS_CTS 0x01
+#define UART_PPS_DCD 0x02
+
+#define UART_PPS_INVERT_PULSE 0x10
+#define UART_PPS_NARROW_PULSE 0x20
+
+#endif /* _DEV_UART_PPSTYPES_H_ */
Property changes on: trunk/sys/dev/uart/uart_ppstypes.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Modified: trunk/sys/dev/uart/uart_subr.c
===================================================================
--- trunk/sys/dev/uart/uart_subr.c 2018-05-27 22:50:50 UTC (rev 10056)
+++ trunk/sys/dev/uart/uart_subr.c 2018-05-27 22:53:06 UTC (rev 10057)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 2004 Marcel Moolenaar
* All rights reserved.
@@ -25,7 +26,7 @@
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/10/sys/dev/uart/uart_subr.c 283327 2015-05-23 20:54:25Z ian $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -52,17 +53,20 @@
&uart_ns8250_class,
&uart_sab82532_class,
&uart_z8530_class,
+#if defined(__arm__)
+ &uart_s3c2410_class,
+#endif
};
static size_t uart_nclasses = sizeof(uart_classes) / sizeof(uart_classes[0]);
static bus_addr_t
-uart_parse_addr(__const char **p)
+uart_parse_addr(const char **p)
{
return (strtoul(*p, (char**)(uintptr_t)p, 0));
}
static struct uart_class *
-uart_parse_class(struct uart_class *class, __const char **p)
+uart_parse_class(struct uart_class *class, const char **p)
{
struct uart_class *uc;
const char *nm;
@@ -84,13 +88,13 @@
}
static long
-uart_parse_long(__const char **p)
+uart_parse_long(const char **p)
{
return (strtol(*p, (char**)(uintptr_t)p, 0));
}
static int
-uart_parse_parity(__const char **p)
+uart_parse_parity(const char **p)
{
if (!strncmp(*p, "even", 4)) {
*p += 4;
@@ -116,7 +120,7 @@
}
static int
-uart_parse_tag(__const char **p)
+uart_parse_tag(const char **p)
{
int tag;
@@ -192,7 +196,7 @@
int
uart_getenv(int devtype, struct uart_devinfo *di, struct uart_class *class)
{
- __const char *spec;
+ const char *spec;
bus_addr_t addr = ~0U;
int error;
Modified: trunk/sys/dev/uart/uart_tty.c
===================================================================
--- trunk/sys/dev/uart/uart_tty.c 2018-05-27 22:50:50 UTC (rev 10056)
+++ trunk/sys/dev/uart/uart_tty.c 2018-05-27 22:53:06 UTC (rev 10057)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 2003 Marcel Moolenaar
* All rights reserved.
@@ -25,7 +26,7 @@
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/10/sys/dev/uart/uart_tty.c 294959 2016-01-27 22:48:04Z marius $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -57,6 +58,16 @@
static cn_grab_t uart_cngrab;
static cn_ungrab_t uart_cnungrab;
+static tsw_open_t uart_tty_open;
+static tsw_close_t uart_tty_close;
+static tsw_outwakeup_t uart_tty_outwakeup;
+static tsw_inwakeup_t uart_tty_inwakeup;
+static tsw_ioctl_t uart_tty_ioctl;
+static tsw_param_t uart_tty_param;
+static tsw_modem_t uart_tty_modem;
+static tsw_free_t uart_tty_free;
+static tsw_busy_t uart_tty_busy;
+
CONSOLE_DRIVER(uart);
static struct uart_devinfo uart_console;
@@ -112,11 +123,15 @@
static void
uart_cngrab(struct consdev *cp)
{
+
+ uart_grab(cp->cn_arg);
}
static void
uart_cnungrab(struct consdev *cp)
{
+
+ uart_ungrab(cp->cn_arg);
}
static void
@@ -153,7 +168,7 @@
struct uart_softc *sc;
sc = tty_softc(tp);
- if (sc == NULL || sc->sc_leaving || !sc->sc_opened)
+ if (sc == NULL || sc->sc_leaving || !sc->sc_opened)
return;
if (sc->sc_hwiflow)
@@ -165,7 +180,6 @@
wakeup(sc);
sc->sc_opened = 0;
- return;
}
static void
@@ -211,7 +225,8 @@
}
static int
-uart_tty_ioctl(struct tty *tp, u_long cmd, caddr_t data, struct thread *td)
+uart_tty_ioctl(struct tty *tp, u_long cmd, caddr_t data,
+ struct thread *td __unused)
{
struct uart_softc *sc;
@@ -258,8 +273,8 @@
}
stopbits = (t->c_cflag & CSTOPB) ? 2 : 1;
if (t->c_cflag & PARENB)
- parity = (t->c_cflag & PARODD) ? UART_PARITY_ODD
- : UART_PARITY_EVEN;
+ parity = (t->c_cflag & PARODD) ? UART_PARITY_ODD :
+ UART_PARITY_EVEN;
else
parity = UART_PARITY_NONE;
if (UART_PARAM(sc, t->c_ospeed, databits, stopbits, parity) != 0)
@@ -287,7 +302,7 @@
sc = tty_softc(tp);
if (biton != 0 || bitoff != 0)
- UART_SETSIG(sc, SER_DELTA(bitoff|biton) | biton);
+ UART_SETSIG(sc, SER_DELTA(bitoff | biton) | biton);
return (sc->sc_hwsig);
}
@@ -346,7 +361,7 @@
}
static void
-uart_tty_free(void *arg)
+uart_tty_free(void *arg __unused)
{
/*
@@ -357,6 +372,18 @@
*/
}
+static bool
+uart_tty_busy(struct tty *tp)
+{
+ struct uart_softc *sc;
+
+ sc = tty_softc(tp);
+ if (sc == NULL || sc->sc_leaving)
+ return (FALSE);
+
+ return (sc->sc_txbusy);
+}
+
static struct ttydevsw uart_tty_class = {
.tsw_flags = TF_INITLOCK|TF_CALLOUT,
.tsw_open = uart_tty_open,
@@ -367,6 +394,7 @@
.tsw_param = uart_tty_param,
.tsw_modem = uart_tty_modem,
.tsw_free = uart_tty_free,
+ .tsw_busy = uart_tty_busy,
};
int
@@ -406,3 +434,13 @@
return (0);
}
+
+struct mtx *
+uart_tty_getlock(struct uart_softc *sc)
+{
+
+ if (sc->sc_u.u_tty.tp != NULL)
+ return (tty_getlock(sc->sc_u.u_tty.tp));
+ else
+ return (NULL);
+}
Modified: trunk/sys/dev/ubsec/ubsec.c
===================================================================
--- trunk/sys/dev/ubsec/ubsec.c 2018-05-27 22:50:50 UTC (rev 10056)
+++ trunk/sys/dev/ubsec/ubsec.c 2018-05-27 22:53:06 UTC (rev 10057)
@@ -40,7 +40,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: stable/10/sys/dev/ubsec/ubsec.c 314667 2017-03-04 13:03:31Z avg $");
/*
* uBsec 5[56]01, 58xx hardware crypto accelerator
@@ -260,7 +260,7 @@
static void
default_harvest(struct rndtest_state *rsp, void *buf, u_int count)
{
- random_harvest(buf, count, count*NBBY, 0, RANDOM_PURE);
+ random_harvest(buf, count, count*NBBY/2, RANDOM_PURE_UBSEC);
}
static int
@@ -268,7 +268,7 @@
{
struct ubsec_softc *sc = device_get_softc(dev);
struct ubsec_dma *dmap;
- u_int32_t cmd, i;
+ u_int32_t i;
int rid;
bzero(sc, sizeof (*sc));
@@ -313,21 +313,8 @@
UBS_FLAGS_LONGCTX | UBS_FLAGS_HWNORM | UBS_FLAGS_BIGKEY;
}
- cmd = pci_read_config(dev, PCIR_COMMAND, 4);
- cmd |= PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN;
- pci_write_config(dev, PCIR_COMMAND, cmd, 4);
- cmd = pci_read_config(dev, PCIR_COMMAND, 4);
+ pci_enable_busmaster(dev);
- if (!(cmd & PCIM_CMD_MEMEN)) {
- device_printf(dev, "failed to enable memory mapping\n");
- goto bad;
- }
-
- if (!(cmd & PCIM_CMD_BUSMASTEREN)) {
- device_printf(dev, "failed to enable bus mastering\n");
- goto bad;
- }
-
/*
* Setup memory-mapping of PCI registers.
*/
@@ -470,7 +457,7 @@
sc->sc_rnghz = hz / 100;
else
sc->sc_rnghz = 1;
- callout_init(&sc->sc_rngto, CALLOUT_MPSAFE);
+ callout_init(&sc->sc_rngto, 1);
callout_reset(&sc->sc_rngto, sc->sc_rnghz, ubsec_rng, sc);
skip_rng:
;
Modified: trunk/sys/dev/ubsec/ubsecreg.h
===================================================================
--- trunk/sys/dev/ubsec/ubsecreg.h 2018-05-27 22:50:50 UTC (rev 10056)
+++ trunk/sys/dev/ubsec/ubsecreg.h 2018-05-27 22:53:06 UTC (rev 10057)
@@ -1,5 +1,5 @@
-/* $MidnightBSD: src/sys/dev/ubsec/ubsecreg.h,v 1.2 2008/12/02 22:46:25 laffer1 Exp $ */
-/* $FreeBSD: src/sys/dev/ubsec/ubsecreg.h,v 1.6 2005/01/06 01:43:27 imp Exp $ */
+/* $MidnightBSD$ */
+/* $FreeBSD: stable/10/sys/dev/ubsec/ubsecreg.h 191894 2009-05-07 18:03:47Z philip $ */
/* $OpenBSD: ubsecreg.h,v 1.27 2002/09/11 22:40:31 jason Exp $ */
/*-
Modified: trunk/sys/dev/ubsec/ubsecvar.h
===================================================================
--- trunk/sys/dev/ubsec/ubsecvar.h 2018-05-27 22:50:50 UTC (rev 10056)
+++ trunk/sys/dev/ubsec/ubsecvar.h 2018-05-27 22:53:06 UTC (rev 10057)
@@ -1,5 +1,5 @@
/* $MidnightBSD$ */
-/* $FreeBSD: src/sys/dev/ubsec/ubsecvar.h,v 1.9 2006/05/17 18:34:26 pjd Exp $ */
+/* $FreeBSD: stable/10/sys/dev/ubsec/ubsecvar.h 158705 2006-05-17 18:34:26Z pjd $ */
/* $OpenBSD: ubsecvar.h,v 1.35 2002/09/24 18:33:26 jason Exp $ */
/*-
More information about the Midnightbsd-cvs
mailing list