File: [local] / funnyos / arch / testarm / dev / tartc.c (download)
Revision 1.5, Tue Nov 6 22:57:45 2007 UTC (16 years, 7 months ago) by init
Branch: MAIN
Changes since 1.4: +64 -13 lines
Complete testarm Real Time Clock driver with use of new kern_time interface.
enter sysclock() at every RTC interrupt.
|
/*
* $Id: tartc.c,v 1.5 2007/11/06 22:57:45 init Exp $
*/
#include <sys/types.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>
/*
* 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);
}