ds13rtc.c revision 331495
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 331495 2018-03-24 19:57:08Z 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{ 348322473Sian struct clocktime ct; 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 382322473Sian ct.sec = FROMBCD(tregs.sec & DS13xx_M_SECOND); 383322473Sian ct.min = FROMBCD(tregs.min & DS13xx_M_MINUTE); 384322473Sian ct.hour = FROMBCD(tregs.hour & hourmask); 385322473Sian ct.day = FROMBCD(tregs.day & DS13xx_M_DAY); 386322473Sian ct.mon = FROMBCD(tregs.month & DS13xx_M_MONTH); 387322473Sian ct.year = FROMBCD(tregs.year & DS13xx_M_YEAR); 388322473Sian ct.nsec = 0; 389322473Sian 390331495Sian if (sc->use_ampm) { 391322473Sian if (ct.hour == 12) 392322473Sian ct.hour = 0; 393322473Sian if (tregs.hour & DS13xx_B_HOUR_PM) 394322473Sian ct.hour += 12; 395322473Sian } 396322473Sian 397322473Sian /* 398322473Sian * If this chip has a century bit, honor it. Otherwise let 399322473Sian * clock_ct_to_ts() infer the century from the 2-digit year. 400322473Sian */ 401331495Sian if (sc->use_century) 402322473Sian ct.year += (tregs.month & DS13xx_B_MONTH_CENTURY) ? 2000 : 1900; 403322473Sian 404322473Sian err = clock_ct_to_ts(&ct, ts); 405322473Sian 406322473Sian return (err); 407322473Sian} 408322473Sian 409322473Sianstatic int 410322473Siands13rtc_settime(device_t dev, struct timespec *ts) 411322473Sian{ 412322473Sian struct clocktime ct; 413322473Sian struct time_regs tregs; 414322473Sian struct ds13rtc_softc *sc; 415322473Sian int err; 416331495Sian uint8_t cflag, statreg, pmflags; 417322473Sian 418322473Sian sc = device_get_softc(dev); 419322473Sian 420322473Sian /* 421322473Sian * We request a timespec with no resolution-adjustment. That also 422322473Sian * disables utc adjustment, so apply that ourselves. 423322473Sian */ 424322473Sian ts->tv_sec -= utc_offset(); 425322473Sian 426322473Sian /* If the chip counts time in binary, store tv_sec and we're done. */ 427331495Sian if (sc->is_binary_counter) 428322473Sian return (write_timeword(sc, ts->tv_sec)); 429322473Sian 430322473Sian clock_ts_to_ct(ts, &ct); 431322473Sian 432322473Sian /* If the chip is in AMPM mode deal with the PM flag. */ 433331495Sian pmflags = 0; 434331495Sian if (sc->use_ampm) { 435331495Sian pmflags = DS13xx_B_HOUR_AMPM; 436322473Sian if (ct.hour >= 12) { 437322473Sian ct.hour -= 12; 438331495Sian pmflags |= DS13xx_B_HOUR_PM; 439322473Sian } 440322473Sian if (ct.hour == 0) 441322473Sian ct.hour = 12; 442322473Sian } 443322473Sian 444322473Sian /* If the chip has a century bit, set it as needed. */ 445322473Sian cflag = 0; 446331495Sian if (sc->use_century) { 447322473Sian if (ct.year >= 2000) 448322473Sian cflag |= DS13xx_B_MONTH_CENTURY; 449322473Sian } 450322473Sian 451322473Sian tregs.sec = TOBCD(ct.sec); 452322473Sian tregs.min = TOBCD(ct.min); 453331495Sian tregs.hour = TOBCD(ct.hour) | pmflags; 454322473Sian tregs.day = TOBCD(ct.day); 455322473Sian tregs.month = TOBCD(ct.mon) | cflag; 456322473Sian tregs.year = TOBCD(ct.year % 100); 457322473Sian tregs.wday = ct.dow; 458322473Sian 459322473Sian /* 460322473Sian * Set the time. Reset the OSF bit if it is on and it is not part of 461322473Sian * the time registers (in which case writing time resets it). 462322473Sian */ 463322473Sian if ((err = write_timeregs(sc, &tregs)) != 0) 464322473Sian goto errout; 465322473Sian if (sc->osfaddr != sc->secaddr) { 466322473Sian if ((err = read_reg(sc, sc->osfaddr, &statreg)) != 0) 467322473Sian goto errout; 468322473Sian if (statreg & DS13xx_B_STATUS_OSF) { 469322473Sian statreg &= ~DS13xx_B_STATUS_OSF; 470322473Sian err = write_reg(sc, sc->osfaddr, statreg); 471322473Sian } 472322473Sian } 473322473Sian 474322473Sianerrout: 475322473Sian 476322473Sian if (err != 0) 477322473Sian device_printf(dev, "cannot update RTC time\n"); 478322473Sian 479322473Sian return (err); 480322473Sian} 481322473Sian 482322473Sianstatic int 483322473Siands13rtc_get_chiptype(device_t dev) 484322473Sian{ 485322473Sian#ifdef FDT 486322473Sian 487322473Sian return (ofw_bus_search_compatible(dev, compat_data)->ocd_data); 488322473Sian#else 489322473Sian ds13_compat_data *cdata; 490322473Sian const char *htype; 491322473Sian 492322473Sian /* 493322473Sian * We can only attach if provided a chiptype hint string. 494322473Sian */ 495322473Sian if (resource_string_value(device_get_name(dev), 496323467Sian device_get_unit(dev), "compatible", &htype) != 0) 497322473Sian return (TYPE_NONE); 498322473Sian 499322473Sian /* 500322473Sian * Loop through the ofw compat data comparing the hinted chip type to 501322473Sian * the compat strings. 502322473Sian */ 503322473Sian for (cdata = compat_data; cdata->ocd_str != NULL; ++cdata) { 504322473Sian if (strcmp(htype, cdata->ocd_str) == 0) 505322473Sian break; 506322473Sian } 507322473Sian return (cdata->ocd_data); 508322473Sian#endif 509322473Sian} 510322473Sian 511322473Sianstatic int 512322473Siands13rtc_probe(device_t dev) 513322473Sian{ 514322473Sian int chiptype, goodrv; 515322473Sian 516322473Sian#ifdef FDT 517322473Sian if (!ofw_bus_status_okay(dev)) 518322473Sian return (ENXIO); 519322473Sian goodrv = BUS_PROBE_GENERIC; 520322473Sian#else 521322473Sian goodrv = BUS_PROBE_NOWILDCARD; 522322473Sian#endif 523322473Sian 524322473Sian chiptype = ds13rtc_get_chiptype(dev); 525322473Sian if (chiptype == TYPE_NONE) 526322473Sian return (ENXIO); 527322473Sian 528322473Sian device_set_desc(dev, desc_strings[chiptype]); 529322473Sian return (goodrv); 530322473Sian} 531322473Sian 532322473Sianstatic int 533322473Siands13rtc_attach(device_t dev) 534322473Sian{ 535322473Sian struct ds13rtc_softc *sc; 536322473Sian 537322473Sian sc = device_get_softc(dev); 538322473Sian sc->dev = dev; 539322473Sian sc->busdev = device_get_parent(dev); 540322473Sian 541322473Sian /* 542322473Sian * We need to know what kind of chip we're driving. 543322473Sian */ 544322473Sian if ((sc->chiptype = ds13rtc_get_chiptype(dev)) == TYPE_NONE) { 545322473Sian device_printf(dev, "impossible: cannot determine chip type\n"); 546322473Sian return (ENXIO); 547322473Sian } 548322473Sian 549322473Sian /* The seconds register is in the same place on all except DS1388. */ 550322473Sian if (sc->chiptype == TYPE_DS1388) 551322473Sian sc->secaddr = DS1388_R_SECOND; 552322473Sian else 553322473Sian sc->secaddr = DS13xx_R_SECOND; 554322473Sian 555322473Sian /* 556322473Sian * The OSF/CH (osc failed/clock-halted) bit appears in different 557322473Sian * registers for different chip types. The DS1375 has no OSF indicator 558322473Sian * because it has no internal oscillator; we just point to an always- 559322473Sian * zero bit in the status register for that chip. 560322473Sian */ 561322473Sian switch (sc->chiptype) { 562322473Sian case TYPE_DS1307: 563322473Sian case TYPE_DS1308: 564322473Sian case TYPE_DS1338: 565322473Sian sc->osfaddr = DS13xx_R_SECOND; 566322473Sian break; 567322473Sian case TYPE_DS1337: 568322473Sian case TYPE_DS1339: 569322473Sian case TYPE_DS1341: 570322473Sian case TYPE_DS1342: 571322473Sian case TYPE_DS1375: 572322473Sian sc->osfaddr = DS133x_R_STATUS; 573331495Sian sc->use_century = true; 574322473Sian break; 575322473Sian case TYPE_DS1340: 576322473Sian sc->osfaddr = DS1340_R_STATUS; 577322473Sian break; 578322473Sian case TYPE_DS1371: 579322473Sian case TYPE_DS1372: 580322473Sian case TYPE_DS1374: 581322473Sian sc->osfaddr = DS137x_R_STATUS; 582331495Sian sc->is_binary_counter = true; 583322473Sian break; 584322473Sian case TYPE_DS1388: 585322473Sian sc->osfaddr = DS1388_R_STATUS; 586322473Sian break; 587322473Sian } 588322473Sian 589322473Sian /* 590322473Sian * We have to wait until interrupts are enabled. Sometimes I2C read 591322473Sian * and write only works when the interrupts are available. 592322473Sian */ 593322473Sian config_intrhook_oneshot(ds13rtc_start, sc); 594322473Sian 595322473Sian return (0); 596322473Sian} 597322473Sian 598322473Sianstatic int 599322473Siands13rtc_detach(device_t dev) 600322473Sian{ 601322473Sian 602322473Sian clock_unregister(dev); 603322473Sian return (0); 604322473Sian} 605322473Sian 606322473Sianstatic device_method_t ds13rtc_methods[] = { 607322473Sian DEVMETHOD(device_probe, ds13rtc_probe), 608322473Sian DEVMETHOD(device_attach, ds13rtc_attach), 609322473Sian DEVMETHOD(device_detach, ds13rtc_detach), 610322473Sian 611322473Sian DEVMETHOD(clock_gettime, ds13rtc_gettime), 612322473Sian DEVMETHOD(clock_settime, ds13rtc_settime), 613322473Sian 614322473Sian DEVMETHOD_END 615322473Sian}; 616322473Sian 617322473Sianstatic driver_t ds13rtc_driver = { 618322473Sian "ds13rtc", 619322473Sian ds13rtc_methods, 620322473Sian sizeof(struct ds13rtc_softc), 621322473Sian}; 622322473Sian 623322473Sianstatic devclass_t ds13rtc_devclass; 624322473Sian 625322473SianDRIVER_MODULE(ds13rtc, iicbus, ds13rtc_driver, ds13rtc_devclass, NULL, NULL); 626322473SianMODULE_VERSION(ds13rtc, 1); 627322473SianMODULE_DEPEND(ds13rtc, iicbus, IICBB_MINVER, IICBB_PREFVER, IICBB_MAXVER); 628