Patrick Wildt
unread,Aug 3, 2016, 4:36:41 PM8/3/16You do not have permission to delete messages in this group
Either email addresses are anonymous for this group or you need the view member email addresses permission to view the original message
to
Hi,
the Synopsys Designware UART, which is used on a bunch of SoCs, is
mostly compatible to com(4). Currently we use sxiuart, a driver based
on another driver, modified to work on sunxi. I would like to replace
sxiuart with com(4). This diff disables sxiuart and implements the
Allwinner and Synopsys specific code in the existing com(4) wrapper
for OMAP. In a follow up diff we can remove sxiuart completely. Also,
we might want to move it to some other folder and/or rename it. That
should be part of a follow up diff.
There's only a slight twist: The controller has a busy interrupt we
need to handle. Otherwise we will get flooded with interrupts.
mglocker@ is currently experiencing that issue with the sxiuart driver
as well. This diff also implements this busy indicator in com(4).
I guess the com(4) and the armv7 changes should be committed separately.
This diff combines both to show what it will be used for.
I tested it on BBB and Lamobo R1. mglocker@ reported success on his
sunxi-based CHIP.
ok? Comments?
Patrick
diff --git a/sys/arch/armv7/armv7/platform.c b/sys/arch/armv7/armv7/platform.c
index f122c1f..390d907 100644
--- a/sys/arch/armv7/armv7/platform.c
+++ b/sys/arch/armv7/armv7/platform.c
@@ -37,7 +37,6 @@ static struct armv7_platform *platform;
void exuart_init_cons(void);
void imxuart_init_cons(void);
void omapuart_init_cons(void);
-void sxiuart_init_cons(void);
void pl011_init_cons(void);
struct armv7_platform *imx_platform_match(void);
@@ -102,7 +101,6 @@ platform_init_cons(void)
exuart_init_cons();
imxuart_init_cons();
omapuart_init_cons();
- sxiuart_init_cons();
pl011_init_cons();
}
diff --git a/sys/arch/armv7/conf/GENERIC b/sys/arch/armv7/conf/GENERIC
index c3f0311..5ddaea7 100644
--- a/sys/arch/armv7/conf/GENERIC
+++ b/sys/arch/armv7/conf/GENERIC
@@ -91,7 +91,7 @@ sxiccmu* at sunxi? # Clock Control Module/Unit
sxitimer* at sunxi?
sxidog* at sunxi? # watchdog timer
sxirtc* at sunxi? # Real Time Clock
-sxiuart* at fdt? # onboard UARTs
+#sxiuart* at fdt? # onboard UARTs
sxie* at fdt?
ahci* at sunxi? # AHCI/SATA (shim)
ehci* at sunxi? # EHCI (shim)
diff --git a/sys/arch/armv7/conf/RAMDISK b/sys/arch/armv7/conf/RAMDISK
index 4a3c53e..36fb0dc 100644
--- a/sys/arch/armv7/conf/RAMDISK
+++ b/sys/arch/armv7/conf/RAMDISK
@@ -90,7 +90,7 @@ sxiccmu* at sunxi? # Clock Control Module/Unit
sxitimer* at sunxi?
sxidog* at sunxi? # watchdog timer
sxirtc* at sunxi? # Real Time Clock
-sxiuart* at fdt? # onboard UARTs
+#sxiuart* at fdt? # onboard UARTs
sxie* at fdt?
ahci* at sunxi? # AHCI/SATA (shim)
ehci* at sunxi? # EHCI (shim)
diff --git a/sys/arch/armv7/omap/omap_com.c b/sys/arch/armv7/omap/omap_com.c
index 20a51b4..5aa82f7 100644
--- a/sys/arch/armv7/omap/omap_com.c
+++ b/sys/arch/armv7/omap/omap_com.c
@@ -76,14 +76,23 @@ omapuart_init_cons(void)
{
struct fdt_reg reg;
void *node;
+ int freq = 48000000;
- if ((node = fdt_find_cons("ti,omap3-uart")) == NULL)
- if ((node = fdt_find_cons("ti,omap4-uart")) == NULL)
+ if ((node = fdt_find_cons("ti,omap3-uart")) == NULL &&
+ (node = fdt_find_cons("ti,omap4-uart")) == NULL &&
+ (node = fdt_find_cons("snps,dw-apb-uart")) == NULL)
return;
if (fdt_get_reg(node, 0, ®))
return;
- comcnattach(&armv7_a4x_bs_tag, reg.addr, comcnspeed, 48000000,
+ if ((node = fdt_find_node("/")) != NULL &&
+ (fdt_is_compatible(node, "allwinner,sun4i-a10") ||
+ fdt_is_compatible(node, "allwinner,sun5i-a10s") ||
+ fdt_is_compatible(node, "allwinner,sun5i-r8") ||
+ fdt_is_compatible(node, "allwinner,sun7i-a20")))
+ freq = 24000000;
+
+ comcnattach(&armv7_a4x_bs_tag, reg.addr, comcnspeed, freq,
comcnmode);
comdefaultrate = comcnspeed;
}
@@ -94,7 +103,8 @@ omapuart_match(struct device *parent, void *match, void *aux)
struct fdt_attach_args *faa = aux;
return (OF_is_compatible(faa->fa_node, "ti,omap3-uart") ||
- OF_is_compatible(faa->fa_node, "ti,omap4-uart"));
+ OF_is_compatible(faa->fa_node, "ti,omap4-uart") ||
+ OF_is_compatible(faa->fa_node, "snps,dw-apb-uart"));
}
void
@@ -102,7 +112,7 @@ omapuart_attach(struct device *parent, struct device *self, void *aux)
{
struct com_softc *sc = (struct com_softc *)self;
struct fdt_attach_args *faa = aux;
- int irq;
+ int irq, node;
if (faa->fa_nreg != 1 || (faa->fa_nintr != 1 && faa->fa_nintr != 3))
return;
@@ -123,7 +133,21 @@ omapuart_attach(struct device *parent, struct device *self, void *aux)
return;
}
- sitara_cm_pinctrlbyname(faa->fa_node, "default");
+ if (OF_is_compatible(faa->fa_node, "ti,omap3-uart") ||
+ OF_is_compatible(faa->fa_node, "ti,omap4-uart"))
+ sitara_cm_pinctrlbyname(faa->fa_node, "default");
+
+ if (OF_is_compatible(faa->fa_node, "snps,dw-apb-uart")) {
+ sc->sc_hwflags |= COM_HW_IIR_BUSY;
+ sc->sc_uarttype = COM_UART_16550;
+ }
+
+ if ((node = OF_finddevice("/")) != 0 &&
+ (OF_is_compatible(node, "allwinner,sun4i-a10") ||
+ OF_is_compatible(node, "allwinner,sun5i-a10s") ||
+ OF_is_compatible(node, "allwinner,sun5i-r8") ||
+ OF_is_compatible(node, "allwinner,sun7i-a20")))
+ sc->sc_frequency = 24000000;
com_attach_subr(sc);
diff --git a/sys/dev/ic/com.c b/sys/dev/ic/com.c
index 000eea3..0bf7181 100644
--- a/sys/dev/ic/com.c
+++ b/sys/dev/ic/com.c
@@ -1219,12 +1219,30 @@ comintr(void *arg)
bus_space_tag_t iot = sc->sc_iot;
bus_space_handle_t ioh = sc->sc_ioh;
struct tty *tp;
- u_char lsr, data, msr, delta;
+ u_char iir, lsr, data, msr, delta;
+ int timeout;
+
+ iir = bus_space_read_1(iot, ioh, com_iir);
+
+ /* Handle ns16750-specific busy interrupt. */
+ if (ISSET(sc->sc_hwflags, COM_HW_IIR_BUSY) &&
+ (iir & IIR_BUSY) == IIR_BUSY) {
+ for (timeout = 10000;
+ (bus_space_read_1(iot, ioh, com_usr) & 0x1) != 0;
+ timeout--)
+ if (timeout <= 0) {
+ printf("%s: timeout while waiting for BUSY "
+ "interrupt acknowledge\n",
+ sc->sc_dev.dv_xname);
+ return (0);
+ }
+ iir = bus_space_read_1(iot, ioh, com_iir);
+ }
if (!sc->sc_tty)
return (0); /* Can't do squat. */
- if (ISSET(bus_space_read_1(iot, ioh, com_iir), IIR_NOPEND))
+ if (ISSET(iir, IIR_NOPEND))
return (0);
tp = sc->sc_tty;
diff --git a/sys/dev/ic/comreg.h b/sys/dev/ic/comreg.h
index 6084698..d2e52a0 100644
--- a/sys/dev/ic/comreg.h
+++ b/sys/dev/ic/comreg.h
@@ -82,6 +82,7 @@
#define IIR_MLSC 0x0 /* Modem status */
#define IIR_NOPEND 0x1 /* No pending interrupts */
#define IIR_FIFO_MASK 0xc0 /* set if FIFOs are enabled */
+#define IIR_BUSY 0x7 /* NS16750: Busy indicator */
/* fifo control register */
#define FIFO_ENABLE 0x01 /* Turn the FIFO on */
diff --git a/sys/dev/ic/comvar.h b/sys/dev/ic/comvar.h
index 893ffde..5f7e5fe 100644
--- a/sys/dev/ic/comvar.h
+++ b/sys/dev/ic/comvar.h
@@ -106,6 +106,7 @@ struct com_softc {
u_char sc_hwflags;
#define COM_HW_NOIEN 0x01
#define COM_HW_FIFO 0x02
+#define COM_HW_IIR_BUSY 0x04
#define COM_HW_SIR 0x20
#define COM_HW_CONSOLE 0x40
#define COM_HW_KGDB 0x80
@@ -117,7 +118,7 @@ struct com_softc {
#define COM_SW_PPS 0x10
#define COM_SW_DEAD 0x20
int sc_fifolen;
- u_char sc_msr, sc_mcr, sc_lcr, sc_ier;
+ u_char sc_msr, sc_mcr, sc_lcr, sc_ier, sc_iir;
u_char sc_dtr;
u_char sc_cua;
diff --git a/sys/dev/ic/ns16550reg.h b/sys/dev/ic/ns16550reg.h
index 5db1a27..d8eb8b3 100644
--- a/sys/dev/ic/ns16550reg.h
+++ b/sys/dev/ic/ns16550reg.h
@@ -50,3 +50,4 @@
#define com_lsr 5 /* line status register (R/W) */
#define com_msr 6 /* modem status register (R/W) */
#define com_scratch 7 /* scratch register (R/W) */
+#define com_usr 31 /* NS16750: status register (R) */