Esempio n. 1
0
static void
zy7_devcfg_intr(void *arg)
{
	struct zy7_devcfg_softc *sc = (struct zy7_devcfg_softc *)arg;
	uint32_t istatus, imask;

	DEVCFG_SC_LOCK(sc);

	istatus = RD4(sc, ZY7_DEVCFG_INT_STATUS);
	imask = ~RD4(sc, ZY7_DEVCFG_INT_MASK);

	/* Turn interrupt off. */
	WR4(sc, ZY7_DEVCFG_INT_MASK, ~0);

	if ((istatus & imask) == 0) {
		DEVCFG_SC_UNLOCK(sc);
		return;
	}

	/* DMA done? */
	if ((istatus & ZY7_DEVCFG_INT_DMA_DONE) != 0)
		wakeup(sc->dma_map);

	/* INIT_B positive edge? */
	if ((istatus & ZY7_DEVCFG_INT_PCFG_INIT_PE) != 0)
		wakeup(sc);

	DEVCFG_SC_UNLOCK(sc);
}
Esempio n. 2
0
static int
zy7_devcfg_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
{
	struct zy7_devcfg_softc *sc = dev->si_drv1;
	int err;

	DEVCFG_SC_LOCK(sc);
	if (sc->is_open) {
		DEVCFG_SC_UNLOCK(sc);
		return (EBUSY);
	}

	sc->dma_map = NULL;
	err = bus_dma_tag_create(bus_get_dma_tag(sc->dev), 4, 0,
				 BUS_SPACE_MAXADDR_32BIT,
				 BUS_SPACE_MAXADDR,
				 NULL, NULL,
				 PAGE_SIZE,
				 1,
				 PAGE_SIZE,
				 0,
				 busdma_lock_mutex,
				 &sc->sc_mtx,
				 &sc->dma_tag);
	if (err) {
		DEVCFG_SC_UNLOCK(sc);
		return (err);
	}

	sc->is_open = 1;
	DEVCFG_SC_UNLOCK(sc);
	return (0);
}
Esempio n. 3
0
static int
zy7_devcfg_close(struct cdev *dev, int fflag, int devtype, struct thread *td)
{
	struct zy7_devcfg_softc *sc = dev->si_drv1;

	DEVCFG_SC_LOCK(sc);
	sc->is_open = 0;
	bus_dma_tag_destroy(sc->dma_tag);
	DEVCFG_SC_UNLOCK(sc);

	return (0);
}
Esempio n. 4
0
/* zy7_devcfg_sysctl_pl_done() returns status of the PL_DONE signal.
 */
static int
zy7_devcfg_sysctl_pl_done(SYSCTL_HANDLER_ARGS)
{
	struct zy7_devcfg_softc *sc = zy7_devcfg_softc_p;
	int pl_done = 0;

	if (sc) {
		DEVCFG_SC_LOCK(sc);

		/* PCFG_DONE bit is sticky.  Clear it before checking it. */
		WR4(sc, ZY7_DEVCFG_INT_STATUS, ZY7_DEVCFG_INT_PCFG_DONE);
		pl_done = ((RD4(sc, ZY7_DEVCFG_INT_STATUS) &
			    ZY7_DEVCFG_INT_PCFG_DONE) != 0);

		DEVCFG_SC_UNLOCK(sc);
	}
	return (sysctl_handle_int(oidp, &pl_done, 0, req));
}
Esempio n. 5
0
static int
zy7_devcfg_write(struct cdev *dev, struct uio *uio, int ioflag)
{
	struct zy7_devcfg_softc *sc = dev->si_drv1;
	void *dma_mem;
	bus_addr_t dma_physaddr;
	int segsz, err;

	DEVCFG_SC_LOCK(sc);

	/* First write?  Reset PL. */
	if (uio->uio_offset == 0 && uio->uio_resid > 0)	{
		zy7_devcfg_init_hw(sc);
		zy7_slcr_preload_pl();
		err = zy7_devcfg_reset_pl(sc);
		if (err != 0) {
			DEVCFG_SC_UNLOCK(sc);
			return (err);
		}
	}

	/* Allocate dma memory and load. */
	err = bus_dmamem_alloc(sc->dma_tag, &dma_mem, BUS_DMA_NOWAIT,
			       &sc->dma_map);
	if (err != 0) {
		DEVCFG_SC_UNLOCK(sc);
		return (err);
	}
	err = bus_dmamap_load(sc->dma_tag, sc->dma_map, dma_mem, PAGE_SIZE,
			      zy7_dma_cb2, &dma_physaddr, 0);
	if (err != 0) {
		bus_dmamem_free(sc->dma_tag, dma_mem, sc->dma_map);
		DEVCFG_SC_UNLOCK(sc);
		return (err);
	}

	while (uio->uio_resid > 0) {
		/* If DONE signal has been set, we shouldn't write anymore. */
		if ((RD4(sc, ZY7_DEVCFG_INT_STATUS) &
		     ZY7_DEVCFG_INT_PCFG_DONE) != 0) {
			err = EIO;
			break;
		}

		/* 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;

		/* Flush the cache to memory. */
		bus_dmamap_sync(sc->dma_tag, sc->dma_map,
				BUS_DMASYNC_PREWRITE);

		/* Program devcfg's DMA engine.  The ordering of these
		 * register writes is critical.
		 */
		if (uio->uio_resid > segsz)
			WR4(sc, ZY7_DEVCFG_DMA_SRC_ADDR,
			    (uint32_t) dma_physaddr);
		else
			WR4(sc, ZY7_DEVCFG_DMA_SRC_ADDR,
			    (uint32_t) dma_physaddr |
			    ZY7_DEVCFG_DMA_ADDR_WAIT_PCAP);
		WR4(sc, ZY7_DEVCFG_DMA_DST_ADDR, ZY7_DEVCFG_DMA_ADDR_ILLEGAL);
		WR4(sc, ZY7_DEVCFG_DMA_SRC_LEN, (segsz+3)/4);
		WR4(sc, ZY7_DEVCFG_DMA_DST_LEN, 0);

		/* Now clear done bit and set up DMA done interrupt. */
		WR4(sc, ZY7_DEVCFG_INT_STATUS, ZY7_DEVCFG_INT_ALL);
		WR4(sc, ZY7_DEVCFG_INT_MASK, ~ZY7_DEVCFG_INT_DMA_DONE);

		/* Wait for DMA done interrupt. */
		err = mtx_sleep(sc->dma_map, &sc->sc_mtx, PCATCH,
				"zy7dma", hz);
		if (err != 0)
			break;

		bus_dmamap_sync(sc->dma_tag, sc->dma_map,
				BUS_DMASYNC_POSTWRITE);

		/* Check DONE signal. */
		if ((RD4(sc, ZY7_DEVCFG_INT_STATUS) &
		     ZY7_DEVCFG_INT_PCFG_DONE) != 0)
			zy7_slcr_postload_pl(zy7_en_level_shifters);
	}

	bus_dmamap_unload(sc->dma_tag, sc->dma_map);
	bus_dmamem_free(sc->dma_tag, dma_mem, sc->dma_map);
	DEVCFG_SC_UNLOCK(sc);
	return (err);
}