Index: sys/arch/arm/acpi/plcom_acpi.c =================================================================== RCS file: /cvsroot/src/sys/arch/arm/acpi/plcom_acpi.c,v retrieving revision 1.3 diff -p -u -r1.3 plcom_acpi.c --- sys/arch/arm/acpi/plcom_acpi.c 25 Apr 2020 21:34:26 -0000 1.3 +++ sys/arch/arm/acpi/plcom_acpi.c 19 Dec 2022 07:55:51 -0000 @@ -50,9 +50,17 @@ static void plcom_acpi_attach(device_t, CFATTACH_DECL_NEW(plcom_acpi, sizeof(struct plcom_softc), plcom_acpi_match, plcom_acpi_attach, NULL, NULL); -static const char * const compatible[] = { - "ARMH0011", - NULL +enum plcom_acpi_variant { + PLCOM_ACPI_GENERIC, + PLCOM_ACPI_PL011, + PLCOM_ACPI_BCM2837 +}; + +static const struct device_compatible_entry compat_data[] = { + { .compat = "BCM2837", .value = PLCOM_ACPI_BCM2837 }, + { .compat = "ARMH0011", .value = PLCOM_ACPI_PL011 }, + { .compat = "ARMHB000", .value = PLCOM_ACPI_GENERIC }, + DEVICE_COMPAT_EOL }; static int @@ -63,7 +71,7 @@ plcom_acpi_match(device_t parent, cfdata if (aa->aa_node->ad_type != ACPI_TYPE_DEVICE) return 0; - return acpi_match_hid(aa->aa_node->ad_devinfo, compatible); + return acpi_compatible_match(aa, compat_data); } static void @@ -98,9 +106,19 @@ plcom_acpi_attach(device_t parent, devic sc->sc_hwflags = 0; sc->sc_swflags = 0; - + sc->sc_fifolen = 0; sc->sc_pi.pi_type = PLCOM_TYPE_PL011; sc->sc_pi.pi_flags = PLC_FLAG_32BIT_ACCESS; + + switch (acpi_compatible_lookup(aa, compat_data)->value) { + case PLCOM_ACPI_BCM2837: + sc->sc_fifolen = 16; + break; + case PLCOM_ACPI_GENERIC: + sc->sc_pi.pi_type = PLCOM_TYPE_GENERIC_UART; + break; + } + sc->sc_pi.pi_iot = aa->aa_memt; sc->sc_pi.pi_iobase = mem->ar_base; if (bus_space_map(aa->aa_memt, mem->ar_base, mem->ar_length, 0, &sc->sc_pi.pi_ioh) != 0) { Index: sys/arch/arm/acpi/acpi_platform.c =================================================================== RCS file: /cvsroot/src/sys/arch/arm/acpi/acpi_platform.c,v retrieving revision 1.34 diff -p -u -r1.34 acpi_platform.c --- sys/arch/arm/acpi/acpi_platform.c 16 Nov 2022 11:54:26 -0000 1.34 +++ sys/arch/arm/acpi/acpi_platform.c 19 Dec 2022 07:55:51 -0000 @@ -188,7 +188,10 @@ acpi_platform_attach_uart(ACPI_TABLE_SPC case ACPI_DBG2_ARM_PL011: case ACPI_DBG2_ARM_SBSA_32BIT: case ACPI_DBG2_ARM_SBSA_GENERIC: - plcom_console.pi_type = PLCOM_TYPE_PL011; + if (spcr->InterfaceType == ACPI_DBG2_ARM_PL011) + plcom_console.pi_type = PLCOM_TYPE_PL011; + else + plcom_console.pi_type = PLCOM_TYPE_GENERIC_UART; plcom_console.pi_iot = &arm_generic_bs_tag; plcom_console.pi_iobase = le64toh(spcr->SerialPort.Address); plcom_console.pi_size = PL011COM_UART_SIZE; Index: sys/arch/arm/fdt/plcom_fdt.c =================================================================== RCS file: /cvsroot/src/sys/arch/arm/fdt/plcom_fdt.c,v retrieving revision 1.5 diff -p -u -r1.5 plcom_fdt.c --- sys/arch/arm/fdt/plcom_fdt.c 27 Jan 2021 03:10:19 -0000 1.5 +++ sys/arch/arm/fdt/plcom_fdt.c 19 Dec 2022 07:55:51 -0000 @@ -44,7 +44,8 @@ static int plcom_fdt_match(device_t, cfd static void plcom_fdt_attach(device_t, device_t, void *); static const struct device_compatible_entry compat_data[] = { - { .compat = "arm,pl011" }, + { .compat = "arm,pl011", .value = PLCOM_TYPE_PL011 }, + { .compat = "arm,sbsa-uart", .value = PLCOM_TYPE_GENERIC_UART }, DEVICE_COMPAT_EOL }; @@ -70,6 +71,8 @@ plcom_fdt_attach(device_t parent, device bus_addr_t addr; bus_size_t size; void *ih; + const u_int *data; + int len; if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) { aprint_error(": missing 'reg' property\n"); @@ -94,10 +97,13 @@ plcom_fdt_attach(device_t parent, device sc->sc_frequency = clk_get_rate(clk); } - sc->sc_hwflags = PLCOM_HW_TXFIFO_DISABLE; + sc->sc_hwflags = 0; sc->sc_swflags = 0; - sc->sc_pi.pi_type = PLCOM_TYPE_PL011; + if ((data = fdtbus_get_prop(phandle, "arm,primecell-periphid", &len)) != NULL) + sc->sc_pi.pi_periphid = be32toh(data[0]); + + sc->sc_pi.pi_type = of_compatible_lookup(faa->faa_phandle, compat_data)->value; sc->sc_pi.pi_flags = PLC_FLAG_32BIT_ACCESS; sc->sc_pi.pi_iot = faa->faa_bst; sc->sc_pi.pi_iobase = addr; Index: sys/arch/evbarm/dev/plcom.c =================================================================== RCS file: /cvsroot/src/sys/arch/evbarm/dev/plcom.c,v retrieving revision 1.66 diff -p -u -r1.66 plcom.c --- sys/arch/evbarm/dev/plcom.c 26 Oct 2022 23:38:07 -0000 1.66 +++ sys/arch/evbarm/dev/plcom.c 19 Dec 2022 07:55:51 -0000 @@ -149,7 +149,7 @@ void plcom_config (struct plcom_softc *) void plcom_shutdown (struct plcom_softc *); int pl010comspeed (long, long); int pl011comspeed (long, long); -static u_char cflag2lcr (tcflag_t); +static uint32_t cflag2lcr (tcflag_t); int plcomparam (struct tty *, struct termios *); void plcomstart (struct tty *); int plcomhwiflow (struct tty *, int); @@ -267,7 +267,17 @@ pread1(struct plcom_instance *pi, bus_si return bus_space_read_4(pi->pi_iot, pi->pi_ioh, reg & -4) >> (8 * (reg & 3)); } -int nhcr; + +static uint16_t +pread2(struct plcom_instance *pi, bus_size_t reg) +{ + if (!ISSET(pi->pi_flags, PLC_FLAG_32BIT_ACCESS)) + return bus_space_read_2(pi->pi_iot, pi->pi_ioh, reg); + + return bus_space_read_4(pi->pi_iot, pi->pi_ioh, reg & -4) >> + (8 * (reg & 3)); +} + static void pwrite1(struct plcom_instance *pi, bus_size_t o, uint8_t val) { @@ -283,6 +293,20 @@ pwrite1(struct plcom_instance *pi, bus_s } static void +pwrite2(struct plcom_instance *pi, bus_size_t o, uint16_t val) +{ + if (!ISSET(pi->pi_flags, PLC_FLAG_32BIT_ACCESS)) { + bus_space_write_2(pi->pi_iot, pi->pi_ioh, o, val); + } else { + const size_t shift = 8 * (o & 3); + o &= -4; + uint32_t tmp = bus_space_read_4(pi->pi_iot, pi->pi_ioh, o); + tmp = (val << shift) | (tmp & ~(0xffff << shift)); + bus_space_write_4(pi->pi_iot, pi->pi_ioh, o, tmp); + } +} + +static void pwritem1(struct plcom_instance *pi, bus_size_t o, const uint8_t *datap, bus_size_t count) { @@ -297,11 +321,13 @@ pwritem1(struct plcom_instance *pi, bus_ } #define PREAD1(pi, reg) pread1(pi, reg) +#define PREAD2(pi, reg) pread2(pi, reg) #define PREAD4(pi, reg) \ bus_space_read_4((pi)->pi_iot, (pi)->pi_ioh, (reg)) #define PWRITE1(pi, reg, val) pwrite1(pi, reg, val) #define PWRITEM1(pi, reg, d, c) pwritem1(pi, reg, d, c) +#define PWRITE2(pi, reg, val) pwrite2(pi, reg, val) #define PWRITE4(pi, reg, val) \ bus_space_write_4((pi)->pi_iot, (pi)->pi_ioh, (reg), (val)) @@ -381,14 +407,14 @@ plcomprobe1(bus_space_tag_t iot, bus_spa /* Disable the UART. */ bus_space_write_1(iot, ioh, plcom_cr, 0); /* Make sure the FIFO is off. */ - bus_space_write_1(iot, ioh, plcom_lcr, PL01X_LCR_8BITS); + bus_space_write_4(iot, ioh, plcom_lcr, PL01X_LCR_8BITS); /* Disable interrupts. */ bus_space_write_1(iot, ioh, plcom_iir, 0); /* Make sure we swallow anything in the receiving register. */ data = bus_space_read_1(iot, ioh, plcom_dr); - if (bus_space_read_1(iot, ioh, plcom_lcr) != PL01X_LCR_8BITS) + if (bus_space_read_4(iot, ioh, plcom_lcr) != PL01X_LCR_8BITS) return 0; data = bus_space_read_1(iot, ioh, plcom_fr) & (PL01X_FR_RXFF | PL01X_FR_RXFE); @@ -424,10 +450,11 @@ plcom_enable_debugport(struct plcom_soft } break; case PLCOM_TYPE_PL011: + case PLCOM_TYPE_GENERIC_UART: sc->sc_imsc = PL011_INT_RX | PL011_INT_RT; SET(sc->sc_cr, PL011_CR_RXE | PL011_CR_TXE); SET(sc->sc_cr, PL011_MCR(sc->sc_mcr)); - PWRITE4(pi, PL011COM_CR, sc->sc_cr); + PWRITE2(pi, PL011COM_CR, sc->sc_cr); PWRITE4(pi, PL011COM_IMSC, sc->sc_imsc); break; } @@ -446,6 +473,7 @@ plcom_attach_subr(struct plcom_softc *sc switch (pi->pi_type) { case PLCOM_TYPE_PL010: case PLCOM_TYPE_PL011: + case PLCOM_TYPE_GENERIC_UART: break; default: aprint_error_dev(sc->sc_dev, @@ -470,8 +498,24 @@ plcom_attach_subr(struct plcom_softc *sc * hang when trying to print. */ sc->sc_cr = PL01X_CR_UARTEN; - if (pi->pi_type == PLCOM_TYPE_PL011) + switch (pi->pi_type) { + case PLCOM_TYPE_PL011: + case PLCOM_TYPE_GENERIC_UART: SET(sc->sc_cr, PL011_CR_RXE | PL011_CR_TXE); + break; + } + } + + switch (pi->pi_type) { + case PLCOM_TYPE_PL011: + if (pi->pi_periphid == 0) { + pi->pi_periphid = PREAD1(pi, PL011COM_PID0) << 0 + | PREAD1(pi, PL011COM_PID1) << 8 + | PREAD1(pi, PL011COM_PID2) << 16 + | PREAD1(pi, PL011COM_PID3) << 24; + } + aprint_debug_dev(sc->sc_dev, "PID %08x\n", pi->pi_periphid); + break; } switch (pi->pi_type) { @@ -480,7 +524,8 @@ plcom_attach_subr(struct plcom_softc *sc break; case PLCOM_TYPE_PL011: - PWRITE4(pi, PL011COM_CR, sc->sc_cr); + case PLCOM_TYPE_GENERIC_UART: + PWRITE2(pi, PL011COM_CR, sc->sc_cr); PWRITE4(pi, PL011COM_IMSC, sc->sc_imsc); break; } @@ -496,18 +541,36 @@ plcom_attach_subr(struct plcom_softc *sc break; case PLCOM_TYPE_PL011: /* Some revisions have a 32 byte TX FIFO */ - sc->sc_fifolen = 16; + switch (pi->pi_periphid & (PL011_DESIGNER_MASK | PL011_HWREV_MASK)) { + case PL011_DESIGNER_ARM | __SHIFTIN(0, PL011_HWREV_MASK): + case PL011_DESIGNER_ARM | __SHIFTIN(1, PL011_HWREV_MASK): + case PL011_DESIGNER_ARM | __SHIFTIN(2, PL011_HWREV_MASK): + sc->sc_fifolen = 16; + break; + default: + sc->sc_fifolen = 32; + break; + } + break; + case PLCOM_TYPE_GENERIC_UART: + /* At least 32 byte TX FIFO */ + sc->sc_fifolen = 32; break; } } + /* Safe amount of bytes to fill when TX FIFO signals empty */ + sc->sc_burstlen = 1; + if (ISSET(sc->sc_hwflags, PLCOM_HW_TXFIFO_DISABLE)) { sc->sc_fifolen = 1; aprint_normal_dev(sc->sc_dev, "txfifo disabled\n"); } - if (sc->sc_fifolen > 1) + if (sc->sc_fifolen > 1) { SET(sc->sc_hwflags, PLCOM_HW_FIFO); + aprint_normal_dev(sc->sc_dev, "txfifo %u bytes\n", sc->sc_fifolen); + } tp = tty_alloc(); tp->t_oproc = plcomstart; @@ -582,7 +645,8 @@ plcom_config(struct plcom_softc *sc) break; case PLCOM_TYPE_PL011: - PWRITE4(pi, PL011COM_CR, sc->sc_cr); + case PLCOM_TYPE_GENERIC_UART: + PWRITE2(pi, PL011COM_CR, sc->sc_cr); PWRITE4(pi, PL011COM_IMSC, sc->sc_imsc); break; } @@ -704,6 +768,7 @@ plcom_shutdown(struct plcom_softc *sc) SET(sc->sc_cr, PL010_CR_RIE | PL010_CR_RTIE); break; case PLCOM_TYPE_PL011: + case PLCOM_TYPE_GENERIC_UART: SET(sc->sc_cr, PL011_CR_RXE); SET(sc->sc_imsc, PL011_INT_RT | PL011_INT_RX); break; @@ -715,9 +780,10 @@ plcom_shutdown(struct plcom_softc *sc) PWRITE1(pi, PL010COM_CR, sc->sc_cr); break; case PLCOM_TYPE_PL011: + case PLCOM_TYPE_GENERIC_UART: SET(sc->sc_cr, PL011_CR_RXE | PL011_CR_TXE); SET(sc->sc_imsc, PL011_INT_RT | PL011_INT_RX); - PWRITE4(pi, PL011COM_CR, sc->sc_cr); + PWRITE2(pi, PL011COM_CR, sc->sc_cr); PWRITE4(pi, PL011COM_IMSC, sc->sc_imsc); break; } @@ -815,6 +881,7 @@ plcomopen(dev_t dev, int flag, int mode, sc->sc_msr = PREAD1(pi, PL01XCOM_FR); break; case PLCOM_TYPE_PL011: + case PLCOM_TYPE_GENERIC_UART: SET(sc->sc_cr, PL011_CR_RXE | PL011_CR_TXE); SET(sc->sc_imsc, PL011_INT_RT | PL011_INT_RX | PL011_INT_MSMASK); @@ -1297,10 +1364,10 @@ plcom_to_tiocm(struct plcom_softc *sc) return ttybits; } -static u_char +static uint32_t cflag2lcr(tcflag_t cflag) { - u_char lcr = 0; + uint32_t lcr = 0; switch (ISSET(cflag, CSIZE)) { case CS5: @@ -1333,8 +1400,8 @@ plcomparam(struct tty *tp, struct termio struct plcom_softc *sc = device_lookup_private(&plcom_cd, PLCOMUNIT(tp->t_dev)); struct plcom_instance *pi = &sc->sc_pi; - int ospeed = -1; - u_char lcr; + int ospeed = -1, lvl; + uint32_t lcr; if (PLCOM_ISALIVE(sc) == 0) return EIO; @@ -1344,6 +1411,7 @@ plcomparam(struct tty *tp, struct termio ospeed = pl010comspeed(t->c_ospeed, sc->sc_frequency); break; case PLCOM_TYPE_PL011: + case PLCOM_TYPE_GENERIC_UART: ospeed = pl011comspeed(t->c_ospeed, sc->sc_frequency); break; } @@ -1387,9 +1455,26 @@ plcomparam(struct tty *tp, struct termio else sc->sc_fifo = 0; - if (sc->sc_fifo) + if (sc->sc_fifo) { SET(sc->sc_lcr, PL01X_LCR_FEN); + switch (pi->pi_type) { + case PLCOM_TYPE_PL010: + sc->sc_ifls = 0; + break; + case PLCOM_TYPE_PL011: + case PLCOM_TYPE_GENERIC_UART: + lvl = PL011_IFLS_3QUARTERS; + sc->sc_ifls = PL011_IFLS_RXIFLS(lvl); + + lvl = PL011_IFLS_1QUARTER; + sc->sc_ifls |= PL011_IFLS_TXIFLS(lvl); + sc->sc_burstlen = uimin(sc->sc_fifolen * 3 / 4, 1); + break; + } + } else + sc->sc_ifls = 0; + /* * If we're not in a mode that assumes a connection is present, then * ignore carrier changes. @@ -1404,8 +1489,19 @@ plcomparam(struct tty *tp, struct termio */ if (ISSET(t->c_cflag, CRTSCTS)) { sc->sc_mcr_dtr = PL01X_MCR_DTR; - sc->sc_mcr_rts = PL01X_MCR_RTS; - sc->sc_msr_cts = PL01X_MSR_CTS; + + switch (pi->pi_type) { + case PLCOM_TYPE_PL010: + sc->sc_mcr_rts = PL01X_MCR_RTS; + sc->sc_msr_cts = PL01X_MSR_CTS; + break; + case PLCOM_TYPE_PL011: + case PLCOM_TYPE_GENERIC_UART: + sc->sc_mcr_rts = 0; + sc->sc_msr_cts = 0; + SET(sc->sc_cr, PL011_CR_CTSEN | PL011_CR_RTSEN); + break; + } } else if (ISSET(t->c_cflag, MDMBUF)) { /* * For DTR/DCD flow control, make sure we don't toggle DTR for @@ -1414,6 +1510,12 @@ plcomparam(struct tty *tp, struct termio sc->sc_mcr_dtr = 0; sc->sc_mcr_rts = PL01X_MCR_DTR; sc->sc_msr_cts = PL01X_MSR_DCD; + + switch (pi->pi_type) { + case PLCOM_TYPE_PL011: + CLR(sc->sc_cr, PL011_CR_CTSEN | PL011_CR_RTSEN); + break; + } } else { /* * If no flow control, then always set RTS. This will make @@ -1427,6 +1529,12 @@ plcomparam(struct tty *tp, struct termio SET(sc->sc_mcr, PL01X_MCR_RTS); else CLR(sc->sc_mcr, PL01X_MCR_RTS); + switch (pi->pi_type) { + case PLCOM_TYPE_PL011: + case PLCOM_TYPE_GENERIC_UART: + CLR(sc->sc_cr, PL011_CR_CTSEN | PL011_CR_RTSEN); + break; + } } sc->sc_msr_mask = sc->sc_msr_cts | sc->sc_msr_dcd; @@ -1443,6 +1551,7 @@ plcomparam(struct tty *tp, struct termio sc->sc_rateh = (ospeed >> 8) & 0xff; break; case PLCOM_TYPE_PL011: + case PLCOM_TYPE_GENERIC_UART: sc->sc_ratel = ospeed & ((1 << 6) - 1); sc->sc_rateh = ospeed >> 6; break; @@ -1536,6 +1645,7 @@ void plcom_loadchannelregs(struct plcom_softc *sc) { struct plcom_instance *pi = &sc->sc_pi; + uint16_t ifls; /* XXXXX necessary? */ plcom_iflush(sc); @@ -1559,16 +1669,23 @@ plcom_loadchannelregs(struct plcom_softc break; case PLCOM_TYPE_PL011: - PWRITE4(pi, PL011COM_CR, 0); + case PLCOM_TYPE_GENERIC_UART: + PWRITE2(pi, PL011COM_CR, 0); if (sc->sc_frequency != 0) { PWRITE1(pi, PL011COM_FBRD, sc->sc_ratel); PWRITE4(pi, PL011COM_IBRD, sc->sc_rateh); } + + /* Bits 6..15 are reserved, don't modify, read as zero */ + ifls = PREAD2(pi, PL011COM_IFLS) & ~PL011_IFLS_MASK; + ifls |= sc->sc_ifls & PL011_IFLS_MASK; + PWRITE2(pi, PL011COM_IFLS, ifls); + PWRITE1(pi, PL011COM_LCRH, sc->sc_lcr); sc->sc_mcr_active = sc->sc_mcr; CLR(sc->sc_cr, PL011_MCR(PL01X_MCR_RTS | PL01X_MCR_DTR)); SET(sc->sc_cr, PL011_MCR(sc->sc_mcr_active)); - PWRITE4(pi, PL011COM_CR, sc->sc_cr); + PWRITE2(pi, PL011COM_CR, sc->sc_cr); break; } } @@ -1633,9 +1750,10 @@ plcom_hwiflow(struct plcom_softc *sc) device_unit(sc->sc_dev), sc->sc_mcr_active); break; case PLCOM_TYPE_PL011: + case PLCOM_TYPE_GENERIC_UART: CLR(sc->sc_cr, PL011_MCR(PL01X_MCR_RTS | PL01X_MCR_DTR)); SET(sc->sc_cr, PL011_MCR(sc->sc_mcr_active)); - PWRITE4(pi, PL011COM_CR, sc->sc_cr); + PWRITE2(pi, PL011COM_CR, sc->sc_cr); break; } } @@ -1687,6 +1805,7 @@ plcomstart(struct tty *tp) } break; case PLCOM_TYPE_PL011: + case PLCOM_TYPE_GENERIC_UART: if (!ISSET(sc->sc_imsc, PL011_INT_TX)) { SET(sc->sc_imsc, PL011_INT_TX); PWRITE4(pi, PL011COM_IMSC, sc->sc_imsc); @@ -1699,8 +1818,8 @@ plcomstart(struct tty *tp) int n; n = sc->sc_tbc; - if (n > sc->sc_fifolen) - n = sc->sc_fifolen; + if (n > sc->sc_burstlen) + n = sc->sc_burstlen; PWRITEM1(pi, PL01XCOM_DR, sc->sc_tba, n); sc->sc_tbc -= n; sc->sc_tba += n; @@ -1820,7 +1939,6 @@ plcom_rxsoft(struct plcom_softc *sc, str get = sc->sc_rbuf; cc--; } - if (cc != scc) { sc->sc_rbget = get; mutex_spin_enter(&sc->sc_lock); @@ -1837,6 +1955,7 @@ plcom_rxsoft(struct plcom_softc *sc, str PWRITE1(pi, PL010COM_CR, sc->sc_cr); break; case PLCOM_TYPE_PL011: + case PLCOM_TYPE_GENERIC_UART: SET(sc->sc_imsc, PL011_INT_RX | PL011_INT_RT); PWRITE4(pi, PL011COM_IMSC, sc->sc_imsc); @@ -1937,6 +2056,7 @@ plcom_intstatus(struct plcom_instance *p ret = ISSET(stat, PL010_IIR_IMASK); break; case PLCOM_TYPE_PL011: + case PLCOM_TYPE_GENERIC_UART: stat = PREAD4(pi, PL011COM_MIS); ret = ISSET(stat, PL011_INT_ALLMASK); break; @@ -1989,6 +2109,7 @@ plcomintr(void *arg) /* Clear any error status. */ if (ISSET(rsr, PL01X_RSR_ERROR)) PWRITE1(pi, PL01XCOM_ECR, 0); + if (ISSET(rsr, PL01X_RSR_BE)) { cn_trapped = 0; cn_check_magic(sc->sc_tty->t_dev, @@ -2060,6 +2181,7 @@ plcomintr(void *arg) PWRITE1(pi, PL010COM_CR, sc->sc_cr); break; case PLCOM_TYPE_PL011: + case PLCOM_TYPE_GENERIC_UART: CLR(sc->sc_imsc, PL011_INT_RT | PL011_INT_RX); PWRITE4(pi, PL011COM_IMSC, sc->sc_imsc); @@ -2078,11 +2200,12 @@ plcomintr(void *arg) } break; case PLCOM_TYPE_PL011: + case PLCOM_TYPE_GENERIC_UART: rxintr = ISSET(istatus, PL011_INT_RX); if (rxintr) { - PWRITE4(pi, PL011COM_CR, 0); + PWRITE2(pi, PL011COM_CR, 0); delay(10); - PWRITE4(pi, PL011COM_CR, sc->sc_cr); + PWRITE2(pi, PL011COM_CR, sc->sc_cr); continue; } break; @@ -2094,6 +2217,7 @@ plcomintr(void *arg) msr = PREAD1(pi, PL01XCOM_FR); break; case PLCOM_TYPE_PL011: + case PLCOM_TYPE_GENERIC_UART: msr = PREAD4(pi, PL01XCOM_FR); break; } @@ -2109,6 +2233,7 @@ plcomintr(void *arg) } break; case PLCOM_TYPE_PL011: + case PLCOM_TYPE_GENERIC_UART: msintr = ISSET(istatus, PL011_INT_MSMASK); if (msintr) { PWRITE4(pi, PL011COM_ICR, PL011_INT_MSMASK); @@ -2218,8 +2343,8 @@ plcomintr(void *arg) int n; n = sc->sc_tbc; - if (n > sc->sc_fifolen) - n = sc->sc_fifolen; + if (n > sc->sc_burstlen) + n = sc->sc_burstlen; PWRITEM1(pi, PL01XCOM_DR, sc->sc_tba, n); sc->sc_tbc -= n; sc->sc_tba += n; @@ -2237,6 +2362,7 @@ plcomintr(void *arg) } break; case PLCOM_TYPE_PL011: + case PLCOM_TYPE_GENERIC_UART: if (ISSET(sc->sc_imsc, PL011_INT_TX)) { CLR(sc->sc_imsc, PL011_INT_TX); PWRITE4(pi, PL011COM_IMSC, @@ -2256,7 +2382,8 @@ plcomintr(void *arg) mutex_spin_exit(&sc->sc_lock); /* Wake up the poller. */ - softint_schedule(sc->sc_si); + if ((sc->sc_rx_ready | sc->sc_st_check | sc->sc_tx_done) != 0) + softint_schedule(sc->sc_si); #ifdef RND_COM rnd_add_uint32(&sc->rnd_source, istatus | rsr); @@ -2347,7 +2474,7 @@ plcom_common_putc(dev_t dev, struct plco int plcominit(struct plcom_instance *pi, int rate, int frequency, tcflag_t cflag) { - u_char lcr; + uint32_t lcr; switch (pi->pi_type) { case PLCOM_TYPE_PL010: @@ -2355,6 +2482,7 @@ plcominit(struct plcom_instance *pi, int pi->pi_size = PL010COM_UART_SIZE; break; case PLCOM_TYPE_PL011: + case PLCOM_TYPE_GENERIC_UART: if (pi->pi_size == 0) pi->pi_size = PL011COM_UART_SIZE; break; @@ -2369,7 +2497,7 @@ plcominit(struct plcom_instance *pi, int lcr = cflag2lcr(cflag) | PL01X_LCR_FEN; switch (pi->pi_type) { case PLCOM_TYPE_PL010: - PWRITE1(pi, PL010COM_CR, 0); + PWRITE4(pi, PL010COM_CR, 0); if (rate && frequency) { rate = pl010comspeed(rate, frequency); @@ -2380,7 +2508,8 @@ plcominit(struct plcom_instance *pi, int PWRITE1(pi, PL010COM_CR, PL01X_CR_UARTEN); break; case PLCOM_TYPE_PL011: - PWRITE4(pi, PL011COM_CR, 0); + case PLCOM_TYPE_GENERIC_UART: + PWRITE2(pi, PL011COM_CR, 0); if (rate && frequency) { rate = pl011comspeed(rate, frequency); @@ -2388,7 +2517,7 @@ plcominit(struct plcom_instance *pi, int PWRITE4(pi, PL011COM_IBRD, rate >> 6); } PWRITE1(pi, PL011COM_LCRH, lcr); - PWRITE4(pi, PL011COM_CR, + PWRITE2(pi, PL011COM_CR, PL01X_CR_UARTEN | PL011_CR_RXE | PL011_CR_TXE); break; } @@ -2478,7 +2607,8 @@ plcomcnhalt(dev_t dev) PWRITE1(pi, PL010COM_CR, PL01X_CR_UARTEN); break; case PLCOM_TYPE_PL011: - PWRITE4(pi, PL011COM_CR, + case PLCOM_TYPE_GENERIC_UART: + PWRITE2(pi, PL011COM_CR, PL01X_CR_UARTEN | PL011_CR_RXE | PL011_CR_TXE); PWRITE4(pi, PL011COM_IMSC, 0); break; Index: sys/arch/evbarm/dev/plcomreg.h =================================================================== RCS file: /cvsroot/src/sys/arch/evbarm/dev/plcomreg.h,v retrieving revision 1.6 diff -p -u -r1.6 plcomreg.h --- sys/arch/evbarm/dev/plcomreg.h 27 Dec 2019 08:22:50 -0000 1.6 +++ sys/arch/evbarm/dev/plcomreg.h 19 Dec 2022 07:55:51 -0000 @@ -107,6 +107,7 @@ #define PL011_MSR_RI PL011_FR_RI /* ifls */ +#define PL011_IFLS_MASK 0x001f #define PL011_IFLS_1EIGHTH 0 #define PL011_IFLS_1QUARTER 1 #define PL011_IFLS_1HALF 2 @@ -133,6 +134,10 @@ #define PL011_INT_ALLMASK \ (PL011_INT_RT | PL011_INT_TX | PL011_INT_RX | PL011_INT_MSMASK) +/* PL011 HW revision bits in PID (0..3 combined little endian) */ +#define PL011_HWREV_MASK 0x00f00000 +#define PL011_DESIGNER_MASK 0x000ff000 +#define PL011_DESIGNER_ARM 0x00041000 /* DMA control registers */ #define PL011_DMA_ONERR 0x4 @@ -161,6 +166,10 @@ #define PL011COM_MIS 0x40 /* Masked interrupt status register */ #define PL011COM_ICR 0x44 /* Interrupt clear register register */ #define PL011COM_DMACR 0x48 /* DMA control register register */ +#define PL011COM_PID0 0xfe0 /* Peripheral ID register 0 */ +#define PL011COM_PID1 0xfe4 /* Peripheral ID register 1 */ +#define PL011COM_PID2 0xfe8 /* Peripheral ID register 2 */ +#define PL011COM_PID3 0xfec /* Peripheral ID register 3 */ #define PL010COM_UART_SIZE 0x100 #define PL011COM_UART_SIZE 0x1000 Index: sys/arch/evbarm/dev/plcomvar.h =================================================================== RCS file: /cvsroot/src/sys/arch/evbarm/dev/plcomvar.h,v retrieving revision 1.18 diff -p -u -r1.18 plcomvar.h --- sys/arch/evbarm/dev/plcomvar.h 17 Oct 2021 22:34:17 -0000 1.18 +++ sys/arch/evbarm/dev/plcomvar.h 19 Dec 2022 07:55:51 -0000 @@ -70,10 +70,12 @@ struct plcom_instance { u_int pi_type; #define PLCOM_TYPE_PL010 0 #define PLCOM_TYPE_PL011 1 +#define PLCOM_TYPE_GENERIC_UART 2 /* SBSA generic uart */ uint32_t pi_flags; /* flags for this PLCOM */ #define PLC_FLAG_USE_DMA 0x0001 #define PLC_FLAG_32BIT_ACCESS 0x0002 + uint32_t pi_periphid; void *pi_cookie; @@ -103,6 +105,7 @@ struct plcom_softc { int sc_hwflags, sc_swflags; u_int sc_fifolen; + u_int sc_burstlen; struct timeval sc_hup_pending; @@ -131,9 +134,10 @@ struct plcom_softc { sc_rx_ready; volatile u_char sc_heldchange; - volatile u_int sc_cr, sc_ratel, sc_rateh, sc_imsc; - volatile u_int sc_msr, sc_msr_delta, sc_msr_mask; - volatile u_char sc_mcr, sc_mcr_active, sc_lcr; + volatile uint32_t sc_cr, sc_ratel, sc_rateh, sc_imsc; + volatile uint32_t sc_msr, sc_msr_delta, sc_msr_mask; + volatile uint32_t sc_lcr, sc_ifls; + volatile u_char sc_mcr, sc_mcr_active; u_char sc_mcr_dtr, sc_mcr_rts, sc_msr_cts, sc_msr_dcd; u_int sc_fifo;