Hi! ARMADAXP user and all,
I think that the support for com_16750 into which I was merged with ARMADAXP is not related to 16750. This is extended function included in ARMADAXP, and 16750 does not include such a function. I looked at the data sheet of TL16C750 and SC16C750. The data sheet of ARMADAXP don't describe compatible with 16750. I moved these ARMADAXP extended function to com_mv.c. My OpenBlocksAX3 works fine. Moreover, I added 64Byte FIFO support for TL16C750. However, since I did not own this device, I was not able to check and confirm. I am going to commit attaching patch at next weekend. The 16950 support before written by me further also plan to commit. http://mail-index.netbsd.org/current-users/2010/03/01/msg012772.html Thanks, -- kiyohara
Index: ic/com.c =================================================================== RCS file: /cvsroot/src/sys/dev/ic/com.c,v retrieving revision 1.312 diff -u -r1.312 com.c --- ic/com.c 27 Jul 2013 06:54:35 -0000 1.312 +++ ic/com.c 24 Aug 2013 05:39:38 -0000 @@ -246,17 +246,7 @@ #define COM_REG_16550 { \ com_data, com_data, com_dlbl, com_dlbh, com_ier, com_iir, com_fifo, \ com_efr, com_lcr, com_mcr, com_lsr, com_msr } -/* 16750-specific register set, additional UART status register */ -#define COM_REG_16750 { \ - com_data, com_data, com_dlbl, com_dlbh, com_ier, com_iir, com_fifo, \ - com_efr, com_lcr, com_mcr, com_lsr, com_msr, 0, 0, 0, 0, 0, 0, 0, 0, \ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, com_usr } - -#ifdef COM_16750 -const bus_size_t com_std_map[32] = COM_REG_16750; -#else const bus_size_t com_std_map[16] = COM_REG_16550; -#endif /* COM_16750 */ #endif /* COM_REGMAP */ #define COMUNIT_MASK 0x7ffff @@ -416,10 +404,7 @@ (u_long)comcons_info.regs.cr_iobase); } -#ifdef COM_16750 - /* Use in comintr(). */ sc->sc_lcr = cflag2lcr(comcons_info.cflag); -#endif /* Make sure the console is always "hardwired". */ delay(10000); /* wait for output to finish */ @@ -1479,19 +1498,19 @@ aprint_error_dev(sc->sc_dev, "com_iflush timeout %02x\n", reg); #endif -#ifdef COM_16750 - uint8_t fifo; - /* - * Reset all Rx/Tx FIFO, preserve current FIFO length. - * This should prevent triggering busy interrupt while - * manipulating divisors. - */ - fifo = CSR_READ_1(regsp, COM_REG_FIFO) & (FIFO_TRIGGER_1 | - FIFO_TRIGGER_4 | FIFO_TRIGGER_8 | FIFO_TRIGGER_14); - CSR_WRITE_1(regsp, COM_REG_FIFO, fifo | FIFO_ENABLE | FIFO_RCV_RST | - FIFO_XMT_RST); - delay(100); -#endif + if (sc->sc_type == COM_TYPE_ARMADAXP) { + uint8_t fifo; + /* + * Reset all Rx/Tx FIFO, preserve current FIFO length. + * This should prevent triggering busy interrupt while + * manipulating divisors. + */ + fifo = CSR_READ_1(regsp, COM_REG_FIFO) & (FIFO_TRIGGER_1 | + FIFO_TRIGGER_4 | FIFO_TRIGGER_8 | FIFO_TRIGGER_14); + CSR_WRITE_1(regsp, COM_REG_FIFO, + fifo | FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST); + delay(100); + } } void Index: ic/comreg.h =================================================================== RCS file: /cvsroot/src/sys/dev/ic/comreg.h,v retrieving revision 1.18 diff -u -r1.18 comreg.h --- ic/comreg.h 20 Apr 2013 11:52:41 -0000 1.18 +++ ic/comreg.h 24 Aug 2013 05:39:38 -0000 @@ -56,15 +56,15 @@ /* interrupt identification register */ #define IIR_IMASK 0xf #define IIR_RXTOUT 0xc +/* ARMADAXP's ns16550 ports have extra value in this register */ +#define IIR_BUSY 0x7 /* Busy indicator */ #define IIR_RLS 0x6 /* Line status change */ #define IIR_RXRDY 0x4 /* Receiver ready */ #define IIR_TXRDY 0x2 /* Transmitter ready */ #define IIR_MLSC 0x0 /* Modem status */ #define IIR_NOPEND 0x1 /* No pending interrupts */ +#define IIR_64B_FIFO 0x20 /* 64byte FIFO Enabled (16750) */ #define IIR_FIFO_MASK 0xc0 /* set if FIFOs are enabled */ -#ifdef COM_16750 -#define IIR_BUSY 0x7 /* Busy indicator */ -#endif /* fifo control register */ #define FIFO_ENABLE 0x01 /* Turn the FIFO on */ @@ -72,6 +72,7 @@ #define FIFO_XMT_RST 0x04 /* Reset TX FIFO */ #define FIFO_DMA_MODE 0x08 #define FIFO_TRIGGER_1 0x00 /* Trigger RXRDY intr on 1 character */ +#define FIFO_64B_ENABLE 0x20 /* 64byte FIFO Enable (16750) */ #define FIFO_TRIGGER_4 0x40 /* ibid 4 */ #define FIFO_TRIGGER_8 0x80 /* ibid 8 */ #define FIFO_TRIGGER_14 0xc0 /* ibid 14 */ Index: ic/comvar.h =================================================================== RCS file: /cvsroot/src/sys/dev/ic/comvar.h,v retrieving revision 1.75 diff -u -r1.75 comvar.h --- ic/comvar.h 17 Jul 2013 19:51:56 -0000 1.75 +++ ic/comvar.h 24 Aug 2013 05:39:38 -0000 @@ -91,27 +91,16 @@ #define COM_REG_MCR 9 #define COM_REG_LSR 10 #define COM_REG_MSR 11 -#ifdef COM_16750 -#define COM_REG_USR 31 -#endif struct com_regs { bus_space_tag_t cr_iot; bus_space_handle_t cr_ioh; bus_addr_t cr_iobase; bus_size_t cr_nports; -#ifdef COM_16750 - bus_size_t cr_map[32]; -#else bus_size_t cr_map[16]; -#endif }; -#ifdef COM_16750 -extern const bus_size_t com_std_map[32]; -#else extern const bus_size_t com_std_map[16]; -#endif #define COM_INIT_REGS(regs, tag, hdl, addr) \ do { \ @@ -138,9 +127,6 @@ #define COM_REG_TCR com_msr #define COM_REG_TLR com_scratch #define COM_REG_MDR1 8 -#ifdef COM_16750 -#define COM_REG_USR com_usr -#endif struct com_regs { bus_space_tag_t cr_iot; @@ -233,6 +219,7 @@ #define COM_TYPE_AU1x00 3 /* AMD/Alchemy Au1x000 proc. built-in */ #define COM_TYPE_OMAP 4 /* TI OMAP processor built-in */ #define COM_TYPE_16550_NOERS 5 /* like a 16550, no ERS */ +#define COM_TYPE_ARMADAXP 6 /* Marvell ARMADA XP proc. built-in */ /* power management hooks */ int (*enable)(struct com_softc *); Index: ic/ns16550reg.h =================================================================== RCS file: /cvsroot/src/sys/dev/ic/ns16550reg.h,v retrieving revision 1.8 diff -u -r1.8 ns16550reg.h --- ic/ns16550reg.h 20 Apr 2013 11:52:41 -0000 1.8 +++ ic/ns16550reg.h 24 Aug 2013 05:39:40 -0000 @@ -47,11 +47,3 @@ #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) */ - -/* - * Additional register present in NS16750 - */ -#ifdef COM_16750 -#define com_usr 31 /* status register (R) */ -#endif - Index: marvell/com_mv.c =================================================================== RCS file: /cvsroot/src/sys/dev/marvell/com_mv.c,v retrieving revision 1.5 diff -u -r1.5 com_mv.c --- marvell/com_mv.c 28 Jan 2011 16:12:22 -0000 1.5 +++ marvell/com_mv.c 24 Aug 2013 05:39:41 -0000 @@ -34,6 +34,7 @@ #include <sys/bus.h> #include <sys/device.h> #include <sys/errno.h> +#include <sys/mutex.h> #include <sys/termios.h> #include <dev/marvell/gtvar.h> @@ -44,34 +45,56 @@ #include <prop/proplib.h> -#define MVUART_SIZE 0x20 +#define MVUART_SIZE 0x80 + +#define MVUART_REG_USR 0x7c /* XXXX: What is this??? */ static int mvuart_match(device_t, struct cfdata *, void *); static void mvuart_attach(device_t, device_t, void *); +static int mvuart_intr(void *); + CFATTACH_DECL_NEW(mvuart_gt, sizeof(struct com_softc), mvuart_match, mvuart_attach, NULL, NULL); CFATTACH_DECL_NEW(mvuart_mbus, sizeof(struct com_softc), mvuart_match, mvuart_attach, NULL, NULL); #ifdef COM_REGMAP -#define MVUART_INIT_REGS(regs, tag, hdl, addr, size) \ - do { \ - int i; \ - \ - regs.cr_iot = tag; \ - regs.cr_ioh = hdl; \ - regs.cr_iobase = addr; \ - regs.cr_nports = size; \ - for (i = 0; i < __arraycount(regs.cr_map); i++) \ - regs.cr_map[i] = com_std_map[i] << 2; \ +#define MVUART_INIT_REGS(regs, tag, hdl, addr, size) \ + do { \ + int _i; \ + \ + regs.cr_iot = tag; \ + regs.cr_ioh = hdl; \ + regs.cr_iobase = addr; \ + regs.cr_nports = size; \ + for (_i = 0; _i < __arraycount(regs.cr_map); _i++) \ + regs.cr_map[_i] = com_std_map[_i] << 2; \ } while (0) +#define CSR_WRITE_1(r, o, v) \ + bus_space_write_1((r)->cr_iot, (r)->cr_ioh, (r)->cr_map[o], v) +#define CSR_READ_1(r, o) \ + bus_space_read_1((r)->cr_iot, (r)->cr_ioh, (r)->cr_map[o]) #else #define MVUART_INIT_REGS(regs, tag, hdl, addr, size) \ COM_INIT_REGS(regs, tag, hdl, addr) +#define CSR_WRITE_1(r, o, v) \ + bus_space_write_1((r)->cr_iot, (r)->cr_ioh, o, v) +#define CSR_READ_1(r, o) \ + bus_space_read_1((r)->cr_iot, (r)->cr_ioh, o) #endif +struct { + int model; + int type; +} mvuart_extensions[] = { + { MARVELL_ARMADAXP_MV78130, COM_TYPE_ARMADAXP }, + { MARVELL_ARMADAXP_MV78160, COM_TYPE_ARMADAXP }, + { MARVELL_ARMADAXP_MV78230, COM_TYPE_ARMADAXP }, + { MARVELL_ARMADAXP_MV78260, COM_TYPE_ARMADAXP }, + { MARVELL_ARMADAXP_MV78460, COM_TYPE_ARMADAXP }, +}; /* ARGSUSED */ static int @@ -111,6 +134,7 @@ bus_space_tag_t iot; bus_space_handle_t ioh; prop_dictionary_t dict = device_properties(self); + int i; sc->sc_dev = self; @@ -130,9 +154,59 @@ MVUART_INIT_REGS(sc->sc_regs, iot, ioh, mva->mva_addr + mva->mva_offset, mva->mva_size); + for (i = 0; i < __arraycount(mvuart_extensions); i++) + if (mva->mva_model == mvuart_extensions[i].model) { + sc->sc_type = mvuart_extensions[i].type; + break; + } + com_attach_subr(sc); - marvell_intr_establish(mva->mva_irq, IPL_SERIAL, comintr, sc); + if (sc->sc_type == COM_TYPE_ARMADAXP) + marvell_intr_establish(mva->mva_irq, IPL_SERIAL, + mvuart_intr, sc); + else + marvell_intr_establish(mva->mva_irq, IPL_SERIAL, comintr, sc); +} + +static int +mvuart_intr(void *arg) +{ + struct com_softc *sc = arg; + struct com_regs *regsp = &sc->sc_regs; + int timeout; + uint8_t iir, v; + + if (!device_is_active(sc->sc_dev)) + return 0; + + KASSERT(regsp != NULL); + + mutex_spin_enter(&sc->sc_lock); + iir = CSR_READ_1(regsp, COM_REG_IIR); + if ((iir & IIR_BUSY) == IIR_BUSY) { + /* + * XXXXX: What is this? I don't found in Marvell datasheet. + * Maybe workaround for BUG in UART. + */ + v = bus_space_read_1(regsp->cr_iot, regsp->cr_ioh, + MVUART_REG_USR); + for (timeout = 10000; (v & 0x1) != 0; timeout--) { + if (timeout <= 0) { + aprint_error_dev(sc->sc_dev, + "timeout while waiting for BUSY interrupt " + "acknowledge\n"); + mutex_spin_exit(&sc->sc_lock); + return 0; + } + v = bus_space_read_1(regsp->cr_iot, regsp->cr_ioh, + MVUART_REG_USR); + } + CSR_WRITE_1(regsp, COM_REG_LCR, sc->sc_lcr); + } + mutex_spin_exit(&sc->sc_lock); + + return comintr(arg); } #ifdef COM_REGMAP
Index: ic/com.c =================================================================== RCS file: /cvsroot/src/sys/dev/ic/com.c,v retrieving revision 1.312 diff -u -r1.312 com.c --- ic/com.c 27 Jul 2013 06:54:35 -0000 1.312 +++ ic/com.c 24 Aug 2013 05:39:38 -0000 @@ -384,9 +374,7 @@ { struct com_regs *regsp = &sc->sc_regs; struct tty *tp; -#ifdef COM_16650 u_int8_t lcr; -#endif const char *fifo_msg = NULL; prop_dictionary_t dict; bool is_console = true; @@ -493,6 +478,37 @@ #endif sc->sc_fifolen = 16; + /* + * TL16C750 can enable 64byte FIFO, only when DLAB + * is 1. However, some 16750 may always enable. For + * example, restrictions according to DLAB in a data + * sheet for SC16C750 were not described. + * Please enable 'options COM_16650', supposing you + * use SC16C750. Probably 32 bytes of FIFO and HW FLOW + * should become effective. + */ + uint8_t iir1, iir2; + const uint8_t fcr = FIFO_ENABLE | FIFO_TRIGGER_14; + + lcr = CSR_READ_1(regsp, COM_REG_LCR); + CSR_WRITE_1(regsp, COM_REG_LCR, lcr & ~LCR_DLAB); + CSR_WRITE_1(regsp, COM_REG_FIFO, fcr | FIFO_64B_ENABLE); + iir1 = CSR_READ_1(regsp, COM_REG_IIR); + CSR_WRITE_1(regsp, COM_REG_FIFO, fcr); + CSR_WRITE_1(regsp, COM_REG_LCR, lcr | LCR_DLAB); + CSR_WRITE_1(regsp, COM_REG_FIFO, fcr | FIFO_64B_ENABLE); + iir2 = CSR_READ_1(regsp, COM_REG_IIR); + + CSR_WRITE_1(regsp, COM_REG_LCR, lcr); + + if (!ISSET(iir1, IIR_64B_FIFO) && + ISSET(iir2, IIR_64B_FIFO)) { + /* It is TL16C750. */ + sc->sc_fifolen = 64; + SET(sc->sc_hwflags, COM_HW_FLOW); + } else + CSR_WRITE_1(regsp, COM_REG_FIFO, fcr); + #ifdef COM_16650 CSR_WRITE_1(regsp, COM_REG_LCR, lcr); if (sc->sc_fifolen == 0) @@ -501,6 +517,9 @@ fifo_msg = "st16650a, working fifo"; else #endif + if (sc->sc_fifolen == 64) + fifo_msg = "tl16c750, working fifo"; + else fifo_msg = "ns16550a, working fifo"; } else fifo_msg = "ns16550, broken fifo"; @@ -1479,19 +1498,19 @@ aprint_error_dev(sc->sc_dev, "com_iflush timeout %02x\n", reg); #endif Index: ic/comreg.h =================================================================== RCS file: /cvsroot/src/sys/dev/ic/comreg.h,v retrieving revision 1.18 diff -u -r1.18 comreg.h --- ic/comreg.h 20 Apr 2013 11:52:41 -0000 1.18 +++ ic/comreg.h 24 Aug 2013 05:39:38 -0000 @@ -63,6 +63,7 @@ #define IIR_TXRDY 0x2 /* Transmitter ready */ #define IIR_MLSC 0x0 /* Modem status */ #define IIR_NOPEND 0x1 /* No pending interrupts */ +#define IIR_64B_FIFO 0x20 /* 64byte FIFO Enabled (16750) */ #define IIR_FIFO_MASK 0xc0 /* set if FIFOs are enabled */ @@ -72,6 +72,7 @@ #define FIFO_XMT_RST 0x04 /* Reset TX FIFO */ #define FIFO_DMA_MODE 0x08 #define FIFO_TRIGGER_1 0x00 /* Trigger RXRDY intr on 1 character */ +#define FIFO_64B_ENABLE 0x20 /* 64byte FIFO Enable (16750) */ #define FIFO_TRIGGER_4 0x40 /* ibid 4 */ #define FIFO_TRIGGER_8 0x80 /* ibid 8 */ #define FIFO_TRIGGER_14 0xc0 /* ibid 14 */