xref: /freebsd/sys/dev/iicbus/rtc/ds1307.c (revision e9ac41698b2f322d55ccf9da50a3596edb2c1800)
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_MCP7941X,
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_MCP7941X},
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_MCP7941X)
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 		switch(compat->ocd_data) {
230 		case TYPE_DS1307:
231 			device_set_desc(dev, "Dallas DS1307");
232 			break;
233 		case TYPE_MAXIM1307:
234 			device_set_desc(dev, "Maxim DS1307");
235 			break;
236 		case TYPE_MICROCHIP_MCP7941X:
237 			device_set_desc(dev, "Microchip MCP7941X");
238 			break;
239 		case TYPE_EPSON_RX8035:
240 			device_set_desc(dev, "Epson RX-8035");
241 			break;
242 		default:
243 			device_set_desc(dev, "Unknown DS1307-like device");
244 			break;
245 		}
246 		return (BUS_PROBE_DEFAULT);
247 	}
248 #endif
249 
250 	device_set_desc(dev, "Maxim DS1307");
251 	return (BUS_PROBE_NOWILDCARD);
252 }
253 
254 static int
255 ds1307_attach(device_t dev)
256 {
257 #ifdef FDT
258 	const struct ofw_compat_data *compat;
259 #endif
260 	struct ds1307_softc *sc;
261 
262 	sc = device_get_softc(dev);
263 	sc->sc_dev = dev;
264 	sc->enum_hook.ich_func = ds1307_start;
265 	sc->enum_hook.ich_arg = dev;
266 #ifdef FDT
267 	compat = ofw_bus_search_compatible(dev, ds1307_compat_data);
268 	sc->chiptype = compat->ocd_data;
269 	/* Unify the chiptypes to DS1307 where possible. */
270 	if (sc->chiptype == TYPE_MAXIM1307)
271 		sc->chiptype = TYPE_DS1307;
272 #else
273 	sc->chiptype = TYPE_DS1307;
274 #endif
275 
276 	/*
277 	 * We have to wait until interrupts are enabled.  Usually I2C read
278 	 * and write only works when the interrupts are available.
279 	 */
280 	if (config_intrhook_establish(&sc->enum_hook) != 0)
281 		return (ENOMEM);
282 
283 	return (0);
284 }
285 
286 static int
287 ds1307_detach(device_t dev)
288 {
289 
290 	clock_unregister(dev);
291 	return (0);
292 }
293 
294 static bool
295 is_epson_time_valid(struct ds1307_softc *sc)
296 {
297 	device_t dev;
298 	int error;
299 	uint8_t ctrl2;
300 
301 	dev = sc->sc_dev;
302 
303 	/*
304 	 * The RX-8035 single register read is non-standard
305 	 * Refer to section 8.9.5 of the RX-8035 application manual:
306 	 * "I2C bus basic transfer format", under "Standard Read Method".
307 	 * Basically, register to read goes into the top 4 bits.
308 	 */
309 	error = ds1307_read1(dev, (RX8035_CTRL_2 << 4), &ctrl2);
310 	if (error) {
311 		device_printf(dev, "%s cannot read Control 2 register: %d\n",
312 		    __func__, error);
313 		return (false);
314 	}
315 
316 	if (ctrl2 & RX8035_CTRL_2_XSTP) {
317 		device_printf(dev, "Oscillation stop detected (ctrl2=%#02x)\n",
318 		    ctrl2);
319 		return (false);
320 	}
321 
322 	/*
323 	 * Power on reset (PON) generally implies oscillation stop,
324 	 * but catch it as well to be sure.
325 	 */
326 	if (ctrl2 & RX8035_CTRL_2_PON) {
327 		device_printf(dev, "Power-on reset detected (ctrl2=%#02x)\n",
328 		    ctrl2);
329 		return (false);
330 	}
331 
332 	return (true);
333 }
334 
335 static int
336 mark_epson_time_valid(struct ds1307_softc *sc)
337 {
338 	device_t dev;
339 	int error;
340 	uint8_t ctrl2;
341 	uint8_t control_mask;
342 
343 	dev = sc->sc_dev;
344 
345 	error = ds1307_read1(dev, (RX8035_CTRL_2 << 4), &ctrl2);
346 	if (error) {
347 		device_printf(dev, "%s cannot read Control 2 register: %d\n",
348 		    __func__, error);
349 		return (error);
350 	}
351 
352 	control_mask = (RX8035_CTRL_2_PON | RX8035_CTRL_2_XSTP | RX8035_CTRL_2_VDET);
353 	ctrl2 = ctrl2 & ~(control_mask);
354 
355 	error = ds1307_write1(dev, (RX8035_CTRL_2 << 4), ctrl2);
356 	if (error) {
357 		device_printf(dev, "%s cannot write to Control 2 register: %d\n",
358 		    __func__, error);
359 		return (error);
360 	}
361 	return (0);
362 }
363 
364 static bool is_dev_time_valid(struct ds1307_softc *sc)
365 {
366 	device_t dev;
367 	int error;
368 	uint8_t osc_en;
369 	uint8_t secs;
370 
371 	/* Epson RTCs have different control/status registers. */
372 	if (sc->chiptype == TYPE_EPSON_RX8035)
373 		return (is_epson_time_valid(sc));
374 
375 	dev = sc->sc_dev;
376 	/* Check if the oscillator is disabled. */
377 	error = ds1307_read1(dev, DS1307_SECS, &secs);
378 	if (error) {
379 		device_printf(dev, "%s: cannot read from RTC: %d\n",
380 		    __func__, error);
381 		return (false);
382 	}
383 
384 	switch (sc->chiptype) {
385 	case TYPE_MICROCHIP_MCP7941X:
386 		osc_en = 0x80;
387 		break;
388 	default:
389 		osc_en = 0x00;
390 		break;
391 	}
392 	if (((secs & DS1307_SECS_CH) ^ osc_en) != 0)
393 		return (false);
394 
395 	return (true);
396 }
397 
398 static void
399 ds1307_start(void *xdev)
400 {
401 	device_t dev;
402 	struct ds1307_softc *sc;
403 	struct sysctl_ctx_list *ctx;
404 	struct sysctl_oid *tree_node;
405 	struct sysctl_oid_list *tree;
406 
407 	dev = (device_t)xdev;
408 	sc = device_get_softc(dev);
409 
410 	config_intrhook_disestablish(&sc->enum_hook);
411 
412 	if (!is_dev_time_valid(sc))
413 		device_printf(dev,
414 		    "WARNING: RTC clock stopped, check the battery.\n");
415 
416 	/*
417 	 * Configuration parameters:
418 	 * square wave output cannot be changed or inhibited on the RX-8035,
419 	 * so don't present the sysctls there.
420 	 */
421 	if (sc->chiptype == TYPE_EPSON_RX8035)
422 		goto skip_sysctl;
423 
424 	ctx = device_get_sysctl_ctx(dev);
425 	tree_node = device_get_sysctl_tree(dev);
426 	tree = SYSCTL_CHILDREN(tree_node);
427 
428 	SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "sqwe",
429 	    CTLFLAG_RW | CTLTYPE_UINT | CTLFLAG_MPSAFE, sc, 0,
430 	    ds1307_sqwe_sysctl, "IU", "DS1307 square-wave enable");
431 	SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "sqw_freq",
432 	    CTLFLAG_RW | CTLTYPE_UINT | CTLFLAG_MPSAFE, sc, 0,
433 	    ds1307_sqw_freq_sysctl, "IU",
434 	    "DS1307 square-wave output frequency");
435 	SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "sqw_out",
436 	    CTLFLAG_RW | CTLTYPE_UINT | CTLFLAG_MPSAFE, sc, 0,
437 	    ds1307_sqw_out_sysctl, "IU", "DS1307 square-wave output state");
438 skip_sysctl:
439 
440 	/*
441 	 * Register as a clock with 1 second resolution.  Schedule the
442 	 * clock_settime() method to be called just after top-of-second;
443 	 * resetting the time resets top-of-second in the hardware.
444 	 */
445 	clock_register_flags(dev, 1000000, CLOCKF_SETTIME_NO_ADJ);
446 	clock_schedule(dev, 1);
447 }
448 
449 static int
450 ds1307_gettime(device_t dev, struct timespec *ts)
451 {
452 	struct bcd_clocktime bct;
453 	struct ds1307_softc *sc;
454 	int error;
455 	uint8_t data[7], hourmask, ampm_mode;
456 
457 	sc = device_get_softc(dev);
458 	error = iicdev_readfrom(sc->sc_dev, DS1307_SECS, data, sizeof(data),
459 	    IIC_INTRWAIT);
460 	if (error != 0) {
461 		device_printf(dev, "%s: cannot read from RTC: %d\n",
462 		    __func__, error);
463 		return (error);
464 	}
465 
466 	if (!is_dev_time_valid(sc)) {
467 		device_printf(dev, "Device time not valid.\n");
468 		return (EINVAL);
469 	}
470 
471 	/*
472 	 * If the chip is in AM/PM mode remember that.
473 	 * The EPSON uses a 1 to signify 24 hour mode, while the DS uses a 0,
474 	 * in slightly different positions.
475 	 */
476 	if (sc->chiptype == TYPE_EPSON_RX8035)
477 		ampm_mode = !(data[DS1307_HOUR] & RX8035_HOUR_USE_24);
478 	else
479 		ampm_mode = data[DS1307_HOUR] & DS1307_HOUR_USE_AMPM;
480 
481 	if (ampm_mode) {
482 		sc->sc_use_ampm = true;
483 		hourmask = DS1307_HOUR_MASK_12HR;
484 	} else
485 		hourmask = DS1307_HOUR_MASK_24HR;
486 
487 	bct.nsec = 0;
488 	bct.ispm = (data[DS1307_HOUR] & DS1307_HOUR_IS_PM) != 0;
489 	bct.sec  = data[DS1307_SECS]  & DS1307_SECS_MASK;
490 	bct.min  = data[DS1307_MINS]  & DS1307_MINS_MASK;
491 	bct.hour = data[DS1307_HOUR]  & hourmask;
492 	bct.day  = data[DS1307_DATE]  & DS1307_DATE_MASK;
493 	bct.mon  = data[DS1307_MONTH] & DS1307_MONTH_MASK;
494 	bct.year = data[DS1307_YEAR]  & DS1307_YEAR_MASK;
495 
496 	clock_dbgprint_bcd(sc->sc_dev, CLOCK_DBG_READ, &bct);
497 	return (clock_bcd_to_ts(&bct, ts, sc->sc_use_ampm));
498 }
499 
500 static int
501 ds1307_settime(device_t dev, struct timespec *ts)
502 {
503 	struct bcd_clocktime bct;
504 	struct ds1307_softc *sc;
505 	int error, year;
506 	uint8_t data[7];
507 	uint8_t pmflags;
508 
509 	sc = device_get_softc(dev);
510 
511 	/*
512 	 * We request a timespec with no resolution-adjustment.  That also
513 	 * disables utc adjustment, so apply that ourselves.
514 	 */
515 	ts->tv_sec -= utc_offset();
516 	clock_ts_to_bcd(ts, &bct, sc->sc_use_ampm);
517 	clock_dbgprint_bcd(sc->sc_dev, CLOCK_DBG_WRITE, &bct);
518 
519 	/*
520 	 * If the chip is in AM/PM mode, adjust hour and set flags as needed.
521 	 * The AM/PM bit polarity and position is different on the EPSON.
522 	 */
523 	if (sc->sc_use_ampm) {
524 		pmflags = (sc->chiptype != TYPE_EPSON_RX8035) ?
525 				DS1307_HOUR_USE_AMPM : 0;
526 		if (bct.ispm)
527 			pmflags |= DS1307_HOUR_IS_PM;
528 
529 	} else if (sc->chiptype == TYPE_EPSON_RX8035)
530 		pmflags = RX8035_HOUR_USE_24;
531 	else
532 		pmflags = 0;
533 
534 	data[DS1307_SECS]    = bct.sec;
535 	data[DS1307_MINS]    = bct.min;
536 	data[DS1307_HOUR]    = bct.hour | pmflags;
537 	data[DS1307_DATE]    = bct.day;
538 	data[DS1307_WEEKDAY] = bct.dow;
539 	data[DS1307_MONTH]   = bct.mon;
540 	data[DS1307_YEAR]    = bct.year & 0xff;
541 	if (sc->chiptype == TYPE_MICROCHIP_MCP7941X) {
542 		data[DS1307_SECS] |= MCP7941X_SECS_ST;
543 		data[DS1307_WEEKDAY] |= MCP7941X_WEEKDAY_VBATEN;
544 		year = bcd2bin(bct.year >> 8) * 100 + bcd2bin(bct.year & 0xff);
545 		if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)
546 			data[DS1307_MONTH] |= MCP7941X_MONTH_LPYR;
547 	}
548 
549 	/* Write the time back to RTC. */
550 	error = iicdev_writeto(sc->sc_dev, DS1307_SECS, data, sizeof(data),
551 	    IIC_INTRWAIT);
552 	if (error != 0)
553 		device_printf(dev, "%s: cannot write to RTC: %d\n",
554 		    __func__, error);
555 
556 	if (sc->chiptype == TYPE_EPSON_RX8035)
557 		error = mark_epson_time_valid(sc);
558 
559 	return (error);
560 }
561 
562 static device_method_t ds1307_methods[] = {
563 	DEVMETHOD(device_probe,		ds1307_probe),
564 	DEVMETHOD(device_attach,	ds1307_attach),
565 	DEVMETHOD(device_detach,	ds1307_detach),
566 
567 	DEVMETHOD(clock_gettime,	ds1307_gettime),
568 	DEVMETHOD(clock_settime,	ds1307_settime),
569 
570 	DEVMETHOD_END
571 };
572 
573 static driver_t ds1307_driver = {
574 	"ds1307",
575 	ds1307_methods,
576 	sizeof(struct ds1307_softc),
577 };
578 
579 DRIVER_MODULE(ds1307, iicbus, ds1307_driver, NULL, NULL);
580 MODULE_VERSION(ds1307, 1);
581 MODULE_DEPEND(ds1307, iicbus, 1, 1, 1);
582 IICBUS_FDT_PNP_INFO(ds1307_compat_data);
583