1322473Sian/*-
2322473Sian * Copyright (c) 2017 Ian Lepore <ian@freebsd.org>
3322473Sian * All rights reserved.
4322473Sian *
5322473Sian * Redistribution and use in source and binary forms, with or without
6322473Sian * modification, are permitted provided that the following conditions
7322473Sian * are met:
8322473Sian * 1. Redistributions of source code must retain the above copyright
9322473Sian *    notice, this list of conditions and the following disclaimer.
10322473Sian * 2. Redistributions in binary form must reproduce the above copyright
11322473Sian *    notice, this list of conditions and the following disclaimer in the
12322473Sian *    documentation and/or other materials provided with the distribution.
13322473Sian *
14322473Sian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15322473Sian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16322473Sian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17322473Sian * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18322473Sian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19322473Sian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20322473Sian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21322473Sian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22322473Sian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23322473Sian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24322473Sian * SUCH DAMAGE.
25322473Sian */
26322473Sian
27322473Sian#include <sys/cdefs.h>
28322473Sian__FBSDID("$FreeBSD: stable/11/sys/dev/iicbus/ds13rtc.c 331503 2018-03-24 23:01:10Z ian $");
29322473Sian
30322473Sian/*
31322473Sian * Driver for Dallas/Maxim DS13xx real-time clock/calendar chips:
32322473Sian *
33322473Sian * - DS1307 = Original/basic rtc + 56 bytes ram; 5v only.
34322473Sian * - DS1308 = Updated 1307, available in 1.8v-5v variations.
35322473Sian * - DS1337 = Like 1308, integrated xtal, 32khz output on at powerup.
36322473Sian * - DS1338 = Like 1308, integrated xtal.
37322473Sian * - DS1339 = Like 1337, integrated xtal, integrated trickle charger.
38322473Sian * - DS1340 = Like 1338, ST M41T00 compatible.
39322473Sian * - DS1341 = Like 1338, can slave-sync osc to external clock signal.
40322473Sian * - DS1342 = Like 1341 but requires different xtal.
41322473Sian * - DS1371 = 32-bit binary counter, watchdog timer.
42322473Sian * - DS1372 = 32-bit binary counter, 64-bit unique id in rom.
43322473Sian * - DS1374 = 32-bit binary counter, watchdog timer, trickle charger.
44322473Sian * - DS1375 = Like 1308 but only 16 bytes ram.
45322473Sian * - DS1388 = Rtc, watchdog timer, 512 bytes eeprom (not sram).
46322473Sian *
47322473Sian * This driver supports only basic timekeeping functions.  It provides no access
48322473Sian * to or control over any other functionality provided by the chips.
49322473Sian */
50322473Sian
51322473Sian#include "opt_platform.h"
52322473Sian
53322473Sian#include <sys/param.h>
54322473Sian#include <sys/systm.h>
55322473Sian#include <sys/bus.h>
56322473Sian#include <sys/clock.h>
57322473Sian#include <sys/endian.h>
58322473Sian#include <sys/kernel.h>
59322473Sian#include <sys/libkern.h>
60322473Sian#include <sys/module.h>
61322473Sian
62322473Sian#include <dev/iicbus/iicbus.h>
63322473Sian#include <dev/iicbus/iiconf.h>
64322473Sian#ifdef FDT
65322473Sian#include <dev/ofw/openfirm.h>
66322473Sian#include <dev/ofw/ofw_bus.h>
67322473Sian#include <dev/ofw/ofw_bus_subr.h>
68322473Sian#endif
69322473Sian
70322473Sian#include "clock_if.h"
71322473Sian#include "iicbus_if.h"
72322473Sian
73322473Sian/*
74322473Sian * I2C address 1101 000x
75322473Sian */
76322473Sian#define	DS13xx_ADDR		0xd0
77322473Sian
78322473Sian/*
79322473Sian * Registers, bits within them, and masks for the various chip types.
80322473Sian */
81322473Sian
82322473Sian#define	DS13xx_R_NONE		0xff	/* Placeholder */
83322473Sian
84322473Sian#define	DS130x_R_CONTROL	0x07
85322473Sian#define	DS133x_R_CONTROL	0x0e
86322473Sian#define	DS1340_R_CONTROL	0x07
87322473Sian#define	DS1341_R_CONTROL	0x0e
88322473Sian#define	DS1371_R_CONTROL	0x07
89322473Sian#define	DS1372_R_CONTROL	0x07
90322473Sian#define	DS1374_R_CONTROL	0x07
91322473Sian#define	DS1375_R_CONTROL	0x0e
92322473Sian#define	DS1388_R_CONTROL	0x0c
93322473Sian
94322473Sian#define	DS13xx_R_SECOND		0x00
95322473Sian#define	DS1388_R_SECOND		0x01
96322473Sian
97322473Sian#define	DS130x_R_STATUS		DS13xx_R_NONE
98322473Sian#define	DS133x_R_STATUS		0x0f
99322473Sian#define	DS1340_R_STATUS		0x09
100322473Sian#define	DS137x_R_STATUS		0x08
101322473Sian#define	DS1388_R_STATUS		0x0b
102322473Sian
103322473Sian#define	DS13xx_B_STATUS_OSF	0x80	/* OSF is 1<<7 in status and sec regs */
104322473Sian#define	DS13xx_B_HOUR_AMPM	0x40	/* AMPM mode is bit 1<<6 */
105322473Sian#define	DS13xx_B_HOUR_PM	0x20	/* PM hours indicated by 1<<5 */
106322473Sian#define	DS13xx_B_MONTH_CENTURY	0x80	/* 21st century indicated by 1<<7 */
107322473Sian
108322473Sian#define	DS13xx_M_SECOND		0x7f	/* Masks for all BCD time regs... */
109322473Sian#define	DS13xx_M_MINUTE		0x7f
110322473Sian#define	DS13xx_M_12HOUR		0x1f
111322473Sian#define	DS13xx_M_24HOUR		0x3f
112322473Sian#define	DS13xx_M_DAY		0x3f
113322473Sian#define	DS13xx_M_MONTH		0x1f
114322473Sian#define	DS13xx_M_YEAR		0xff
115322473Sian
116322473Sian/*
117322473Sian * The chip types we support.
118322473Sian */
119322473Sianenum {
120322473Sian	TYPE_NONE,
121322473Sian	TYPE_DS1307,
122322473Sian	TYPE_DS1308,
123322473Sian	TYPE_DS1337,
124322473Sian	TYPE_DS1338,
125322473Sian	TYPE_DS1339,
126322473Sian	TYPE_DS1340,
127322473Sian	TYPE_DS1341,
128322473Sian	TYPE_DS1342,
129322473Sian	TYPE_DS1371,
130322473Sian	TYPE_DS1372,
131322473Sian	TYPE_DS1374,
132322473Sian	TYPE_DS1375,
133322473Sian	TYPE_DS1388,
134322473Sian
135322473Sian	TYPE_COUNT
136322473Sian};
137322473Sianstatic const char *desc_strings[] = {
138322473Sian	"",
139322473Sian	"Dallas/Maxim DS1307 RTC",
140322473Sian	"Dallas/Maxim DS1308 RTC",
141322473Sian	"Dallas/Maxim DS1337 RTC",
142322473Sian	"Dallas/Maxim DS1338 RTC",
143322473Sian	"Dallas/Maxim DS1339 RTC",
144322473Sian	"Dallas/Maxim DS1340 RTC",
145322473Sian	"Dallas/Maxim DS1341 RTC",
146322473Sian	"Dallas/Maxim DS1342 RTC",
147322473Sian	"Dallas/Maxim DS1371 RTC",
148322473Sian	"Dallas/Maxim DS1372 RTC",
149322473Sian	"Dallas/Maxim DS1374 RTC",
150322473Sian	"Dallas/Maxim DS1375 RTC",
151322473Sian	"Dallas/Maxim DS1388 RTC",
152322473Sian};
153322473SianCTASSERT(nitems(desc_strings) == TYPE_COUNT);
154322473Sian
155322473Sian/*
156322473Sian * The time registers in the order they are laid out in hardware.
157322473Sian */
158322473Sianstruct time_regs {
159322473Sian	uint8_t sec, min, hour, wday, day, month, year;
160322473Sian};
161322473Sian
162322473Sianstruct ds13rtc_softc {
163322473Sian	device_t	dev;
164322473Sian	device_t	busdev;
165322473Sian	u_int		chiptype;	/* Type of DS13xx chip */
166322473Sian	uint8_t		secaddr;	/* Address of seconds register */
167322473Sian	uint8_t		osfaddr;	/* Address of register with OSF */
168331495Sian	bool		use_ampm;	/* Use AM/PM mode. */
169331495Sian	bool		use_century;	/* Use the Century bit. */
170331495Sian	bool		is_binary_counter; /* Chip has 32-bit binary counter. */
171322473Sian};
172322473Sian
173322473Sian/*
174322473Sian * We use the compat_data table to look up hint strings in the non-FDT case, so
175322473Sian * define the struct locally when we don't get it from ofw_bus_subr.h.
176322473Sian */
177322473Sian#ifdef FDT
178322473Siantypedef struct ofw_compat_data ds13_compat_data;
179322473Sian#else
180322473Siantypedef struct {
181322473Sian	const char *ocd_str;
182322473Sian	uintptr_t  ocd_data;
183322473Sian} ds13_compat_data;
184322473Sian#endif
185322473Sian
186322473Sianstatic ds13_compat_data compat_data[] = {
187322473Sian	{"dallas,ds1307",   TYPE_DS1307},
188322473Sian	{"dallas,ds1308",   TYPE_DS1308},
189322473Sian	{"dallas,ds1337",   TYPE_DS1337},
190322473Sian	{"dallas,ds1338",   TYPE_DS1338},
191322473Sian	{"dallas,ds1339",   TYPE_DS1339},
192322473Sian	{"dallas,ds1340",   TYPE_DS1340},
193322473Sian	{"dallas,ds1341",   TYPE_DS1341},
194322473Sian	{"dallas,ds1342",   TYPE_DS1342},
195322473Sian	{"dallas,ds1371",   TYPE_DS1371},
196322473Sian	{"dallas,ds1372",   TYPE_DS1372},
197322473Sian	{"dallas,ds1374",   TYPE_DS1374},
198322473Sian	{"dallas,ds1375",   TYPE_DS1375},
199322473Sian	{"dallas,ds1388",   TYPE_DS1388},
200322473Sian
201322473Sian	{NULL,              TYPE_NONE},
202322473Sian};
203322473Sian
204322473Sianstatic int
205322473Sianread_reg(struct ds13rtc_softc *sc, uint8_t reg, uint8_t *val)
206322473Sian{
207322473Sian
208322473Sian	return (iicdev_readfrom(sc->dev, reg, val, sizeof(*val), IIC_WAIT));
209322473Sian}
210322473Sian
211322473Sianstatic int
212322473Sianwrite_reg(struct ds13rtc_softc *sc, uint8_t reg, uint8_t val)
213322473Sian{
214322473Sian
215322473Sian	return (iicdev_writeto(sc->dev, reg, &val, sizeof(val), IIC_WAIT));
216322473Sian}
217322473Sian
218322473Sianstatic int
219322473Sianread_timeregs(struct ds13rtc_softc *sc, struct time_regs *tregs)
220322473Sian{
221322473Sian	int err;
222322473Sian
223322473Sian	if ((err = iicdev_readfrom(sc->dev, sc->secaddr, tregs,
224322473Sian	    sizeof(*tregs), IIC_WAIT)) != 0)
225322473Sian		return (err);
226322473Sian
227322473Sian	return (err);
228322473Sian}
229322473Sian
230322473Sianstatic int
231322473Sianwrite_timeregs(struct ds13rtc_softc *sc, struct time_regs *tregs)
232322473Sian{
233322473Sian
234322473Sian	return (iicdev_writeto(sc->dev, sc->secaddr, tregs,
235322473Sian	    sizeof(*tregs), IIC_WAIT));
236322473Sian}
237322473Sian
238322473Sianstatic int
239322473Sianread_timeword(struct ds13rtc_softc *sc, time_t *secs)
240322473Sian{
241322473Sian	int err;
242322473Sian	uint8_t buf[4];
243322473Sian
244322473Sian	if ((err = iicdev_readfrom(sc->dev, sc->secaddr, buf, sizeof(buf),
245322473Sian	    IIC_WAIT)) == 0)
246322473Sian		*secs = le32dec(buf);
247322473Sian
248322473Sian	return (err);
249322473Sian}
250322473Sian
251322473Sianstatic int
252322473Sianwrite_timeword(struct ds13rtc_softc *sc, time_t secs)
253322473Sian{
254322473Sian	uint8_t buf[4];
255322473Sian
256322473Sian	le32enc(buf, (uint32_t)secs);
257322473Sian	return (iicdev_writeto(sc->dev, sc->secaddr, buf, sizeof(buf),
258322473Sian	    IIC_WAIT));
259322473Sian}
260322473Sian
261322473Sianstatic void
262322473Siands13rtc_start(void *arg)
263322473Sian{
264322473Sian	struct ds13rtc_softc *sc;
265322473Sian	uint8_t ctlreg, statreg;
266322473Sian
267322473Sian	sc = arg;
268322473Sian
269322473Sian	/*
270322473Sian	 * Every chip in this family can be usefully initialized by writing 0 to
271322473Sian	 * the control register, except DS1375 which has an external oscillator
272322473Sian	 * controlled by values in the ctlreg that we know nothing about, so
273322473Sian	 * we'd best leave them alone.  For all other chips, writing 0 enables
274322473Sian	 * the oscillator, disables signals/outputs in battery-backed mode
275322473Sian	 * (saves power) and disables features like watchdog timers and alarms.
276322473Sian	 */
277322473Sian	switch (sc->chiptype) {
278322473Sian	case TYPE_DS1307:
279322473Sian	case TYPE_DS1308:
280322473Sian	case TYPE_DS1338:
281322473Sian	case TYPE_DS1340:
282322473Sian	case TYPE_DS1371:
283322473Sian	case TYPE_DS1372:
284322473Sian	case TYPE_DS1374:
285322473Sian		ctlreg = DS130x_R_CONTROL;
286322473Sian		break;
287322473Sian	case TYPE_DS1337:
288322473Sian	case TYPE_DS1339:
289322473Sian		ctlreg = DS133x_R_CONTROL;
290322473Sian		break;
291322473Sian	case TYPE_DS1341:
292322473Sian	case TYPE_DS1342:
293322473Sian		ctlreg = DS1341_R_CONTROL;
294322473Sian		break;
295322473Sian	case TYPE_DS1375:
296322473Sian		ctlreg = DS13xx_R_NONE;
297322473Sian		break;
298322473Sian	case TYPE_DS1388:
299322473Sian		ctlreg = DS1388_R_CONTROL;
300322473Sian		break;
301322473Sian	default:
302322473Sian		device_printf(sc->dev, "missing init code for this chiptype\n");
303322473Sian		return;
304322473Sian	}
305322473Sian	if (ctlreg != DS13xx_R_NONE)
306322473Sian		write_reg(sc, ctlreg, 0);
307322473Sian
308322473Sian	/*
309322473Sian	 * Common init.  Read the OSF/CH status bit and report stopped clocks to
310322473Sian	 * the user.  The status bit will be cleared the first time we write
311322473Sian	 * valid time to the chip (and must not be cleared before that).
312322473Sian	 */
313322473Sian	if (read_reg(sc, sc->osfaddr, &statreg) != 0) {
314322473Sian		device_printf(sc->dev, "cannot read RTC clock status bit\n");
315322473Sian		return;
316322473Sian	}
317322473Sian	if (statreg & DS13xx_B_STATUS_OSF) {
318322473Sian		device_printf(sc->dev,
319322473Sian		    "WARNING: RTC battery failed; time is invalid\n");
320322473Sian	}
321322473Sian
322322473Sian	/*
323322473Sian	 * Figure out whether the chip is configured for AM/PM mode.  On all
324322473Sian	 * chips that do AM/PM mode, the flag bit is in the hours register,
325322473Sian	 * which is secaddr+2.
326322473Sian	 */
327331495Sian	if ((sc->chiptype != TYPE_DS1340) && !sc->is_binary_counter) {
328322473Sian		if (read_reg(sc, sc->secaddr + 2, &statreg) != 0) {
329322473Sian			device_printf(sc->dev,
330322473Sian			    "cannot read RTC clock AM/PM bit\n");
331322473Sian			return;
332322473Sian		}
333322473Sian		if (statreg & DS13xx_B_HOUR_AMPM)
334331495Sian			sc->use_ampm = true;
335322473Sian	}
336322473Sian
337322473Sian	/*
338322473Sian	 * Everything looks good if we make it to here; register as an RTC.
339322473Sian	 * Schedule RTC updates to happen just after top-of-second.
340322473Sian	 */
341322473Sian	clock_register_flags(sc->dev, 1000000, CLOCKF_SETTIME_NO_ADJ);
342322473Sian	clock_schedule(sc->dev, 1);
343322473Sian}
344322473Sian
345322473Sianstatic int
346322473Siands13rtc_gettime(device_t dev, struct timespec *ts)
347322473Sian{
348331496Sian	struct bcd_clocktime bct;
349322473Sian	struct time_regs tregs;
350322473Sian	struct ds13rtc_softc *sc;
351322473Sian	int err;
352322473Sian	uint8_t statreg, hourmask;
353322473Sian
354322473Sian	sc = device_get_softc(dev);
355322473Sian
356322473Sian	/* Read the OSF/CH bit; if the clock stopped we can't provide time. */
357322473Sian	if ((err = read_reg(sc, sc->osfaddr, &statreg)) != 0) {
358322473Sian		return (err);
359322473Sian	}
360322473Sian	if (statreg & DS13xx_B_STATUS_OSF)
361322473Sian		return (EINVAL); /* hardware is good, time is not. */
362322473Sian
363322473Sian	/* If the chip counts time in binary, we just read and return it. */
364331495Sian	if (sc->is_binary_counter) {
365322473Sian		ts->tv_nsec = 0;
366331495Sian		return (read_timeword(sc, &ts->tv_sec));
367322473Sian	}
368322473Sian
369322473Sian	/*
370322473Sian	 * Chip counts in BCD, read and decode it...
371322473Sian	 */
372322473Sian	if ((err = read_timeregs(sc, &tregs)) != 0) {
373322473Sian		device_printf(dev, "cannot read RTC time\n");
374322473Sian		return (err);
375322473Sian	}
376322473Sian
377331495Sian	if (sc->use_ampm)
378322473Sian		hourmask = DS13xx_M_12HOUR;
379322473Sian	else
380322473Sian		hourmask = DS13xx_M_24HOUR;
381322473Sian
382331496Sian	bct.nsec = 0;
383331496Sian	bct.ispm = tregs.hour  & DS13xx_B_HOUR_PM;
384331496Sian	bct.sec  = tregs.sec   & DS13xx_M_SECOND;
385331496Sian	bct.min  = tregs.min   & DS13xx_M_MINUTE;
386331496Sian	bct.hour = tregs.hour  & hourmask;
387331496Sian	bct.day  = tregs.day   & DS13xx_M_DAY;
388331496Sian	bct.mon  = tregs.month & DS13xx_M_MONTH;
389331496Sian	bct.year = tregs.year  & DS13xx_M_YEAR;
390322473Sian
391322473Sian	/*
392322473Sian	 * If this chip has a century bit, honor it.  Otherwise let
393322473Sian	 * clock_ct_to_ts() infer the century from the 2-digit year.
394322473Sian	 */
395331495Sian	if (sc->use_century)
396331496Sian		bct.year += (tregs.month & DS13xx_B_MONTH_CENTURY) ? 0x100 : 0;
397322473Sian
398331503Sian	clock_dbgprint_bcd(sc->dev, CLOCK_DBG_READ, &bct);
399331496Sian	err = clock_bcd_to_ts(&bct, ts, sc->use_ampm);
400322473Sian
401322473Sian	return (err);
402322473Sian}
403322473Sian
404322473Sianstatic int
405322473Siands13rtc_settime(device_t dev, struct timespec *ts)
406322473Sian{
407331496Sian	struct bcd_clocktime bct;
408322473Sian	struct time_regs tregs;
409322473Sian	struct ds13rtc_softc *sc;
410322473Sian	int err;
411331495Sian	uint8_t cflag, statreg, pmflags;
412322473Sian
413322473Sian	sc = device_get_softc(dev);
414322473Sian
415322473Sian	/*
416322473Sian	 * We request a timespec with no resolution-adjustment.  That also
417322473Sian	 * disables utc adjustment, so apply that ourselves.
418322473Sian	 */
419322473Sian	ts->tv_sec -= utc_offset();
420322473Sian
421322473Sian	/* If the chip counts time in binary, store tv_sec and we're done. */
422331495Sian	if (sc->is_binary_counter)
423322473Sian		return (write_timeword(sc, ts->tv_sec));
424322473Sian
425331496Sian	clock_ts_to_bcd(ts, &bct, sc->use_ampm);
426331503Sian	clock_dbgprint_bcd(sc->dev, CLOCK_DBG_WRITE, &bct);
427322473Sian
428322473Sian	/* If the chip is in AMPM mode deal with the PM flag. */
429331495Sian	pmflags = 0;
430331495Sian	if (sc->use_ampm) {
431331495Sian		pmflags = DS13xx_B_HOUR_AMPM;
432331496Sian		if (bct.ispm)
433331495Sian			pmflags |= DS13xx_B_HOUR_PM;
434322473Sian	}
435322473Sian
436322473Sian	/* If the chip has a century bit, set it as needed. */
437322473Sian	cflag = 0;
438331495Sian	if (sc->use_century) {
439331496Sian		if (bct.year >= 2000)
440322473Sian			cflag |= DS13xx_B_MONTH_CENTURY;
441322473Sian	}
442322473Sian
443331496Sian	tregs.sec   = bct.sec;
444331496Sian	tregs.min   = bct.min;
445331496Sian	tregs.hour  = bct.hour | pmflags;
446331496Sian	tregs.day   = bct.day;
447331496Sian	tregs.month = bct.mon | cflag;
448331496Sian	tregs.year  = bct.year & 0xff;
449331496Sian	tregs.wday  = bct.dow;
450322473Sian
451322473Sian	/*
452322473Sian	 * Set the time.  Reset the OSF bit if it is on and it is not part of
453322473Sian	 * the time registers (in which case writing time resets it).
454322473Sian	 */
455322473Sian	if ((err = write_timeregs(sc, &tregs)) != 0)
456322473Sian		goto errout;
457322473Sian	if (sc->osfaddr != sc->secaddr) {
458322473Sian		if ((err = read_reg(sc, sc->osfaddr, &statreg)) != 0)
459322473Sian			goto errout;
460322473Sian		if (statreg & DS13xx_B_STATUS_OSF) {
461322473Sian			statreg &= ~DS13xx_B_STATUS_OSF;
462322473Sian			err = write_reg(sc, sc->osfaddr, statreg);
463322473Sian		}
464322473Sian	}
465322473Sian
466322473Sianerrout:
467322473Sian
468322473Sian	if (err != 0)
469322473Sian		device_printf(dev, "cannot update RTC time\n");
470322473Sian
471322473Sian	return (err);
472322473Sian}
473322473Sian
474322473Sianstatic int
475322473Siands13rtc_get_chiptype(device_t dev)
476322473Sian{
477322473Sian#ifdef FDT
478322473Sian
479322473Sian	return (ofw_bus_search_compatible(dev, compat_data)->ocd_data);
480322473Sian#else
481322473Sian	ds13_compat_data *cdata;
482322473Sian	const char *htype;
483322473Sian
484322473Sian	/*
485322473Sian	 * We can only attach if provided a chiptype hint string.
486322473Sian	 */
487322473Sian	if (resource_string_value(device_get_name(dev),
488323467Sian	    device_get_unit(dev), "compatible", &htype) != 0)
489322473Sian		return (TYPE_NONE);
490322473Sian
491322473Sian	/*
492322473Sian	 * Loop through the ofw compat data comparing the hinted chip type to
493322473Sian	 * the compat strings.
494322473Sian	 */
495322473Sian	for (cdata = compat_data; cdata->ocd_str != NULL; ++cdata) {
496322473Sian		if (strcmp(htype, cdata->ocd_str) == 0)
497322473Sian			break;
498322473Sian	}
499322473Sian	return (cdata->ocd_data);
500322473Sian#endif
501322473Sian}
502322473Sian
503322473Sianstatic int
504322473Siands13rtc_probe(device_t dev)
505322473Sian{
506322473Sian	int chiptype, goodrv;
507322473Sian
508322473Sian#ifdef FDT
509322473Sian	if (!ofw_bus_status_okay(dev))
510322473Sian		return (ENXIO);
511322473Sian	goodrv = BUS_PROBE_GENERIC;
512322473Sian#else
513322473Sian	goodrv = BUS_PROBE_NOWILDCARD;
514322473Sian#endif
515322473Sian
516322473Sian	chiptype = ds13rtc_get_chiptype(dev);
517322473Sian	if (chiptype == TYPE_NONE)
518322473Sian		return (ENXIO);
519322473Sian
520322473Sian	device_set_desc(dev, desc_strings[chiptype]);
521322473Sian	return (goodrv);
522322473Sian}
523322473Sian
524322473Sianstatic int
525322473Siands13rtc_attach(device_t dev)
526322473Sian{
527322473Sian	struct ds13rtc_softc *sc;
528322473Sian
529322473Sian	sc = device_get_softc(dev);
530322473Sian	sc->dev = dev;
531322473Sian	sc->busdev = device_get_parent(dev);
532322473Sian
533322473Sian	/*
534322473Sian	 * We need to know what kind of chip we're driving.
535322473Sian	 */
536322473Sian	if ((sc->chiptype = ds13rtc_get_chiptype(dev)) == TYPE_NONE) {
537322473Sian		device_printf(dev, "impossible: cannot determine chip type\n");
538322473Sian		return (ENXIO);
539322473Sian	}
540322473Sian
541322473Sian	/* The seconds register is in the same place on all except DS1388. */
542322473Sian	if (sc->chiptype == TYPE_DS1388)
543322473Sian		sc->secaddr = DS1388_R_SECOND;
544322473Sian	else
545322473Sian		sc->secaddr = DS13xx_R_SECOND;
546322473Sian
547322473Sian	/*
548322473Sian	 * The OSF/CH (osc failed/clock-halted) bit appears in different
549322473Sian	 * registers for different chip types.  The DS1375 has no OSF indicator
550322473Sian	 * because it has no internal oscillator; we just point to an always-
551322473Sian	 * zero bit in the status register for that chip.
552322473Sian	 */
553322473Sian	switch (sc->chiptype) {
554322473Sian	case TYPE_DS1307:
555322473Sian	case TYPE_DS1308:
556322473Sian	case TYPE_DS1338:
557322473Sian		sc->osfaddr = DS13xx_R_SECOND;
558322473Sian		break;
559322473Sian	case TYPE_DS1337:
560322473Sian	case TYPE_DS1339:
561322473Sian	case TYPE_DS1341:
562322473Sian	case TYPE_DS1342:
563322473Sian	case TYPE_DS1375:
564322473Sian		sc->osfaddr = DS133x_R_STATUS;
565331495Sian		sc->use_century = true;
566322473Sian		break;
567322473Sian	case TYPE_DS1340:
568322473Sian		sc->osfaddr = DS1340_R_STATUS;
569322473Sian		break;
570322473Sian	case TYPE_DS1371:
571322473Sian	case TYPE_DS1372:
572322473Sian	case TYPE_DS1374:
573322473Sian		sc->osfaddr = DS137x_R_STATUS;
574331495Sian		sc->is_binary_counter = true;
575322473Sian		break;
576322473Sian	case TYPE_DS1388:
577322473Sian		sc->osfaddr = DS1388_R_STATUS;
578322473Sian		break;
579322473Sian	}
580322473Sian
581322473Sian	/*
582322473Sian	 * We have to wait until interrupts are enabled.  Sometimes I2C read
583322473Sian	 * and write only works when the interrupts are available.
584322473Sian	 */
585322473Sian	config_intrhook_oneshot(ds13rtc_start, sc);
586322473Sian
587322473Sian	return (0);
588322473Sian}
589322473Sian
590322473Sianstatic int
591322473Siands13rtc_detach(device_t dev)
592322473Sian{
593322473Sian
594322473Sian	clock_unregister(dev);
595322473Sian	return (0);
596322473Sian}
597322473Sian
598322473Sianstatic device_method_t ds13rtc_methods[] = {
599322473Sian	DEVMETHOD(device_probe,		ds13rtc_probe),
600322473Sian	DEVMETHOD(device_attach,	ds13rtc_attach),
601322473Sian	DEVMETHOD(device_detach,	ds13rtc_detach),
602322473Sian
603322473Sian	DEVMETHOD(clock_gettime,	ds13rtc_gettime),
604322473Sian	DEVMETHOD(clock_settime,	ds13rtc_settime),
605322473Sian
606322473Sian	DEVMETHOD_END
607322473Sian};
608322473Sian
609322473Sianstatic driver_t ds13rtc_driver = {
610322473Sian	"ds13rtc",
611322473Sian	ds13rtc_methods,
612322473Sian	sizeof(struct ds13rtc_softc),
613322473Sian};
614322473Sian
615322473Sianstatic devclass_t ds13rtc_devclass;
616322473Sian
617322473SianDRIVER_MODULE(ds13rtc, iicbus, ds13rtc_driver, ds13rtc_devclass, NULL, NULL);
618322473SianMODULE_VERSION(ds13rtc, 1);
619322473SianMODULE_DEPEND(ds13rtc, iicbus, IICBB_MINVER, IICBB_PREFVER, IICBB_MAXVER);
620