Date: Thu, 8 May 2014 17:20:45 +0000 (UTC) From: Ian Lepore <ian@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r265690 - head/sys/arm/xilinx Message-ID: <201405081720.s48HKjCM034671@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: ian Date: Thu May 8 17:20:45 2014 New Revision: 265690 URL: http://svnweb.freebsd.org/changeset/base/265690 Log: Use edge-triggered interrupts rather than polling loops to avoid missing transitions of the INIT_B line. Also, release the mutex during uiomove(). Submitted by: Thomas Skibo <ThomasSkibo@sbcglobal.net> Modified: head/sys/arm/xilinx/zy7_devcfg.c Modified: head/sys/arm/xilinx/zy7_devcfg.c ============================================================================== --- head/sys/arm/xilinx/zy7_devcfg.c Thu May 8 16:59:36 2014 (r265689) +++ head/sys/arm/xilinx/zy7_devcfg.c Thu May 8 17:20:45 2014 (r265690) @@ -267,24 +267,35 @@ zy7_devcfg_reset_pl(struct zy7_devcfg_so devcfg_ctl = RD4(sc, ZY7_DEVCFG_CTRL); + /* Clear sticky bits and set up INIT signal positive edge interrupt. */ + WR4(sc, ZY7_DEVCFG_INT_STATUS, ZY7_DEVCFG_INT_ALL); + WR4(sc, ZY7_DEVCFG_INT_MASK, ~ZY7_DEVCFG_INT_PCFG_INIT_PE); + /* Deassert PROG_B (active low). */ devcfg_ctl |= ZY7_DEVCFG_CTRL_PCFG_PROG_B; WR4(sc, ZY7_DEVCFG_CTRL, devcfg_ctl); - /* Wait for INIT_B deasserted (active low). */ - tries = 0; - while ((RD4(sc, ZY7_DEVCFG_STATUS) & - ZY7_DEVCFG_STATUS_PCFG_INIT) == 0) { - if (++tries >= 100) - return (EIO); - DELAY(5); + /* + * Wait for INIT to assert. If it is already asserted, we may not get + * an edge interrupt so cancel it and continue. + */ + if ((RD4(sc, ZY7_DEVCFG_STATUS) & + ZY7_DEVCFG_STATUS_PCFG_INIT) != 0) { + /* Already asserted. Cancel interrupt. */ + WR4(sc, ZY7_DEVCFG_INT_MASK, ~0); + } + else { + /* Wait for positive edge interrupt. */ + err = mtx_sleep(sc, &sc->sc_mtx, PCATCH, "zy7i1", hz); + if (err != 0) + return (err); } - - /* Reassert PROG_B. */ + + /* Reassert PROG_B (active low). */ devcfg_ctl &= ~ZY7_DEVCFG_CTRL_PCFG_PROG_B; WR4(sc, ZY7_DEVCFG_CTRL, devcfg_ctl); - /* Wait for INIT_B asserted. */ + /* Wait for INIT deasserted. This happens almost instantly. */ tries = 0; while ((RD4(sc, ZY7_DEVCFG_STATUS) & ZY7_DEVCFG_STATUS_PCFG_INIT) != 0) { @@ -293,7 +304,7 @@ zy7_devcfg_reset_pl(struct zy7_devcfg_so DELAY(5); } - /* Clear sticky bits and set up INIT_B positive edge interrupt. */ + /* Clear sticky bits and set up INIT positive edge interrupt. */ WR4(sc, ZY7_DEVCFG_INT_STATUS, ZY7_DEVCFG_INT_ALL); WR4(sc, ZY7_DEVCFG_INT_MASK, ~ZY7_DEVCFG_INT_PCFG_INIT_PE); @@ -301,11 +312,11 @@ zy7_devcfg_reset_pl(struct zy7_devcfg_so devcfg_ctl |= ZY7_DEVCFG_CTRL_PCFG_PROG_B; WR4(sc, ZY7_DEVCFG_CTRL, devcfg_ctl); - /* Wait for INIT_B deasserted indicating FPGA internal initialization - * is complete. This takes much longer than the previous waits for - * INIT_B transition (on the order of 700us). + /* + * Wait for INIT asserted indicating FPGA internal initialization + * is complete. */ - err = mtx_sleep(sc, &sc->sc_mtx, PCATCH, "zy7in", hz); + err = mtx_sleep(sc, &sc->sc_mtx, PCATCH, "zy7i2", hz); if (err != 0) return (err); @@ -404,7 +415,9 @@ zy7_devcfg_write(struct cdev *dev, struc /* uiomove the data from user buffer to our dma map. */ segsz = MIN(PAGE_SIZE, uio->uio_resid); + DEVCFG_SC_UNLOCK(sc); err = uiomove(dma_mem, segsz, uio); + DEVCFG_SC_LOCK(sc); if (err != 0) break;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201405081720.s48HKjCM034671>