void at91_pit_delay(int us) { int32_t cnt, last, piv; uint64_t pit_freq; const uint64_t mhz = 1E6; if (sc == NULL) return; last = PIT_PIV(RD4(sc, PIT_PIIR)); /* Max delay ~= 260s. @ 133Mhz */ pit_freq = at91_master_clock / PIT_PRESCALE; cnt = ((pit_freq * us) + (mhz -1)) / mhz; cnt = (cnt <= 0) ? 1 : cnt; while (cnt > 0) { piv = PIT_PIV(RD4(sc, PIT_PIIR)); cnt -= piv - last ; if (piv < last) cnt -= PIT_PIV(~0u) - last; last = piv; } }
static int pit_intr(void *arg) { struct trapframe *fp = arg; uint32_t icnt; if (RD4(sc, PIT_SR) & PIT_PITS_DONE) { icnt = RD4(sc, PIT_PIVR) >> 20; /* Just add in the overflows we just read */ timecount += PIT_PIV(RD4(sc, PIT_MR)) * icnt; hardclock(TRAPF_USERMODE(fp), TRAPF_PC(fp)); return (FILTER_HANDLED); }
void cpu_initclocks(void) { struct at91_pmc_clock *master; master = at91_pmc_clock_ref("mck"); pit_rate = master->hz / 16; pit_cycle = (pit_rate + HZ/2) / HZ; at91pit_timecounter.tc_frequency = pit_rate; WR4(PIT_MR, 0); while (PIT_PIV(RD4(PIT_PIVR)) != 0); WR4(PIT_MR, (pit_cycle - 1) | PIT_IEN | PIT_EN); tc_init(&at91pit_timecounter); }
static int at91_pit_attach(device_t dev) { void *ih; int rid, err = 0; struct at91_softc *at91_sc; struct resource *irq; at91_sc = device_get_softc(device_get_parent(dev)); sc = device_get_softc(dev); sc->sc_dev = dev; rid = 0; sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); if (sc->mem_res == NULL) panic("couldn't allocate register resources"); rid = 0; irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 1, 1, 1, RF_ACTIVE | RF_SHAREABLE); if (!irq) { device_printf(dev, "could not allocate interrupt resources.\n"); err = ENOMEM; goto out; } /* Activate the interrupt. */ err = bus_setup_intr(dev, irq, INTR_TYPE_CLK, pit_intr, NULL, NULL, &ih); at91_pit_timecounter.tc_frequency = at91_master_clock / PIT_PRESCALE; tc_init(&at91_pit_timecounter); /* Enable the PIT here. */ WR4(sc, PIT_MR, PIT_PIV(at91_master_clock / PIT_PRESCALE / hz) | PIT_EN | PIT_IEN); out: return (err); }