ds3231.c revision 279399
1/*-
2 * Copyright (c) 2014-2015 Luiz Otavio O Souza <loos@FreeBSD.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
28__FBSDID("$FreeBSD: head/sys/dev/iicbus/ds3231.c 279399 2015-02-28 19:02:44Z loos $");
29
30/*
31 * Driver for Maxim DS3231[N] real-time clock/calendar.
32 */
33
34#include "opt_platform.h"
35
36#include <sys/param.h>
37#include <sys/systm.h>
38#include <sys/bus.h>
39#include <sys/clock.h>
40#include <sys/kernel.h>
41#include <sys/module.h>
42#include <sys/sysctl.h>
43
44#include <dev/iicbus/iicbus.h>
45#include <dev/iicbus/iiconf.h>
46#ifdef FDT
47#include <dev/ofw/openfirm.h>
48#include <dev/ofw/ofw_bus.h>
49#include <dev/ofw/ofw_bus_subr.h>
50#endif
51
52#include <dev/iicbus/ds3231reg.h>
53
54#include "clock_if.h"
55#include "iicbus_if.h"
56
57struct ds3231_softc {
58	device_t	sc_dev;
59	int		sc_last_c;
60	int		sc_year0;
61	struct intr_config_hook	enum_hook;
62	uint16_t	sc_addr;	/* DS3231 slave address. */
63	uint8_t		sc_ctrl;
64	uint8_t		sc_status;
65};
66
67static int ds3231_sqw_freq[] = { 1, 1024, 4096, 8192 };
68
69static void ds3231_start(void *);
70
71static int
72ds3231_read(device_t dev, uint16_t addr, uint8_t reg, uint8_t *data, size_t len)
73{
74	struct iic_msg msg[2] = {
75	    { addr, IIC_M_WR | IIC_M_NOSTOP, 1, &reg },
76	    { addr, IIC_M_RD, len, data },
77	};
78
79	return (iicbus_transfer(dev, msg, nitems(msg)));
80}
81
82static int
83ds3231_write(device_t dev, uint16_t addr, uint8_t *data, size_t len)
84{
85	struct iic_msg msg[1] = {
86	    { addr, IIC_M_WR, len, data },
87	};
88
89	return (iicbus_transfer(dev, msg, nitems(msg)));
90}
91
92static int
93ds3231_ctrl_read(struct ds3231_softc *sc)
94{
95	int error;
96
97	sc->sc_ctrl = 0;
98	error = ds3231_read(sc->sc_dev, sc->sc_addr, DS3231_CONTROL,
99	    &sc->sc_ctrl, sizeof(sc->sc_ctrl));
100	if (error) {
101		device_printf(sc->sc_dev, "cannot read from RTC.\n");
102		return (error);
103	}
104
105	return (0);
106}
107
108static int
109ds3231_ctrl_write(struct ds3231_softc *sc)
110{
111	int error;
112	uint8_t data[2];
113
114	data[0] = DS3231_CONTROL;
115	/* Always enable the oscillator.  Always disable both alarms. */
116	data[1] = sc->sc_ctrl & ~DS3231_CTRL_MASK;
117	error = ds3231_write(sc->sc_dev, sc->sc_addr, data, sizeof(data));
118	if (error != 0)
119		device_printf(sc->sc_dev, "cannot write to RTC.\n");
120
121	return (error);
122}
123
124static int
125ds3231_status_read(struct ds3231_softc *sc)
126{
127	int error;
128
129	sc->sc_status = 0;
130	error = ds3231_read(sc->sc_dev, sc->sc_addr, DS3231_STATUS,
131	    &sc->sc_status, sizeof(sc->sc_status));
132	if (error) {
133		device_printf(sc->sc_dev, "cannot read from RTC.\n");
134		return (error);
135	}
136
137	return (0);
138}
139
140static int
141ds3231_status_write(struct ds3231_softc *sc, int clear_a1, int clear_a2)
142{
143	int error;
144	uint8_t data[2];
145
146	data[0] = DS3231_STATUS;
147	data[1] = sc->sc_status;
148	if (clear_a1 == 0)
149		data[1] |= DS3231_STATUS_A1F;
150	if (clear_a2 == 0)
151		data[1] |= DS3231_STATUS_A2F;
152	error = ds3231_write(sc->sc_dev, sc->sc_addr, data, sizeof(data));
153	if (error != 0)
154		device_printf(sc->sc_dev, "cannot write to RTC.\n");
155
156	return (error);
157}
158
159static int
160ds3231_set_24hrs_mode(struct ds3231_softc *sc)
161{
162	int error;
163	uint8_t data[2], hour;
164
165	hour = 0;
166	error = ds3231_read(sc->sc_dev, sc->sc_addr, DS3231_HOUR,
167	    &hour, sizeof(hour));
168	if (error) {
169		device_printf(sc->sc_dev, "cannot read from RTC.\n");
170		return (error);
171	}
172	data[0] = DS3231_HOUR;
173	data[1] = hour & ~DS3231_C_MASK;
174	error = ds3231_write(sc->sc_dev, sc->sc_addr, data, sizeof(data));
175	if (error != 0)
176		device_printf(sc->sc_dev, "cannot write to RTC.\n");
177
178	return (error);
179}
180
181static int
182ds3231_temp_read(struct ds3231_softc *sc, int *temp)
183{
184	int error, neg, t;
185	uint8_t buf8[2];
186	uint16_t buf;
187
188	error = ds3231_read(sc->sc_dev, sc->sc_addr, DS3231_TEMP,
189	    buf8, sizeof(buf8));
190	if (error != 0)
191		return (error);
192	buf = (buf8[0] << 8) | (buf8[1] & 0xff);
193	neg = 0;
194	if (buf & DS3231_NEG_BIT) {
195		buf = ~(buf & DS3231_TEMP_MASK) + 1;
196		neg = 1;
197	}
198	*temp = ((int16_t)buf >> 8) * 10;
199	t = 0;
200	if (buf & DS3231_0250C)
201		t += 250;
202	if (buf & DS3231_0500C)
203		t += 500;
204	t /= 100;
205	*temp += t;
206	if (neg)
207		*temp = -(*temp);
208	*temp += TZ_ZEROC;
209
210	return (0);
211}
212
213static int
214ds3231_temp_sysctl(SYSCTL_HANDLER_ARGS)
215{
216	int error, temp;
217	struct ds3231_softc *sc;
218
219	sc = (struct ds3231_softc *)arg1;
220	if (ds3231_temp_read(sc, &temp) != 0)
221		return (EIO);
222	error = sysctl_handle_int(oidp, &temp, 0, req);
223
224	return (error);
225}
226
227static int
228ds3231_conv_sysctl(SYSCTL_HANDLER_ARGS)
229{
230	int error, conv, newc;
231	struct ds3231_softc *sc;
232
233	sc = (struct ds3231_softc *)arg1;
234	error = ds3231_ctrl_read(sc);
235	if (error != 0)
236		return (error);
237	newc = conv = (sc->sc_ctrl & DS3231_CTRL_CONV) ? 1 : 0;
238	error = sysctl_handle_int(oidp, &newc, 0, req);
239	if (error != 0 || req->newptr == NULL)
240		return (error);
241	if (conv == 0 && newc != 0) {
242		error = ds3231_status_read(sc);
243		if (error != 0)
244			return (error);
245		if (sc->sc_status & DS3231_STATUS_BUSY)
246			return (0);
247		sc->sc_ctrl |= DS3231_CTRL_CONV;
248		error = ds3231_ctrl_write(sc);
249		if (error != 0)
250			return (error);
251	}
252
253	return (error);
254}
255
256static int
257ds3231_bbsqw_sysctl(SYSCTL_HANDLER_ARGS)
258{
259	int bbsqw, error, newb;
260	struct ds3231_softc *sc;
261
262	sc = (struct ds3231_softc *)arg1;
263	error = ds3231_ctrl_read(sc);
264	if (error != 0)
265		return (error);
266	bbsqw = newb = (sc->sc_ctrl & DS3231_CTRL_BBSQW) ? 1 : 0;
267	error = sysctl_handle_int(oidp, &newb, 0, req);
268	if (error != 0 || req->newptr == NULL)
269		return (error);
270	if (bbsqw != newb) {
271		sc->sc_ctrl &= ~DS3231_CTRL_BBSQW;
272		if (newb)
273			sc->sc_ctrl |= DS3231_CTRL_BBSQW;
274		error = ds3231_ctrl_write(sc);
275		if (error != 0)
276			return (error);
277	}
278
279	return (error);
280}
281
282static int
283ds3231_sqw_freq_sysctl(SYSCTL_HANDLER_ARGS)
284{
285	int error, freq, i, newf, tmp;
286	struct ds3231_softc *sc;
287
288	sc = (struct ds3231_softc *)arg1;
289	error = ds3231_ctrl_read(sc);
290	if (error != 0)
291		return (error);
292	tmp = (sc->sc_ctrl & DS3231_CTRL_RS_MASK) >> DS3231_CTRL_RS_SHIFT;
293	if (tmp > nitems(ds3231_sqw_freq))
294		tmp = nitems(ds3231_sqw_freq);
295	freq = ds3231_sqw_freq[tmp];
296	error = sysctl_handle_int(oidp, &freq, 0, req);
297	if (error != 0 || req->newptr == NULL)
298		return (error);
299	if (freq != ds3231_sqw_freq[tmp]) {
300		newf = 0;
301		for (i = 0; i < nitems(ds3231_sqw_freq); i++)
302			if (freq >= ds3231_sqw_freq[i])
303				newf = i;
304		sc->sc_ctrl &= ~DS3231_CTRL_RS_MASK;
305		sc->sc_ctrl |= newf << DS3231_CTRL_RS_SHIFT;
306		error = ds3231_ctrl_write(sc);
307		if (error != 0)
308			return (error);
309	}
310
311	return (error);
312}
313
314static int
315ds3231_str_sqw_mode(char *buf)
316{
317	int len, rtrn;
318
319	rtrn = -1;
320	len = strlen(buf);
321	if ((len > 2 && strncasecmp("interrupt", buf, len) == 0) ||
322	    (len > 2 && strncasecmp("int", buf, len) == 0)) {
323		rtrn = 1;
324	} else if ((len > 2 && strncasecmp("square-wave", buf, len) == 0) ||
325	    (len > 2 && strncasecmp("sqw", buf, len) == 0)) {
326		rtrn = 0;
327	}
328
329	return (rtrn);
330}
331
332static int
333ds3231_sqw_mode_sysctl(SYSCTL_HANDLER_ARGS)
334{
335	char buf[16];
336	int error, mode, newm;
337	struct ds3231_softc *sc;
338
339	sc = (struct ds3231_softc *)arg1;
340	error = ds3231_ctrl_read(sc);
341	if (error != 0)
342		return (error);
343	if (sc->sc_ctrl & DS3231_CTRL_INTCN) {
344		mode = 1;
345		strlcpy(buf, "interrupt", sizeof(buf));
346	} else {
347		mode = 0;
348		strlcpy(buf, "square-wave", sizeof(buf));
349	}
350	error = sysctl_handle_string(oidp, buf, sizeof(buf), req);
351	if (error != 0 || req->newptr == NULL)
352		return (error);
353	newm = ds3231_str_sqw_mode(buf);
354	if (newm != -1 && mode != newm) {
355		sc->sc_ctrl &= ~DS3231_CTRL_INTCN;
356		if (newm == 1)
357			sc->sc_ctrl |= DS3231_CTRL_INTCN;
358		error = ds3231_ctrl_write(sc);
359		if (error != 0)
360			return (error);
361	}
362
363	return (error);
364}
365
366static int
367ds3231_en32khz_sysctl(SYSCTL_HANDLER_ARGS)
368{
369	int error, en32khz, tmp;
370	struct ds3231_softc *sc;
371
372	sc = (struct ds3231_softc *)arg1;
373	error = ds3231_status_read(sc);
374	if (error != 0)
375		return (error);
376	tmp = en32khz = (sc->sc_status & DS3231_STATUS_EN32KHZ) ? 1 : 0;
377	error = sysctl_handle_int(oidp, &en32khz, 0, req);
378	if (error != 0 || req->newptr == NULL)
379		return (error);
380	if (en32khz != tmp) {
381		sc->sc_status &= ~DS3231_STATUS_EN32KHZ;
382		if (en32khz)
383			sc->sc_status |= DS3231_STATUS_EN32KHZ;
384		error = ds3231_status_write(sc, 0, 0);
385		if (error != 0)
386			return (error);
387	}
388
389	return (error);
390}
391
392static int
393ds3231_probe(device_t dev)
394{
395
396#ifdef FDT
397	if (!ofw_bus_status_okay(dev))
398		return (ENXIO);
399	if (!ofw_bus_is_compatible(dev, "maxim,ds3231"))
400		return (ENXIO);
401#endif
402	device_set_desc(dev, "Maxim DS3231 RTC");
403
404	return (BUS_PROBE_DEFAULT);
405}
406
407static int
408ds3231_attach(device_t dev)
409{
410	struct ds3231_softc *sc;
411
412	sc = device_get_softc(dev);
413	sc->sc_dev = dev;
414	sc->sc_addr = iicbus_get_addr(dev);
415	sc->sc_last_c = -1;
416	sc->sc_year0 = 1900;
417	sc->enum_hook.ich_func = ds3231_start;
418	sc->enum_hook.ich_arg = dev;
419
420	/*
421	 * We have to wait until interrupts are enabled.  Usually I2C read
422	 * and write only works when the interrupts are available.
423	 */
424	if (config_intrhook_establish(&sc->enum_hook) != 0)
425		return (ENOMEM);
426
427	return (0);
428}
429
430static void
431ds3231_start(void *xdev)
432{
433	device_t dev;
434	struct ds3231_softc *sc;
435	struct sysctl_ctx_list *ctx;
436	struct sysctl_oid *tree_node;
437	struct sysctl_oid_list *tree;
438
439	dev = (device_t)xdev;
440	sc = device_get_softc(dev);
441	ctx = device_get_sysctl_ctx(dev);
442	tree_node = device_get_sysctl_tree(dev);
443	tree = SYSCTL_CHILDREN(tree_node);
444
445	config_intrhook_disestablish(&sc->enum_hook);
446	if (ds3231_ctrl_read(sc) != 0)
447		return;
448	if (ds3231_status_read(sc) != 0)
449		return;
450	/* Clear the OSF bit and ack any pending alarm interrupt. */
451	if (sc->sc_status & DS3231_STATUS_OSF) {
452		device_printf(sc->sc_dev,
453		    "oscillator has stopped, check the battery.\n");
454		sc->sc_status &= ~DS3231_STATUS_OSF;
455	}
456	if (ds3231_status_write(sc, 1, 1) != 0)
457		return;
458	/* Always enable the oscillator. */
459	if (ds3231_ctrl_write(sc) != 0)
460		return;
461	/* Set the 24 hours mode. */
462	if (ds3231_set_24hrs_mode(sc) != 0)
463		return;
464
465	/* Temperature. */
466	SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "temperature",
467	    CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, sc, 0,
468	    ds3231_temp_sysctl, "IK", "Current temperature");
469	/* Configuration parameters. */
470	SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "temp_conv",
471	    CTLFLAG_RW | CTLTYPE_UINT | CTLFLAG_MPSAFE, sc, 0,
472	    ds3231_conv_sysctl, "IU",
473	    "DS3231 start a new temperature converstion");
474	SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "bbsqw",
475	    CTLFLAG_RW | CTLTYPE_UINT | CTLFLAG_MPSAFE, sc, 0,
476	    ds3231_bbsqw_sysctl, "IU",
477	    "DS3231 battery-backed square-wave output enable");
478	SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "sqw_freq",
479	    CTLFLAG_RW | CTLTYPE_UINT | CTLFLAG_MPSAFE, sc, 0,
480	    ds3231_sqw_freq_sysctl, "IU",
481	    "DS3231 square-wave output frequency");
482	SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "sqw_mode",
483	    CTLFLAG_RW | CTLTYPE_STRING | CTLFLAG_MPSAFE, sc, 0,
484	    ds3231_sqw_mode_sysctl, "A", "DS3231 SQW output mode control");
485	SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "32khz_enable",
486	    CTLFLAG_RW | CTLTYPE_UINT | CTLFLAG_MPSAFE, sc, 0,
487	    ds3231_en32khz_sysctl, "IU", "DS3231 enable the 32kHz output");
488
489	/* 1 second resolution. */
490	clock_register(dev, 1000000);
491}
492
493static int
494ds3231_gettime(device_t dev, struct timespec *ts)
495{
496	int c, error;
497	struct clocktime ct;
498	struct ds3231_softc *sc;
499	uint8_t data[7];
500
501	sc = device_get_softc(dev);
502	memset(data, 0, sizeof(data));
503	error = ds3231_read(sc->sc_dev, sc->sc_addr, DS3231_SECS,
504	    data, sizeof(data));
505	if (error != 0) {
506		device_printf(dev, "cannot read from RTC.\n");
507		return (error);
508	}
509	ct.nsec = 0;
510	ct.sec = FROMBCD(data[DS3231_SECS] & DS3231_SECS_MASK);
511	ct.min = FROMBCD(data[DS3231_MINS] & DS3231_MINS_MASK);
512	ct.hour = FROMBCD(data[DS3231_HOUR] & DS3231_HOUR_MASK);
513	ct.day = FROMBCD(data[DS3231_DATE] & DS3231_DATE_MASK);
514	ct.dow = data[DS3231_WEEKDAY] & DS3231_WEEKDAY_MASK;
515	ct.mon = FROMBCD(data[DS3231_MONTH] & DS3231_MONTH_MASK);
516	ct.year = FROMBCD(data[DS3231_YEAR] & DS3231_YEAR_MASK);
517	c = (data[DS3231_MONTH] & DS3231_C_MASK) ? 1 : 0;
518	if (sc->sc_last_c == -1)
519		sc->sc_last_c = c;
520	else if (c != sc->sc_last_c) {
521		sc->sc_year0 += 100;
522		sc->sc_last_c = c;
523	}
524	ct.year += sc->sc_year0;
525	if (ct.year < POSIX_BASE_YEAR)
526		ct.year += 100;	/* assume [1970, 2069] */
527
528	return (clock_ct_to_ts(&ct, ts));
529}
530
531static int
532ds3231_settime(device_t dev, struct timespec *ts)
533{
534	int error;
535	struct clocktime ct;
536	struct ds3231_softc *sc;
537	uint8_t data[8];
538
539	sc = device_get_softc(dev);
540	/* Accuracy is only one second. */
541	if (ts->tv_nsec >= 500000000)
542		ts->tv_sec++;
543	ts->tv_nsec = 0;
544	clock_ts_to_ct(ts, &ct);
545	memset(data, 0, sizeof(data));
546	data[0] = DS3231_SECS;
547	data[DS3231_SECS + 1] = TOBCD(ct.sec);
548	data[DS3231_MINS + 1] = TOBCD(ct.min);
549	data[DS3231_HOUR + 1] = TOBCD(ct.hour);
550	data[DS3231_DATE + 1] = TOBCD(ct.day);
551	data[DS3231_WEEKDAY + 1] = ct.dow;
552	data[DS3231_MONTH + 1] = TOBCD(ct.mon);
553	data[DS3231_YEAR + 1] = TOBCD(ct.year % 100);
554	if (sc->sc_last_c)
555		data[DS3231_MONTH] |= DS3231_C_MASK;
556	/* Write the time back to RTC. */
557	error = ds3231_write(dev, sc->sc_addr, data, sizeof(data));
558	if (error != 0)
559		device_printf(dev, "cannot write to RTC.\n");
560
561	return (error);
562}
563
564static device_method_t ds3231_methods[] = {
565	DEVMETHOD(device_probe,		ds3231_probe),
566	DEVMETHOD(device_attach,	ds3231_attach),
567
568	DEVMETHOD(clock_gettime,	ds3231_gettime),
569	DEVMETHOD(clock_settime,	ds3231_settime),
570
571	DEVMETHOD_END
572};
573
574static driver_t ds3231_driver = {
575	"ds3231",
576	ds3231_methods,
577	sizeof(struct ds3231_softc),
578};
579
580static devclass_t ds3231_devclass;
581
582DRIVER_MODULE(ds3231, iicbus, ds3231_driver, ds3231_devclass, NULL, NULL);
583MODULE_VERSION(ds3231, 1);
584MODULE_DEPEND(ds3231, iicbus, 1, 1, 1);
585