/* * $Id: tartc.c,v 1.5 2007/11/06 22:57:45 init Exp $ */ #include #include #include #include #include #include #include /* * testarm Real Time Clock driver. */ int tartc_attach(struct device *, uint32_t loc, uint8_t flags); void tartc_interrupt(struct device *); void tartc_sethz(uint8_t hz); uint32_t tartc_getsec(void); uint32_t tartc_getusec(void); /* default tartc device to use; will bind to first tartc instance */ struct tartc_dd *tartcdd = NULL; extern struct rtcops sysrtcops; struct driver tartc_dr = { sizeof(struct tartc_dd), tartc_attach, NULL, tartc_interrupt }; int tartc_attach(struct device *self, uint32_t loc, uint8_t flags) { struct tartc_dd *ddp = self->dv_devdata; uint32_t seconds; /* acquire bus_handle from parent */ ddp->td_bushandlep = self->dv_parent->dv_aux; /* save our location on parent (or use default if loc == 0) */ ddp->td_ioaddr = (loc != 0) ? loc : TARTC_REG_BASE; /* * Read seconds past Epoch. */ /* trigger clock update on host */ bus_write_1(ddp->td_bushandlep, ddp->td_ioaddr + TARTC_OFF_CLOCKUPDATE, 1); /* get seconds past Epoch */ seconds = bus_read_4(ddp->td_bushandlep, ddp->td_ioaddr + TARTC_OFF_READSECONDS); printf("testarm Real Time Clock (%d seconds past Epoch)\n", seconds); /* set default tartc */ tartcdd = ddp; /* fill-in rtcops to be used by kern_time */ sysrtcops.ro_sethz = tartc_sethz; sysrtcops.ro_getsec = tartc_getsec; sysrtcops.ro_getusec = tartc_getusec; return(0); } void tartc_sethz(uint8_t hz) { /* * Set timer frequency. */ if (tartcdd == NULL) panic("can't calibrate not configured timer\n"); bus_write_1(tartcdd->td_bushandlep, tartcdd->td_ioaddr + TARTC_OFF_TMRINTRFREQ, hz); } uint32_t tartc_getsec(void) { /* * Get seconds. */ if (tartcdd == NULL) panic("tartc_getsec: can't get seconds from rtc: default device not configured\n"); /* trigger clock update on host */ bus_write_1(tartcdd->td_bushandlep, tartcdd->td_ioaddr + TARTC_OFF_CLOCKUPDATE, 1); return( bus_read_4(tartcdd->td_bushandlep, tartcdd->td_ioaddr + TARTC_OFF_READSECONDS) ); } uint32_t tartc_getusec(void) { /* * Get microseconds. */ if (tartcdd == NULL) panic("tartc_getusec: can't get microseconds from rtc: default device not configured\n"); /* trigger clock update on host */ bus_write_1(tartcdd->td_bushandlep, tartcdd->td_ioaddr + TARTC_OFF_CLOCKUPDATE, 1); return( bus_read_4(tartcdd->td_bushandlep, tartcdd->td_ioaddr + TARTC_OFF_READUSECONDS) ); } void tartc_interrupt(struct device *self) { struct tartc_dd *ddp = self->dv_devdata; /* process system tick */ sysclock(); /* acknowledge one timer intr */ bus_write_1(ddp->td_bushandlep, ddp->td_ioaddr + TARTC_OFF_TMRINTRACK, 0xff); }