xref: /plan9/sys/src/9/bcm/devfakertc.c (revision 5d9de2d38d2503efca29e12e0e32036368a7a75f)
1 /*
2  * raspberry pi doesn't have a realtime clock
3  * fake a crude approximation from the kernel build time
4  */
5 
6 #include	"u.h"
7 #include	"../port/lib.h"
8 #include	"mem.h"
9 #include	"dat.h"
10 #include	"fns.h"
11 #include	"../port/error.h"
12 
13 enum{
14 	Qdir = 0,
15 	Qrtc,
16 };
17 
18 Dirtab rtcdir[]={
19 	".",	{Qdir, 0, QTDIR},	0,	0555,
20 	"rtc",		{Qrtc, 0},	0,	0664,
21 };
22 
23 extern ulong kerndate;
24 
25 static ulong rtcsecs;
26 
27 static void
rtctick(void)28 rtctick(void)
29 {
30 	rtcsecs++;
31 }
32 
33 static void
rtcinit(void)34 rtcinit(void)
35 {
36 	rtcsecs = kerndate;
37 	addclock0link(rtctick, 1000);
38 }
39 
40 static long
rtcread(Chan * c,void * a,long n,vlong offset)41 rtcread(Chan *c, void *a, long n, vlong offset)
42 {
43 	if(c->qid.type & QTDIR)
44 		return devdirread(c, a, n, rtcdir, nelem(rtcdir), devgen);
45 
46 	switch((ulong)c->qid.path){
47 	case Qrtc:
48 		return readnum((ulong)offset, a, n, rtcsecs, 12);
49 	}
50 	error(Ebadarg);
51 	return 0;
52 }
53 
54 static long
rtcwrite(Chan * c,void * a,long n,vlong)55 rtcwrite(Chan*c, void *a, long n, vlong)
56 {
57 	char b[13];
58 	ulong i;
59 
60 	switch((ulong)c->qid.path){
61 	case Qrtc:
62 		if(n >= sizeof(b))
63 			error(Ebadarg);
64 		strncpy(b, (char*)a, n);
65 		i = strtol(b, 0, 0);
66 		if(i <= 0)
67 			error(Ebadarg);
68 		rtcsecs = i;
69 		return n;
70 	}
71 	error(Eperm);
72 	return 0;
73 }
74 
75 static Chan*
rtcattach(char * spec)76 rtcattach(char* spec)
77 {
78 	return devattach('r', spec);
79 }
80 
81 static Walkqid*
rtcwalk(Chan * c,Chan * nc,char ** name,int nname)82 rtcwalk(Chan* c, Chan *nc, char** name, int nname)
83 {
84 	return devwalk(c, nc, name, nname, rtcdir, nelem(rtcdir), devgen);
85 }
86 
87 static int
rtcstat(Chan * c,uchar * dp,int n)88 rtcstat(Chan* c, uchar* dp, int n)
89 {
90 	return devstat(c, dp, n, rtcdir, nelem(rtcdir), devgen);
91 }
92 
93 static Chan*
rtcopen(Chan * c,int omode)94 rtcopen(Chan* c, int omode)
95 {
96 	return devopen(c, omode, rtcdir, nelem(rtcdir), devgen);
97 }
98 
99 static void
rtcclose(Chan *)100 rtcclose(Chan*)
101 {
102 }
103 
104 Dev fakertcdevtab = {
105 	'r',
106 	"rtc",
107 
108 	devreset,
109 	rtcinit,
110 	devshutdown,
111 	rtcattach,
112 	rtcwalk,
113 	rtcstat,
114 	rtcopen,
115 	devcreate,
116 	rtcclose,
117 	rtcread,
118 	devbread,
119 	rtcwrite,
120 	devbwrite,
121 	devremove,
122 	devwstat,
123 };
124 
125