Hi!
I mistook commit the other day. http://mail-index.NetBSD.org/source-changes/2013/09/01/msg047120.html Although the processing for this ARMADAXP was moved to com_mv.c, IIR of com is reset by reading. That is, since IIR was read by mvuart_intr(), IIR was not able to be correctly read by comintr(). I would like to add the next member to com_softc, in order to solve this problem. /* XXXX: vendor workaround functions */ int (*sc_vendor_workaround)(struct com_softc *); Processing which avoids BUSY of ARMADAXP is performed by calling this from comintr() at the time of COM_TYPE_ARMADAXP. Probably addition of this member will consume many several bytes of memories by almost all your machines. However, no machines other than ARMADAXP call this. I would like to merge this correction. Please let me know your opinion. Probably, it will be more desirable for this member to add reasoncode and value of int to an argument for other LSI with fault. int (*sc_vendor_workaround)(struct com_softc *, int reasoncode, int val); Thanks, -- kiyohara
Index: ic/com.c =================================================================== RCS file: /cvsroot/src/sys/dev/ic/com.c,v retrieving revision 1.314 diff -u -r1.314 com.c --- ic/com.c 1 Sep 2013 04:58:15 -0000 1.314 +++ ic/com.c 24 Sep 2013 11:00:02 -0000 @@ -1938,6 +1938,18 @@ mutex_spin_enter(&sc->sc_lock); iir = CSR_READ_1(regsp, COM_REG_IIR); + if (sc->sc_type == COM_TYPE_ARMADAXP) { + if ((iir & IIR_BUSY) == IIR_BUSY) { + if (sc->sc_vendor_workaround != NULL && + sc->sc_vendor_workaround(sc) != 0) { + mutex_spin_exit(&sc->sc_lock); + return (0); + } + CSR_WRITE_1(regsp, COM_REG_LCR, sc->sc_lcr); + iir = CSR_READ_1(regsp, COM_REG_IIR); + } + } + if (ISSET(iir, IIR_NOPEND)) { mutex_spin_exit(&sc->sc_lock); return (0); Index: ic/comvar.h =================================================================== RCS file: /cvsroot/src/sys/dev/ic/comvar.h,v retrieving revision 1.76 diff -u -r1.76 comvar.h --- ic/comvar.h 1 Sep 2013 04:51:24 -0000 1.76 +++ ic/comvar.h 24 Sep 2013 11:00:02 -0000 @@ -226,6 +226,9 @@ void (*disable)(struct com_softc *); int enabled; + /* XXXX: vendor workaround functions */ + int (*sc_vendor_workaround)(struct com_softc *); + struct pps_state sc_pps_state; /* pps state */ #ifdef RND_COM Index: marvell/com_mv.c =================================================================== RCS file: /cvsroot/src/sys/dev/marvell/com_mv.c,v retrieving revision 1.6 diff -u -r1.6 com_mv.c --- marvell/com_mv.c 1 Sep 2013 04:51:24 -0000 1.6 +++ marvell/com_mv.c 24 Sep 2013 11:00:04 -0000 @@ -53,7 +53,7 @@ static int mvuart_match(device_t, struct cfdata *, void *); static void mvuart_attach(device_t, device_t, void *); -static int mvuart_intr(void *); +static int mvuart_armadaxp_workaround(struct com_softc *); CFATTACH_DECL_NEW(mvuart_gt, sizeof(struct com_softc), mvuart_match, mvuart_attach, NULL, NULL); @@ -88,12 +88,14 @@ struct { int model; int type; + int (*workaround)(struct com_softc *); } 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 }, +#define MV(x) MARVELL_ ## x + { MV(ARMADAXP_MV78130), COM_TYPE_ARMADAXP, mvuart_armadaxp_workaround }, + { MV(ARMADAXP_MV78160), COM_TYPE_ARMADAXP, mvuart_armadaxp_workaround }, + { MV(ARMADAXP_MV78230), COM_TYPE_ARMADAXP, mvuart_armadaxp_workaround }, + { MV(ARMADAXP_MV78260), COM_TYPE_ARMADAXP, mvuart_armadaxp_workaround }, + { MV(ARMADAXP_MV78460), COM_TYPE_ARMADAXP, mvuart_armadaxp_workaround }, }; /* ARGSUSED */ @@ -157,56 +159,40 @@ for (i = 0; i < __arraycount(mvuart_extensions); i++) if (mva->mva_model == mvuart_extensions[i].model) { sc->sc_type = mvuart_extensions[i].type; + sc->sc_vendor_workaround = + mvuart_extensions[i].workaround; break; } com_attach_subr(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); + marvell_intr_establish(mva->mva_irq, IPL_SERIAL, comintr, sc); } static int -mvuart_intr(void *arg) +mvuart_armadaxp_workaround(struct com_softc *sc) { - struct com_softc *sc = arg; struct com_regs *regsp = &sc->sc_regs; int timeout; - uint8_t iir, v; + uint8_t 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. - */ + /* + * 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"); + return -1; + } 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); + return 0; } #ifdef COM_REGMAP