xref: /freebsd/sys/dev/iicbus/rtc/ds1307.c (revision 02e9120893770924227138ba49df1edb3896112a)
1 /*-
2  * Copyright (c) 2015 Luiz Otavio O Souza <loos@FreeBSD.org>
3  * Copyright (c) 2022 Mathew McBride <matt@traverse.com.au>
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  */
27 
28 #include <sys/cdefs.h>
29 /*
30  * Driver for Maxim DS1307 I2C real-time clock/calendar.
31  */
32 
33 #include "opt_platform.h"
34 
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/bus.h>
38 #include <sys/clock.h>
39 #include <sys/kernel.h>
40 #include <sys/module.h>
41 #include <sys/sysctl.h>
42 
43 #include <dev/iicbus/iicbus.h>
44 #include <dev/iicbus/iiconf.h>
45 #ifdef FDT
46 #include <dev/ofw/openfirm.h>
47 #include <dev/ofw/ofw_bus.h>
48 #include <dev/ofw/ofw_bus_subr.h>
49 #endif
50 
51 #include <dev/iicbus/rtc/ds1307reg.h>
52 
53 #include "clock_if.h"
54 #include "iicbus_if.h"
55 
56 enum {
57 	TYPE_DS1307,
58 	TYPE_MAXIM1307,
59 	TYPE_MICROCHIP_MCP7491X,
60 	TYPE_EPSON_RX8035,
61 	TYPE_COUNT
62 };
63 
64 struct ds1307_softc {
65 	device_t			sc_dev;
66 	struct intr_config_hook		enum_hook;
67 	uint32_t			chiptype;
68 	uint8_t				sc_ctrl;
69 	bool				sc_use_ampm;
70 };
71 
72 static void ds1307_start(void *);
73 
74 #ifdef FDT
75 static const struct ofw_compat_data ds1307_compat_data[] = {
76 	{"dallas,ds1307",		TYPE_DS1307},
77 	{"maxim,ds1307",		TYPE_MAXIM1307},
78 	{"microchip,mcp7941x",		TYPE_MICROCHIP_MCP7491X},
79 	{"epson,rx8035",		TYPE_EPSON_RX8035},
80 	{ NULL, 0 }
81 };
82 #endif
83 
84 static int
85 ds1307_read1(device_t dev, uint8_t reg, uint8_t *data)
86 {
87 
88 	return (iicdev_readfrom(dev, reg, data, 1, IIC_INTRWAIT));
89 }
90 
91 static int
92 ds1307_write1(device_t dev, uint8_t reg, uint8_t data)
93 {
94 
95 	return (iicdev_writeto(dev, reg, &data, 1, IIC_INTRWAIT));
96 }
97 
98 static int
99 ds1307_ctrl_read(struct ds1307_softc *sc)
100 {
101 	int error;
102 
103 	sc->sc_ctrl = 0;
104 	error = ds1307_read1(sc->sc_dev, DS1307_CONTROL, &sc->sc_ctrl);
105 	if (error) {
106 		device_printf(sc->sc_dev, "%s: cannot read from RTC: %d\n",
107 		    __func__, error);
108 		return (error);
109 	}
110 
111 	return (0);
112 }
113 
114 static int
115 ds1307_ctrl_write(struct ds1307_softc *sc)
116 {
117 	int error;
118 	uint8_t ctrl;
119 
120 	ctrl = sc->sc_ctrl & DS1307_CTRL_MASK;
121 	error = ds1307_write1(sc->sc_dev, DS1307_CONTROL, ctrl);
122 	if (error != 0)
123 		device_printf(sc->sc_dev, "%s: cannot write to RTC: %d\n",
124 		    __func__, error);
125 
126 	return (error);
127 }
128 
129 static int
130 ds1307_sqwe_sysctl(SYSCTL_HANDLER_ARGS)
131 {
132 	int sqwe, error, newv, sqwe_bit;
133 	struct ds1307_softc *sc;
134 
135 	sc = (struct ds1307_softc *)arg1;
136 	error = ds1307_ctrl_read(sc);
137 	if (error != 0)
138 		return (error);
139 	if (sc->chiptype == TYPE_MICROCHIP_MCP7491X)
140 		sqwe_bit = MCP7941X_CTRL_SQWE;
141 	else
142 		sqwe_bit = DS1307_CTRL_SQWE;
143 	sqwe = newv = (sc->sc_ctrl & sqwe_bit) ? 1 : 0;
144 	error = sysctl_handle_int(oidp, &newv, 0, req);
145 	if (error != 0 || req->newptr == NULL)
146 		return (error);
147 	if (sqwe != newv) {
148 		sc->sc_ctrl &= ~sqwe_bit;
149 		if (newv)
150 			sc->sc_ctrl |= sqwe_bit;
151 		error = ds1307_ctrl_write(sc);
152 		if (error != 0)
153 			return (error);
154 	}
155 
156 	return (error);
157 }
158 
159 static int
160 ds1307_sqw_freq_sysctl(SYSCTL_HANDLER_ARGS)
161 {
162 	int ds1307_sqw_freq[] = { 1, 4096, 8192, 32768 };
163 	int error, freq, i, newf, tmp;
164 	struct ds1307_softc *sc;
165 
166 	sc = (struct ds1307_softc *)arg1;
167 	error = ds1307_ctrl_read(sc);
168 	if (error != 0)
169 		return (error);
170 	tmp = (sc->sc_ctrl & DS1307_CTRL_RS_MASK);
171 	if (tmp >= nitems(ds1307_sqw_freq))
172 		tmp = nitems(ds1307_sqw_freq) - 1;
173 	freq = ds1307_sqw_freq[tmp];
174 	error = sysctl_handle_int(oidp, &freq, 0, req);
175 	if (error != 0 || req->newptr == NULL)
176 		return (error);
177 	if (freq != ds1307_sqw_freq[tmp]) {
178 		newf = 0;
179 		for (i = 0; i < nitems(ds1307_sqw_freq); i++)
180 			if (freq >= ds1307_sqw_freq[i])
181 				newf = i;
182 		sc->sc_ctrl &= ~DS1307_CTRL_RS_MASK;
183 		sc->sc_ctrl |= newf;
184 		error = ds1307_ctrl_write(sc);
185 		if (error != 0)
186 			return (error);
187 	}
188 
189 	return (error);
190 }
191 
192 static int
193 ds1307_sqw_out_sysctl(SYSCTL_HANDLER_ARGS)
194 {
195 	int sqwe, error, newv;
196 	struct ds1307_softc *sc;
197 
198 	sc = (struct ds1307_softc *)arg1;
199 	error = ds1307_ctrl_read(sc);
200 	if (error != 0)
201 		return (error);
202 	sqwe = newv = (sc->sc_ctrl & DS1307_CTRL_OUT) ? 1 : 0;
203 	error = sysctl_handle_int(oidp, &newv, 0, req);
204 	if (error != 0 || req->newptr == NULL)
205 		return (error);
206 	if (sqwe != newv) {
207 		sc->sc_ctrl &= ~DS1307_CTRL_OUT;
208 		if (newv)
209 			sc->sc_ctrl |= DS1307_CTRL_OUT;
210 		error = ds1307_ctrl_write(sc);
211 		if (error != 0)
212 			return (error);
213 	}
214 
215 	return (error);
216 }
217 
218 static int
219 ds1307_probe(device_t dev)
220 {
221 #ifdef FDT
222 	const struct ofw_compat_data *compat;
223 
224 	if (!ofw_bus_status_okay(dev))
225 		return (ENXIO);
226 
227 	compat = ofw_bus_search_compatible(dev, ds1307_compat_data);
228 	if (compat->ocd_str == NULL)
229 		return (ENXIO);
230 
231 	switch(compat->ocd_data) {
232 		case TYPE_DS1307:
233 			device_set_desc(dev, "Dallas DS1307");
234 			break;
235 		case TYPE_MAXIM1307:
236 			device_set_desc(dev, "Maxim DS1307");
237 			break;
238 		case TYPE_MICROCHIP_MCP7491X:
239 			device_set_desc(dev, "Microchip MCP7491X");
240 			break;
241 		case TYPE_EPSON_RX8035:
242 			device_set_desc(dev, "Epson RX-8035");
243 			break;
244 		default:
245 			device_set_desc(dev, "Unknown DS1307-like device");
246 			break;
247 	}
248 	return (BUS_PROBE_DEFAULT);
249 #endif
250 
251 	device_set_desc(dev, "Maxim DS1307 RTC");
252 	return (BUS_PROBE_NOWILDCARD);
253 }
254 
255 static int
256 ds1307_attach(device_t dev)
257 {
258 #ifdef FDT
259 	const struct ofw_compat_data *compat;
260 #endif
261 	struct ds1307_softc *sc;
262 
263 	sc = device_get_softc(dev);
264 	sc->sc_dev = dev;
265 	sc->enum_hook.ich_func = ds1307_start;
266 	sc->enum_hook.ich_arg = dev;
267 #ifdef FDT
268 	compat = ofw_bus_search_compatible(dev, ds1307_compat_data);
269 	sc->chiptype = compat->ocd_data;
270 	/* Unify the chiptypes to DS1307 where possible. */
271 	if (sc->chiptype == TYPE_MAXIM1307)
272 		sc->chiptype = TYPE_DS1307;
273 #else
274 	sc->chiptype = TYPE_DS1307;
275 #endif
276 
277 	/*
278 	 * We have to wait until interrupts are enabled.  Usually I2C read
279 	 * and write only works when the interrupts are available.
280 	 */
281 	if (config_intrhook_establish(&sc->enum_hook) != 0)
282 		return (ENOMEM);
283 
284 	return (0);
285 }
286 
287 static int
288 ds1307_detach(device_t dev)
289 {
290 
291 	clock_unregister(dev);
292 	return (0);
293 }
294 
295 static bool
296 is_epson_time_valid(struct ds1307_softc *sc)
297 {
298 	device_t dev;
299 	int error;
300 	uint8_t ctrl2;
301 
302 	dev = sc->sc_dev;
303 
304 	/*
305 	 * The RX-8035 single register read is non-standard
306 	 * Refer to section 8.9.5 of the RX-8035 application manual:
307 	 * "I2C bus basic transfer format", under "Standard Read Method".
308 	 * Basically, register to read goes into the top 4 bits.
309 	 */
310 	error = ds1307_read1(dev, (RX8035_CTRL_2 << 4), &ctrl2);
311 	if (error) {
312 		device_printf(dev, "%s cannot read Control 2 register: %d\n",
313 		    __func__, error);
314 		return (false);
315 	}
316 
317 	if (ctrl2 & RX8035_CTRL_2_XSTP) {
318 		device_printf(dev, "Oscillation stop detected (ctrl2=%#02x)\n",
319 		    ctrl2);
320 		return (false);
321 	}
322 
323 	/*
324 	 * Power on reset (PON) generally implies oscillation stop,
325 	 * but catch it as well to be sure.
326 	 */
327 	if (ctrl2 & RX8035_CTRL_2_PON) {
328 		device_printf(dev, "Power-on reset detected (ctrl2=%#02x)\n",
329 		    ctrl2);
330 		return (false);
331 	}
332 
333 	return (true);
334 }
335 
336 static int
337 mark_epson_time_valid(struct ds1307_softc *sc)
338 {
339 	device_t dev;
340 	int error;
341 	uint8_t ctrl2;
342 	uint8_t control_mask;
343 
344 	dev = sc->sc_dev;
345 
346 	error = ds1307_read1(dev, (RX8035_CTRL_2 << 4), &ctrl2);
347 	if (error) {
348 		device_printf(dev, "%s cannot read Control 2 register: %d\n",
349 		    __func__, error);
350 		return (false);
351 	}
352 
353 	control_mask = (RX8035_CTRL_2_PON | RX8035_CTRL_2_XSTP | RX8035_CTRL_2_VDET);
354 	ctrl2 = ctrl2 & ~(control_mask);
355 
356 	error = ds1307_write1(dev, (RX8035_CTRL_2 << 4), ctrl2);
357 	if (error) {
358 		device_printf(dev, "%s cannot write to Control 2 register: %d\n",
359 		    __func__, error);
360 		return (false);
361 	}
362 	return (true);
363 }
364 
365 static bool is_dev_time_valid(struct ds1307_softc *sc)
366 {
367 	device_t dev;
368 	int error;
369 	uint8_t osc_en;
370 	uint8_t secs;
371 
372 	/* Epson RTCs have different control/status registers. */
373 	if (sc->chiptype == TYPE_EPSON_RX8035)
374 		return (is_epson_time_valid(sc));
375 
376 	dev = sc->sc_dev;
377 	/* Check if the oscillator is disabled. */
378 	error = ds1307_read1(dev, DS1307_SECS, &secs);
379 	if (error) {
380 		device_printf(dev, "%s: cannot read from RTC: %d\n",
381 		    __func__, error);
382 		return (false);
383 	}
384 
385 	switch (sc->chiptype) {
386 	case TYPE_MICROCHIP_MCP7491X:
387 		osc_en = 0x80;
388 		break;
389 	default:
390 		osc_en = 0x00;
391 		break;
392 	}
393 	if (((secs & DS1307_SECS_CH) ^ osc_en) != 0)
394 		return (false);
395 
396 	return (true);
397 }
398 
399 static void
400 ds1307_start(void *xdev)
401 {
402 	device_t dev;
403 	struct ds1307_softc *sc;
404 	struct sysctl_ctx_list *ctx;
405 	struct sysctl_oid *tree_node;
406 	struct sysctl_oid_list *tree;
407 
408 	dev = (device_t)xdev;
409 	sc = device_get_softc(dev);
410 
411 	config_intrhook_disestablish(&sc->enum_hook);
412 
413 	if (!is_dev_time_valid(sc))
414 		device_printf(dev,
415 		    "WARNING: RTC clock stopped, check the battery.\n");
416 
417 	/*
418 	 * Configuration parameters:
419 	 * square wave output cannot be changed or inhibited on the RX-8035,
420 	 * so don't present the sysctls there.
421 	 */
422 	if (sc->chiptype == TYPE_EPSON_RX8035)
423 		goto skip_sysctl;
424 
425 	ctx = device_get_sysctl_ctx(dev);
426 	tree_node = device_get_sysctl_tree(dev);
427 	tree = SYSCTL_CHILDREN(tree_node);
428 
429 	SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "sqwe",
430 	    CTLFLAG_RW | CTLTYPE_UINT | CTLFLAG_MPSAFE, sc, 0,
431 	    ds1307_sqwe_sysctl, "IU", "DS1307 square-wave enable");
432 	SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "sqw_freq",
433 	    CTLFLAG_RW | CTLTYPE_UINT | CTLFLAG_MPSAFE, sc, 0,
434 	    ds1307_sqw_freq_sysctl, "IU",
435 	    "DS1307 square-wave output frequency");
436 	SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "sqw_out",
437 	    CTLFLAG_RW | CTLTYPE_UINT | CTLFLAG_MPSAFE, sc, 0,
438 	    ds1307_sqw_out_sysctl, "IU", "DS1307 square-wave output state");
439 skip_sysctl:
440 
441 	/*
442 	 * Register as a clock with 1 second resolution.  Schedule the
443 	 * clock_settime() method to be called just after top-of-second;
444 	 * resetting the time resets top-of-second in the hardware.
445 	 */
446 	clock_register_flags(dev, 1000000, CLOCKF_SETTIME_NO_ADJ);
447 	clock_schedule(dev, 1);
448 }
449 
450 static int
451 ds1307_gettime(device_t dev, struct timespec *ts)
452 {
453 	struct bcd_clocktime bct;
454 	struct ds1307_softc *sc;
455 	int error;
456 	uint8_t data[7], hourmask, ampm_mode;
457 
458 	sc = device_get_softc(dev);
459 	error = iicdev_readfrom(sc->sc_dev, DS1307_SECS, data, sizeof(data),
460 	    IIC_INTRWAIT);
461 	if (error != 0) {
462 		device_printf(dev, "%s: cannot read from RTC: %d\n",
463 		    __func__, error);
464 		return (error);
465 	}
466 
467 	if (!is_dev_time_valid(sc)) {
468 		device_printf(dev, "Device time not valid.\n");
469 		return (EINVAL);
470 	}
471 
472 	/*
473 	 * If the chip is in AM/PM mode remember that.
474 	 * The EPSON uses a 1 to signify 24 hour mode, while the DS uses a 0,
475 	 * in slighly different positions.
476 	 */
477 	if (sc->chiptype == TYPE_EPSON_RX8035)
478 		ampm_mode = !(data[DS1307_HOUR] & RX8035_HOUR_USE_24);
479 	else
480 		ampm_mode = data[DS1307_HOUR] & DS1307_HOUR_USE_AMPM;
481 
482 	if (ampm_mode) {
483 		sc->sc_use_ampm = true;
484 		hourmask = DS1307_HOUR_MASK_12HR;
485 	} else
486 		hourmask = DS1307_HOUR_MASK_24HR;
487 
488 	bct.nsec = 0;
489 	bct.ispm = (data[DS1307_HOUR] & DS1307_HOUR_IS_PM) != 0;
490 	bct.sec  = data[DS1307_SECS]  & DS1307_SECS_MASK;
491 	bct.min  = data[DS1307_MINS]  & DS1307_MINS_MASK;
492 	bct.hour = data[DS1307_HOUR]  & hourmask;
493 	bct.day  = data[DS1307_DATE]  & DS1307_DATE_MASK;
494 	bct.mon  = data[DS1307_MONTH] & DS1307_MONTH_MASK;
495 	bct.year = data[DS1307_YEAR]  & DS1307_YEAR_MASK;
496 
497 	clock_dbgprint_bcd(sc->sc_dev, CLOCK_DBG_READ, &bct);
498 	return (clock_bcd_to_ts(&bct, ts, sc->sc_use_ampm));
499 }
500 
501 static int
502 ds1307_settime(device_t dev, struct timespec *ts)
503 {
504 	struct bcd_clocktime bct;
505 	struct ds1307_softc *sc;
506 	int error, year;
507 	uint8_t data[7];
508 	uint8_t pmflags;
509 
510 	sc = device_get_softc(dev);
511 
512 	/*
513 	 * We request a timespec with no resolution-adjustment.  That also
514 	 * disables utc adjustment, so apply that ourselves.
515 	 */
516 	ts->tv_sec -= utc_offset();
517 	clock_ts_to_bcd(ts, &bct, sc->sc_use_ampm);
518 	clock_dbgprint_bcd(sc->sc_dev, CLOCK_DBG_WRITE, &bct);
519 
520 	/*
521 	 * If the chip is in AM/PM mode, adjust hour and set flags as needed.
522 	 * The AM/PM bit polarity and position is different on the EPSON.
523 	 */
524 	if (sc->sc_use_ampm) {
525 		pmflags = (sc->chiptype != TYPE_EPSON_RX8035) ?
526 				DS1307_HOUR_USE_AMPM : 0;
527 		if (bct.ispm)
528 			pmflags |= DS1307_HOUR_IS_PM;
529 
530 	} else if (sc->chiptype == TYPE_EPSON_RX8035)
531 		pmflags = RX8035_HOUR_USE_24;
532 	else
533 		pmflags = 0;
534 
535 	data[DS1307_SECS]    = bct.sec;
536 	data[DS1307_MINS]    = bct.min;
537 	data[DS1307_HOUR]    = bct.hour | pmflags;
538 	data[DS1307_DATE]    = bct.day;
539 	data[DS1307_WEEKDAY] = bct.dow;
540 	data[DS1307_MONTH]   = bct.mon;
541 	data[DS1307_YEAR]    = bct.year & 0xff;
542 	if (sc->chiptype == TYPE_MICROCHIP_MCP7491X) {
543 		data[DS1307_SECS] |= MCP7941X_SECS_ST;
544 		data[DS1307_WEEKDAY] |= MCP7941X_WEEKDAY_VBATEN;
545 		year = bcd2bin(bct.year >> 8) * 100 + bcd2bin(bct.year & 0xff);
546 		if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)
547 			data[DS1307_MONTH] |= MCP7941X_MONTH_LPYR;
548 	}
549 
550 	/* Write the time back to RTC. */
551 	error = iicdev_writeto(sc->sc_dev, DS1307_SECS, data, sizeof(data),
552 	    IIC_INTRWAIT);
553 	if (error != 0)
554 		device_printf(dev, "%s: cannot write to RTC: %d\n",
555 		    __func__, error);
556 
557 	if (sc->chiptype == TYPE_EPSON_RX8035)
558 		error = mark_epson_time_valid(sc);
559 
560 	return (error);
561 }
562 
563 static device_method_t ds1307_methods[] = {
564 	DEVMETHOD(device_probe,		ds1307_probe),
565 	DEVMETHOD(device_attach,	ds1307_attach),
566 	DEVMETHOD(device_detach,	ds1307_detach),
567 
568 	DEVMETHOD(clock_gettime,	ds1307_gettime),
569 	DEVMETHOD(clock_settime,	ds1307_settime),
570 
571 	DEVMETHOD_END
572 };
573 
574 static driver_t ds1307_driver = {
575 	"ds1307",
576 	ds1307_methods,
577 	sizeof(struct ds1307_softc),
578 };
579 
580 DRIVER_MODULE(ds1307, iicbus, ds1307_driver, NULL, NULL);
581 MODULE_VERSION(ds1307, 1);
582 MODULE_DEPEND(ds1307, iicbus, 1, 1, 1);
583 IICBUS_FDT_PNP_INFO(ds1307_compat_data);
584