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