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
56enum {
57	TYPE_DS1307,
58	TYPE_MAXIM1307,
59	TYPE_MICROCHIP_MCP7941X,
60	TYPE_EPSON_RX8035,
61	TYPE_COUNT
62};
63
64struct 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
72static void ds1307_start(void *);
73
74#ifdef FDT
75static 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
84static int
85ds1307_read1(device_t dev, uint8_t reg, uint8_t *data)
86{
87
88	return (iicdev_readfrom(dev, reg, data, 1, IIC_INTRWAIT));
89}
90
91static int
92ds1307_write1(device_t dev, uint8_t reg, uint8_t data)
93{
94
95	return (iicdev_writeto(dev, reg, &data, 1, IIC_INTRWAIT));
96}
97
98static int
99ds1307_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
114static int
115ds1307_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
129static int
130ds1307_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
159static int
160ds1307_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
192static int
193ds1307_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
218static int
219ds1307_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
254static int
255ds1307_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
286static int
287ds1307_detach(device_t dev)
288{
289
290	clock_unregister(dev);
291	return (0);
292}
293
294static bool
295is_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
335static int
336mark_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
364static 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
398static void
399ds1307_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");
438skip_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
449static int
450ds1307_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
500static int
501ds1307_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
562static 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
573static driver_t ds1307_driver = {
574	"ds1307",
575	ds1307_methods,
576	sizeof(struct ds1307_softc),
577};
578
579DRIVER_MODULE(ds1307, iicbus, ds1307_driver, NULL, NULL);
580MODULE_VERSION(ds1307, 1);
581MODULE_DEPEND(ds1307, iicbus, 1, 1, 1);
582IICBUS_FDT_PNP_INFO(ds1307_compat_data);
583