/* Clear previous configuration of the PL by asserting PROG_B. */ static int zy7_devcfg_reset_pl(struct zy7_devcfg_softc *sc) { uint32_t devcfg_ctl; int tries, err; DEVCFG_SC_ASSERT_LOCKED(sc); devcfg_ctl = RD4(sc, ZY7_DEVCFG_CTRL); /* 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); } /* Reassert PROG_B. */ devcfg_ctl &= ~ZY7_DEVCFG_CTRL_PCFG_PROG_B; WR4(sc, ZY7_DEVCFG_CTRL, devcfg_ctl); /* Wait for INIT_B asserted. */ tries = 0; while ((RD4(sc, ZY7_DEVCFG_STATUS) & ZY7_DEVCFG_STATUS_PCFG_INIT) != 0) { if (++tries >= 100) return (EIO); DELAY(5); } /* Clear sticky bits and set up INIT_B 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 again. */ 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). */ err = mtx_sleep(sc, &sc->sc_mtx, PCATCH, "zy7in", hz); if (err != 0) return (err); /* Clear sticky DONE bit in interrupt status. */ WR4(sc, ZY7_DEVCFG_INT_STATUS, ZY7_DEVCFG_INT_ALL); return (0); }
/* Enable programming the PL through PCAP. */ static void zy7_devcfg_init_hw(struct zy7_devcfg_softc *sc) { DEVCFG_SC_ASSERT_LOCKED(sc); /* Set devcfg control register. */ WR4(sc, ZY7_DEVCFG_CTRL, ZY7_DEVCFG_CTRL_PCFG_PROG_B | ZY7_DEVCFG_CTRL_PCAP_PR | ZY7_DEVCFG_CTRL_PCAP_MODE | ZY7_DEVCFG_CTRL_USER_MODE | ZY7_DEVCFG_CTRL_RESVD_WR11 | ZY7_DEVCFG_CTRL_SPNIDEN | ZY7_DEVCFG_CTRL_SPIDEN | ZY7_DEVCFG_CTRL_NIDEN | ZY7_DEVCFG_CTRL_DBGEN | ZY7_DEVCFG_CTRL_DAP_EN_MASK); /* Turn off internal PCAP loopback. */ WR4(sc, ZY7_DEVCFG_MCTRL, RD4(sc, ZY7_DEVCFG_MCTRL) & ~ZY7_DEVCFG_MCTRL_INT_PCAP_LPBK); }
/* Clear previous configuration of the PL by asserting PROG_B. */ static int zy7_devcfg_reset_pl(struct zy7_devcfg_softc *sc) { uint32_t devcfg_ctl; int tries, err; DEVCFG_SC_ASSERT_LOCKED(sc); 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 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 (active low). */ devcfg_ctl &= ~ZY7_DEVCFG_CTRL_PCFG_PROG_B; WR4(sc, ZY7_DEVCFG_CTRL, devcfg_ctl); /* Wait for INIT deasserted. This happens almost instantly. */ tries = 0; while ((RD4(sc, ZY7_DEVCFG_STATUS) & ZY7_DEVCFG_STATUS_PCFG_INIT) != 0) { if (++tries >= 100) return (EIO); DELAY(5); } /* 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); /* Deassert PROG_B again. */ devcfg_ctl |= ZY7_DEVCFG_CTRL_PCFG_PROG_B; WR4(sc, ZY7_DEVCFG_CTRL, devcfg_ctl); /* * Wait for INIT asserted indicating FPGA internal initialization * is complete. */ err = mtx_sleep(sc, &sc->sc_mtx, PCATCH, "zy7i2", hz); if (err != 0) return (err); /* Clear sticky DONE bit in interrupt status. */ WR4(sc, ZY7_DEVCFG_INT_STATUS, ZY7_DEVCFG_INT_ALL); return (0); }