123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169 |
- #include "u.h"
- #include "../port/lib.h"
- #include "mem.h"
- #include "dat.h"
- #include "fns.h"
- #include "../port/error.h"
- #include "io.h"
- /*
- * SA11x0 real time clock
- * TO DO: alarms, wakeup, allow trim setting(?)
- */
- enum{
- Qdir,
- Qrtc,
- Qrtctrim,
- };
- static Dirtab rtcdir[]={
- ".", {Qdir,0,QTDIR}, 0, 0555,
- "rtc", {Qrtc}, NUMSIZE, 0664,
- "rtctrim", {Qrtctrim}, 0, 0664,
- };
- #define NRTC (sizeof(rtcdir)/sizeof(rtcdir[0]))
- extern ulong boottime;
- enum {
- RTSR_al= 1<<0, /* RTC alarm detected */
- RTSR_hz= 1<<1, /* 1-Hz rising-edge detected */
- RTSR_ale= 1<<2, /* RTC alarm interrupt enabled */
- RTSR_hze= 1<<3, /* 1-Hz interrupt enable */
- };
- static void
- rtcreset(void)
- {
- RTCreg *r;
- r = RTCREG;
- if((r->rttr & 0xFFFF) == 0){ /* reset state */
- r->rttr = 32768-1;
- r->rcnr = boottime; /* typically zero */
- }
- r->rtar = ~0;
- r->rtsr = RTSR_al | RTSR_hz;
- }
- static Chan*
- rtcattach(char *spec)
- {
- return devattach('r', spec);
- }
- static Walkqid*
- rtcwalk(Chan *c, Chan *nc, char **name, int nname)
- {
- return devwalk(c, nc, name, nname, rtcdir, NRTC, devgen);
- }
- static int
- rtcstat(Chan *c, uchar *dp, int n)
- {
- return devstat(c, dp, n, rtcdir, NRTC, devgen);
- }
- static Chan*
- rtcopen(Chan *c, int omode)
- {
- return devopen(c, omode, rtcdir, NRTC, devgen);
- }
- static void
- rtcclose(Chan*)
- {
- }
- static long
- rtcread(Chan *c, void *buf, long n, vlong off)
- {
- if(c->qid.type & QTDIR)
- return devdirread(c, buf, n, rtcdir, NRTC, devgen);
- switch((ulong)c->qid.path){
- case Qrtc:
- return readnum(off, buf, n, RTCREG->rcnr, NUMSIZE);
- case Qrtctrim:
- return readnum(off, buf, n, RTCREG->rttr, NUMSIZE);
- }
- error(Egreg);
- return 0; /* not reached */
- }
- static long
- rtcwrite(Chan *c, void *buf, long n, vlong off)
- {
- ulong offset = off;
- ulong secs;
- char *cp, sbuf[32];
- switch((ulong)c->qid.path){
- case Qrtc:
- /*
- * write the time
- */
- if(offset != 0 || n >= sizeof(sbuf)-1)
- error(Ebadarg);
- memmove(sbuf, buf, n);
- sbuf[n] = '\0';
- cp = sbuf;
- while(*cp){
- if(*cp>='0' && *cp<='9')
- break;
- cp++;
- }
- secs = strtoul(cp, 0, 0);
- RTCREG->rcnr = secs;
- return n;
- case Qrtctrim:
- if(offset != 0 || n >= sizeof(sbuf)-1)
- error(Ebadarg);
- memmove(sbuf, buf, n);
- sbuf[n] = '\0';
- RTCREG->rttr = strtoul(sbuf, 0, 0);
- return n;
- }
- error(Egreg);
- return 0; /* not reached */
- }
- static void
- rtcpower(int on)
- {
- if(on)
- boottime = RTCREG->rcnr - TK2SEC(MACHP(0)->ticks);
- else
- RTCREG->rcnr = seconds();
- }
- long
- rtctime(void)
- {
- return RTCREG->rcnr;
- }
- Dev rtcdevtab = {
- 'r',
- "rtc",
- rtcreset,
- devinit,
- devshutdown,
- rtcattach,
- rtcwalk,
- rtcstat,
- rtcopen,
- devcreate,
- rtcclose,
- rtcread,
- devbread,
- rtcwrite,
- devbwrite,
- devremove,
- devwstat,
- rtcpower,
- };
|