version 1.1.1.1, 2007/10/16 09:41:04 |
version 1.6, 2007/11/06 23:02:14 |
|
|
*/ |
*/ |
#include <sys/types.h> |
#include <sys/types.h> |
#include <sys/device.h> |
#include <sys/device.h> |
|
#include <sys/bus.h> |
|
|
|
#include <sys/kern_time.h> |
|
#include <arch/testarm/dev/tartcvar.h> |
|
#include <arch/testarm/dev/tartcreg.h> |
#include <libkern/printf.h> |
#include <libkern/printf.h> |
|
|
/* |
/* |
* testarm Real Time Clock driver. |
* 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); |
|
|
/* TODO */ |
|
|
|
|
/* 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 |
int |
tartc_attach(struct device *self) |
tartc_attach(struct device *self, uint32_t loc, uint8_t flags) |
{ |
{ |
|
struct tartc_dd *ddp = self->dv_devdata; |
|
uint32_t seconds; |
|
|
printf("testarm Real Time Clock\n"); |
/* 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); |
return(0); |
|
|
|
} |
|
|
|
|
|
void |
|
tartc_sethz(uint8_t hz) |
|
{ |
|
/* |
|
* Set timer frequency. |
|
*/ |
|
if (tartcdd == NULL) |
|
panic("tartc_sethz: can't calibrate timer: default device not configured\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); |
} |
} |
|
|