xref: /plan9-contrib/sys/src/9/bcm/devrtc3231.c (revision 5c47fe09a0cc86dfb02c0ea4a2b6aec7eda2361f)
1*5c47fe09SDavid du Colombier /*
2*5c47fe09SDavid du Colombier  * Maxim DS3231 realtime clock (accessed via rtc)
3*5c47fe09SDavid du Colombier  */
4*5c47fe09SDavid du Colombier 
5*5c47fe09SDavid du Colombier #include	"u.h"
6*5c47fe09SDavid du Colombier #include	"../port/lib.h"
7*5c47fe09SDavid du Colombier #include	"mem.h"
8*5c47fe09SDavid du Colombier #include	"dat.h"
9*5c47fe09SDavid du Colombier #include	"fns.h"
10*5c47fe09SDavid du Colombier #include	"../port/error.h"
11*5c47fe09SDavid du Colombier 
12*5c47fe09SDavid du Colombier enum {
13*5c47fe09SDavid du Colombier 	/* DS3231 registers */
14*5c47fe09SDavid du Colombier 	Seconds=	0,
15*5c47fe09SDavid du Colombier 	Minutes=	1,
16*5c47fe09SDavid du Colombier 	Hours=		2,
17*5c47fe09SDavid du Colombier 	Weekday=	3,
18*5c47fe09SDavid du Colombier 	Mday=		4,
19*5c47fe09SDavid du Colombier 	Month=		5,
20*5c47fe09SDavid du Colombier 	Year=		6,
21*5c47fe09SDavid du Colombier 	Nbcd=		7,
22*5c47fe09SDavid du Colombier 
23*5c47fe09SDavid du Colombier 	/* Hours register may be in 12-hour or 24-hour mode */
24*5c47fe09SDavid du Colombier 	Twelvehr=	1<<6,
25*5c47fe09SDavid du Colombier 	Pm=		1<<5,
26*5c47fe09SDavid du Colombier 
27*5c47fe09SDavid du Colombier 	I2Caddr=	0x68,
28*5c47fe09SDavid du Colombier 
29*5c47fe09SDavid du Colombier };
30*5c47fe09SDavid du Colombier 
31*5c47fe09SDavid du Colombier typedef struct Rtc	Rtc;
32*5c47fe09SDavid du Colombier 
33*5c47fe09SDavid du Colombier struct Rtc
34*5c47fe09SDavid du Colombier {
35*5c47fe09SDavid du Colombier 	int	sec;
36*5c47fe09SDavid du Colombier 	int	min;
37*5c47fe09SDavid du Colombier 	int	hour;
38*5c47fe09SDavid du Colombier 	int	mday;
39*5c47fe09SDavid du Colombier 	int	mon;
40*5c47fe09SDavid du Colombier 	int	year;
41*5c47fe09SDavid du Colombier };
42*5c47fe09SDavid du Colombier 
43*5c47fe09SDavid du Colombier enum{
44*5c47fe09SDavid du Colombier 	Qdir = 0,
45*5c47fe09SDavid du Colombier 	Qrtc,
46*5c47fe09SDavid du Colombier };
47*5c47fe09SDavid du Colombier 
48*5c47fe09SDavid du Colombier Dirtab rtcdir[]={
49*5c47fe09SDavid du Colombier 	".",	{Qdir, 0, QTDIR},	0,	0555,
50*5c47fe09SDavid du Colombier 	"rtc",		{Qrtc, 0},	0,	0664,
51*5c47fe09SDavid du Colombier };
52*5c47fe09SDavid du Colombier 
53*5c47fe09SDavid du Colombier static ulong rtc2sec(Rtc*);
54*5c47fe09SDavid du Colombier static void sec2rtc(ulong, Rtc*);
55*5c47fe09SDavid du Colombier 
56*5c47fe09SDavid du Colombier static void
i2cread(uint addr,void * buf,int len)57*5c47fe09SDavid du Colombier i2cread(uint addr, void *buf, int len)
58*5c47fe09SDavid du Colombier {
59*5c47fe09SDavid du Colombier 	I2Cdev d;
60*5c47fe09SDavid du Colombier 
61*5c47fe09SDavid du Colombier 	d.addr = addr;
62*5c47fe09SDavid du Colombier 	d.tenbit = 0;
63*5c47fe09SDavid du Colombier 	d.salen = 0;
64*5c47fe09SDavid du Colombier 	i2crecv(&d, buf, len, 0);
65*5c47fe09SDavid du Colombier }
66*5c47fe09SDavid du Colombier 
67*5c47fe09SDavid du Colombier static void
i2cwrite(uint addr,void * buf,int len)68*5c47fe09SDavid du Colombier i2cwrite(uint addr, void *buf, int len)
69*5c47fe09SDavid du Colombier {
70*5c47fe09SDavid du Colombier 	I2Cdev d;
71*5c47fe09SDavid du Colombier 
72*5c47fe09SDavid du Colombier 	d.addr = addr;
73*5c47fe09SDavid du Colombier 	d.tenbit = 0;
74*5c47fe09SDavid du Colombier 	d.salen = 0;
75*5c47fe09SDavid du Colombier 	i2csend(&d, buf, len, 0);
76*5c47fe09SDavid du Colombier }
77*5c47fe09SDavid du Colombier 
78*5c47fe09SDavid du Colombier static void
rtcinit()79*5c47fe09SDavid du Colombier rtcinit()
80*5c47fe09SDavid du Colombier {
81*5c47fe09SDavid du Colombier 	i2csetup(0);
82*5c47fe09SDavid du Colombier }
83*5c47fe09SDavid du Colombier 
84*5c47fe09SDavid du Colombier static Chan*
rtcattach(char * spec)85*5c47fe09SDavid du Colombier rtcattach(char* spec)
86*5c47fe09SDavid du Colombier {
87*5c47fe09SDavid du Colombier 	return devattach('r', spec);
88*5c47fe09SDavid du Colombier }
89*5c47fe09SDavid du Colombier 
90*5c47fe09SDavid du Colombier static Walkqid*
rtcwalk(Chan * c,Chan * nc,char ** name,int nname)91*5c47fe09SDavid du Colombier rtcwalk(Chan* c, Chan *nc, char** name, int nname)
92*5c47fe09SDavid du Colombier {
93*5c47fe09SDavid du Colombier 	return devwalk(c, nc, name, nname, rtcdir, nelem(rtcdir), devgen);
94*5c47fe09SDavid du Colombier }
95*5c47fe09SDavid du Colombier 
96*5c47fe09SDavid du Colombier static int
rtcstat(Chan * c,uchar * dp,int n)97*5c47fe09SDavid du Colombier rtcstat(Chan* c, uchar* dp, int n)
98*5c47fe09SDavid du Colombier {
99*5c47fe09SDavid du Colombier 	return devstat(c, dp, n, rtcdir, nelem(rtcdir), devgen);
100*5c47fe09SDavid du Colombier }
101*5c47fe09SDavid du Colombier 
102*5c47fe09SDavid du Colombier static Chan*
rtcopen(Chan * c,int omode)103*5c47fe09SDavid du Colombier rtcopen(Chan* c, int omode)
104*5c47fe09SDavid du Colombier {
105*5c47fe09SDavid du Colombier 	char dummy;
106*5c47fe09SDavid du Colombier 
107*5c47fe09SDavid du Colombier 	omode = openmode(omode);
108*5c47fe09SDavid du Colombier 	switch((ulong)c->qid.path){
109*5c47fe09SDavid du Colombier 	case Qrtc:
110*5c47fe09SDavid du Colombier 		if(strcmp(up->user, eve)!=0 && omode!=OREAD)
111*5c47fe09SDavid du Colombier 			error(Eperm);
112*5c47fe09SDavid du Colombier 		/* if it's not there, this will throw an error */
113*5c47fe09SDavid du Colombier 		i2cread(I2Caddr, &dummy, 1);
114*5c47fe09SDavid du Colombier 		break;
115*5c47fe09SDavid du Colombier 	}
116*5c47fe09SDavid du Colombier 	return devopen(c, omode, rtcdir, nelem(rtcdir), devgen);
117*5c47fe09SDavid du Colombier }
118*5c47fe09SDavid du Colombier 
119*5c47fe09SDavid du Colombier static void
rtcclose(Chan *)120*5c47fe09SDavid du Colombier rtcclose(Chan*)
121*5c47fe09SDavid du Colombier {
122*5c47fe09SDavid du Colombier }
123*5c47fe09SDavid du Colombier 
124*5c47fe09SDavid du Colombier static int
bcd(int n)125*5c47fe09SDavid du Colombier bcd(int n)
126*5c47fe09SDavid du Colombier {
127*5c47fe09SDavid du Colombier 	return (n & 0xF) + (10 * (n >> 4));
128*5c47fe09SDavid du Colombier }
129*5c47fe09SDavid du Colombier 
130*5c47fe09SDavid du Colombier long
rtctime(void)131*5c47fe09SDavid du Colombier rtctime(void)
132*5c47fe09SDavid du Colombier {
133*5c47fe09SDavid du Colombier 	uchar clk[Nbcd];
134*5c47fe09SDavid du Colombier 	Rtc rtc;
135*5c47fe09SDavid du Colombier 
136*5c47fe09SDavid du Colombier 	clk[0] = 0;
137*5c47fe09SDavid du Colombier 	i2cwrite(I2Caddr, clk, 1);
138*5c47fe09SDavid du Colombier 	i2cread(I2Caddr, clk, Nbcd);
139*5c47fe09SDavid du Colombier 
140*5c47fe09SDavid du Colombier 	/*
141*5c47fe09SDavid du Colombier 	 *  convert from BCD
142*5c47fe09SDavid du Colombier 	 */
143*5c47fe09SDavid du Colombier 	rtc.sec = bcd(clk[Seconds]);
144*5c47fe09SDavid du Colombier 	rtc.min = bcd(clk[Minutes]);
145*5c47fe09SDavid du Colombier 	rtc.hour = bcd(clk[Hours]);
146*5c47fe09SDavid du Colombier 	if(clk[Hours] & Twelvehr){
147*5c47fe09SDavid du Colombier 		rtc.hour = bcd(clk[Hours] & 0x1F);
148*5c47fe09SDavid du Colombier 		if(clk[Hours] & Pm)
149*5c47fe09SDavid du Colombier 			rtc.hour += 12;
150*5c47fe09SDavid du Colombier 	}
151*5c47fe09SDavid du Colombier 	rtc.mday = bcd(clk[Mday]);
152*5c47fe09SDavid du Colombier 	rtc.mon = bcd(clk[Month] & 0x1F);
153*5c47fe09SDavid du Colombier 	rtc.year = bcd(clk[Year]);
154*5c47fe09SDavid du Colombier 
155*5c47fe09SDavid du Colombier 	/*
156*5c47fe09SDavid du Colombier 	 *  the world starts jan 1 1970
157*5c47fe09SDavid du Colombier 	 */
158*5c47fe09SDavid du Colombier 	if(rtc.year < 70)
159*5c47fe09SDavid du Colombier 		rtc.year += 2000;
160*5c47fe09SDavid du Colombier 	else
161*5c47fe09SDavid du Colombier 		rtc.year += 1900;
162*5c47fe09SDavid du Colombier 	return rtc2sec(&rtc);
163*5c47fe09SDavid du Colombier }
164*5c47fe09SDavid du Colombier 
165*5c47fe09SDavid du Colombier 
166*5c47fe09SDavid du Colombier static long
rtcread(Chan * c,void * buf,long n,vlong off)167*5c47fe09SDavid du Colombier rtcread(Chan* c, void* buf, long n, vlong off)
168*5c47fe09SDavid du Colombier {
169*5c47fe09SDavid du Colombier 	ulong t;
170*5c47fe09SDavid du Colombier 	ulong offset = off;
171*5c47fe09SDavid du Colombier 
172*5c47fe09SDavid du Colombier 	if(c->qid.type & QTDIR)
173*5c47fe09SDavid du Colombier 		return devdirread(c, buf, n, rtcdir, nelem(rtcdir), devgen);
174*5c47fe09SDavid du Colombier 
175*5c47fe09SDavid du Colombier 	switch((ulong)c->qid.path){
176*5c47fe09SDavid du Colombier 	case Qrtc:
177*5c47fe09SDavid du Colombier 		t = rtctime();
178*5c47fe09SDavid du Colombier 		n = readnum(offset, buf, n, t, 12);
179*5c47fe09SDavid du Colombier 		return n;
180*5c47fe09SDavid du Colombier 	}
181*5c47fe09SDavid du Colombier 	error(Ebadarg);
182*5c47fe09SDavid du Colombier 	return 0;
183*5c47fe09SDavid du Colombier }
184*5c47fe09SDavid du Colombier 
185*5c47fe09SDavid du Colombier #define PUTBCD(n,o) bcdclock[1+o] = (n % 10) | (((n / 10) % 10)<<4)
186*5c47fe09SDavid du Colombier 
187*5c47fe09SDavid du Colombier static long
rtcwrite(Chan * c,void * buf,long n,vlong off)188*5c47fe09SDavid du Colombier rtcwrite(Chan* c, void* buf, long n, vlong off)
189*5c47fe09SDavid du Colombier {
190*5c47fe09SDavid du Colombier 	Rtc rtc;
191*5c47fe09SDavid du Colombier 	ulong secs;
192*5c47fe09SDavid du Colombier 	uchar bcdclock[1+Nbcd];
193*5c47fe09SDavid du Colombier 	char *cp, *ep;
194*5c47fe09SDavid du Colombier 	ulong offset = off;
195*5c47fe09SDavid du Colombier 
196*5c47fe09SDavid du Colombier 	if(offset!=0)
197*5c47fe09SDavid du Colombier 		error(Ebadarg);
198*5c47fe09SDavid du Colombier 
199*5c47fe09SDavid du Colombier 
200*5c47fe09SDavid du Colombier 	switch((ulong)c->qid.path){
201*5c47fe09SDavid du Colombier 	case Qrtc:
202*5c47fe09SDavid du Colombier 		/*
203*5c47fe09SDavid du Colombier 		 *  read the time
204*5c47fe09SDavid du Colombier 		 */
205*5c47fe09SDavid du Colombier 		cp = ep = buf;
206*5c47fe09SDavid du Colombier 		ep += n;
207*5c47fe09SDavid du Colombier 		while(cp < ep){
208*5c47fe09SDavid du Colombier 			if(*cp>='0' && *cp<='9')
209*5c47fe09SDavid du Colombier 				break;
210*5c47fe09SDavid du Colombier 			cp++;
211*5c47fe09SDavid du Colombier 		}
212*5c47fe09SDavid du Colombier 		secs = strtoul(cp, 0, 0);
213*5c47fe09SDavid du Colombier 
214*5c47fe09SDavid du Colombier 		/*
215*5c47fe09SDavid du Colombier 		 *  convert to bcd
216*5c47fe09SDavid du Colombier 		 */
217*5c47fe09SDavid du Colombier 		sec2rtc(secs, &rtc);
218*5c47fe09SDavid du Colombier 		PUTBCD(rtc.sec, Seconds);
219*5c47fe09SDavid du Colombier 		PUTBCD(rtc.min, Minutes);	/* forces 24 hour mode */
220*5c47fe09SDavid du Colombier 		PUTBCD(rtc.hour, Hours);
221*5c47fe09SDavid du Colombier 		PUTBCD(0, Weekday);		/* hope no other OS uses this */
222*5c47fe09SDavid du Colombier 		PUTBCD(rtc.mday, Mday);
223*5c47fe09SDavid du Colombier 		PUTBCD(rtc.mon, Month);
224*5c47fe09SDavid du Colombier 		PUTBCD(rtc.year, Year);
225*5c47fe09SDavid du Colombier 
226*5c47fe09SDavid du Colombier 		/*
227*5c47fe09SDavid du Colombier 		 *  write the clock
228*5c47fe09SDavid du Colombier 		 */
229*5c47fe09SDavid du Colombier 		bcdclock[0] = 0;
230*5c47fe09SDavid du Colombier 		i2cwrite(I2Caddr, bcdclock, 1+Nbcd);
231*5c47fe09SDavid du Colombier 		return n;
232*5c47fe09SDavid du Colombier 	}
233*5c47fe09SDavid du Colombier 	error(Ebadarg);
234*5c47fe09SDavid du Colombier 	return 0;
235*5c47fe09SDavid du Colombier }
236*5c47fe09SDavid du Colombier 
237*5c47fe09SDavid du Colombier Dev rtc3231devtab = {
238*5c47fe09SDavid du Colombier 	'r',
239*5c47fe09SDavid du Colombier 	"rtc",
240*5c47fe09SDavid du Colombier 
241*5c47fe09SDavid du Colombier 	devreset,
242*5c47fe09SDavid du Colombier 	rtcinit,
243*5c47fe09SDavid du Colombier 	devshutdown,
244*5c47fe09SDavid du Colombier 	rtcattach,
245*5c47fe09SDavid du Colombier 	rtcwalk,
246*5c47fe09SDavid du Colombier 	rtcstat,
247*5c47fe09SDavid du Colombier 	rtcopen,
248*5c47fe09SDavid du Colombier 	devcreate,
249*5c47fe09SDavid du Colombier 	rtcclose,
250*5c47fe09SDavid du Colombier 	rtcread,
251*5c47fe09SDavid du Colombier 	devbread,
252*5c47fe09SDavid du Colombier 	rtcwrite,
253*5c47fe09SDavid du Colombier 	devbwrite,
254*5c47fe09SDavid du Colombier 	devremove,
255*5c47fe09SDavid du Colombier 	devwstat,
256*5c47fe09SDavid du Colombier };
257*5c47fe09SDavid du Colombier 
258*5c47fe09SDavid du Colombier #define SEC2MIN 60L
259*5c47fe09SDavid du Colombier #define SEC2HOUR (60L*SEC2MIN)
260*5c47fe09SDavid du Colombier #define SEC2DAY (24L*SEC2HOUR)
261*5c47fe09SDavid du Colombier 
262*5c47fe09SDavid du Colombier /*
263*5c47fe09SDavid du Colombier  *  days per month plus days/year
264*5c47fe09SDavid du Colombier  */
265*5c47fe09SDavid du Colombier static	int	dmsize[] =
266*5c47fe09SDavid du Colombier {
267*5c47fe09SDavid du Colombier 	365, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
268*5c47fe09SDavid du Colombier };
269*5c47fe09SDavid du Colombier static	int	ldmsize[] =
270*5c47fe09SDavid du Colombier {
271*5c47fe09SDavid du Colombier 	366, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
272*5c47fe09SDavid du Colombier };
273*5c47fe09SDavid du Colombier 
274*5c47fe09SDavid du Colombier /*
275*5c47fe09SDavid du Colombier  *  return the days/month for the given year
276*5c47fe09SDavid du Colombier  */
277*5c47fe09SDavid du Colombier static int*
yrsize(int y)278*5c47fe09SDavid du Colombier yrsize(int y)
279*5c47fe09SDavid du Colombier {
280*5c47fe09SDavid du Colombier 	if((y%4) == 0 && ((y%100) != 0 || (y%400) == 0))
281*5c47fe09SDavid du Colombier 		return ldmsize;
282*5c47fe09SDavid du Colombier 	else
283*5c47fe09SDavid du Colombier 		return dmsize;
284*5c47fe09SDavid du Colombier }
285*5c47fe09SDavid du Colombier 
286*5c47fe09SDavid du Colombier /*
287*5c47fe09SDavid du Colombier  *  compute seconds since Jan 1 1970
288*5c47fe09SDavid du Colombier  */
289*5c47fe09SDavid du Colombier static ulong
rtc2sec(Rtc * rtc)290*5c47fe09SDavid du Colombier rtc2sec(Rtc *rtc)
291*5c47fe09SDavid du Colombier {
292*5c47fe09SDavid du Colombier 	ulong secs;
293*5c47fe09SDavid du Colombier 	int i;
294*5c47fe09SDavid du Colombier 	int *d2m;
295*5c47fe09SDavid du Colombier 
296*5c47fe09SDavid du Colombier 	secs = 0;
297*5c47fe09SDavid du Colombier 
298*5c47fe09SDavid du Colombier 	/*
299*5c47fe09SDavid du Colombier 	 *  seconds per year
300*5c47fe09SDavid du Colombier 	 */
301*5c47fe09SDavid du Colombier 	for(i = 1970; i < rtc->year; i++){
302*5c47fe09SDavid du Colombier 		d2m = yrsize(i);
303*5c47fe09SDavid du Colombier 		secs += d2m[0] * SEC2DAY;
304*5c47fe09SDavid du Colombier 	}
305*5c47fe09SDavid du Colombier 
306*5c47fe09SDavid du Colombier 	/*
307*5c47fe09SDavid du Colombier 	 *  seconds per month
308*5c47fe09SDavid du Colombier 	 */
309*5c47fe09SDavid du Colombier 	d2m = yrsize(rtc->year);
310*5c47fe09SDavid du Colombier 	for(i = 1; i < rtc->mon; i++)
311*5c47fe09SDavid du Colombier 		secs += d2m[i] * SEC2DAY;
312*5c47fe09SDavid du Colombier 
313*5c47fe09SDavid du Colombier 	secs += (rtc->mday-1) * SEC2DAY;
314*5c47fe09SDavid du Colombier 	secs += rtc->hour * SEC2HOUR;
315*5c47fe09SDavid du Colombier 	secs += rtc->min * SEC2MIN;
316*5c47fe09SDavid du Colombier 	secs += rtc->sec;
317*5c47fe09SDavid du Colombier 
318*5c47fe09SDavid du Colombier 	return secs;
319*5c47fe09SDavid du Colombier }
320*5c47fe09SDavid du Colombier 
321*5c47fe09SDavid du Colombier /*
322*5c47fe09SDavid du Colombier  *  compute rtc from seconds since Jan 1 1970
323*5c47fe09SDavid du Colombier  */
324*5c47fe09SDavid du Colombier static void
sec2rtc(ulong secs,Rtc * rtc)325*5c47fe09SDavid du Colombier sec2rtc(ulong secs, Rtc *rtc)
326*5c47fe09SDavid du Colombier {
327*5c47fe09SDavid du Colombier 	int d;
328*5c47fe09SDavid du Colombier 	long hms, day;
329*5c47fe09SDavid du Colombier 	int *d2m;
330*5c47fe09SDavid du Colombier 
331*5c47fe09SDavid du Colombier 	/*
332*5c47fe09SDavid du Colombier 	 * break initial number into days
333*5c47fe09SDavid du Colombier 	 */
334*5c47fe09SDavid du Colombier 	hms = secs % SEC2DAY;
335*5c47fe09SDavid du Colombier 	day = secs / SEC2DAY;
336*5c47fe09SDavid du Colombier 	if(hms < 0) {
337*5c47fe09SDavid du Colombier 		hms += SEC2DAY;
338*5c47fe09SDavid du Colombier 		day -= 1;
339*5c47fe09SDavid du Colombier 	}
340*5c47fe09SDavid du Colombier 
341*5c47fe09SDavid du Colombier 	/*
342*5c47fe09SDavid du Colombier 	 * generate hours:minutes:seconds
343*5c47fe09SDavid du Colombier 	 */
344*5c47fe09SDavid du Colombier 	rtc->sec = hms % 60;
345*5c47fe09SDavid du Colombier 	d = hms / 60;
346*5c47fe09SDavid du Colombier 	rtc->min = d % 60;
347*5c47fe09SDavid du Colombier 	d /= 60;
348*5c47fe09SDavid du Colombier 	rtc->hour = d;
349*5c47fe09SDavid du Colombier 
350*5c47fe09SDavid du Colombier 	/*
351*5c47fe09SDavid du Colombier 	 * year number
352*5c47fe09SDavid du Colombier 	 */
353*5c47fe09SDavid du Colombier 	if(day >= 0)
354*5c47fe09SDavid du Colombier 		for(d = 1970; day >= *yrsize(d); d++)
355*5c47fe09SDavid du Colombier 			day -= *yrsize(d);
356*5c47fe09SDavid du Colombier 	else
357*5c47fe09SDavid du Colombier 		for (d = 1970; day < 0; d--)
358*5c47fe09SDavid du Colombier 			day += *yrsize(d-1);
359*5c47fe09SDavid du Colombier 	rtc->year = d;
360*5c47fe09SDavid du Colombier 
361*5c47fe09SDavid du Colombier 	/*
362*5c47fe09SDavid du Colombier 	 * generate month
363*5c47fe09SDavid du Colombier 	 */
364*5c47fe09SDavid du Colombier 	d2m = yrsize(rtc->year);
365*5c47fe09SDavid du Colombier 	for(d = 1; day >= d2m[d]; d++)
366*5c47fe09SDavid du Colombier 		day -= d2m[d];
367*5c47fe09SDavid du Colombier 	rtc->mday = day + 1;
368*5c47fe09SDavid du Colombier 	rtc->mon = d;
369*5c47fe09SDavid du Colombier 
370*5c47fe09SDavid du Colombier 	return;
371*5c47fe09SDavid du Colombier }
372