From owner-svn-src-stable-11@freebsd.org Sat Mar 24 23:01:12 2018 Return-Path: Delivered-To: svn-src-stable-11@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 7A228F539F9; Sat, 24 Mar 2018 23:01:12 +0000 (UTC) (envelope-from ian@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 27277846CB; Sat, 24 Mar 2018 23:01:12 +0000 (UTC) (envelope-from ian@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 21DF515B55; Sat, 24 Mar 2018 23:01:12 +0000 (UTC) (envelope-from ian@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id w2ON1CSf023487; Sat, 24 Mar 2018 23:01:12 GMT (envelope-from ian@FreeBSD.org) Received: (from ian@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id w2ON1AiX023472; Sat, 24 Mar 2018 23:01:10 GMT (envelope-from ian@FreeBSD.org) Message-Id: <201803242301.w2ON1AiX023472@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: ian set sender to ian@FreeBSD.org using -f From: Ian Lepore Date: Sat, 24 Mar 2018 23:01:10 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org Subject: svn commit: r331503 - in stable/11/sys: conf dev/iicbus kern modules/i2c modules/i2c/ds1672 modules/i2c/rtc8583 sys x86/isa X-SVN-Group: stable-11 X-SVN-Commit-Author: ian X-SVN-Commit-Paths: in stable/11/sys: conf dev/iicbus kern modules/i2c modules/i2c/ds1672 modules/i2c/rtc8583 sys x86/isa X-SVN-Commit-Revision: 331503 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable-11@freebsd.org X-Mailman-Version: 2.1.25 Precedence: list List-Id: SVN commit messages for only the 11-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 24 Mar 2018 23:01:12 -0000 Author: ian Date: Sat Mar 24 23:01:10 2018 New Revision: 331503 URL: https://svnweb.freebsd.org/changeset/base/331503 Log: MFC r325233, r328956, r329170, r329172-r329173, r329224, r330403-r330407, r330411-r330412, r330416, r330430-r330431, r330433, r330528-r330529, r330767 r325233: [i2c/clock] add support for EPSON RTC-8583 RTC-8583 is time-of-day clock used in some SOHO routers. This clock has only 2 bits for year values, but thanks to user SRAM it's possible to save year value and keep it up to date via driver code. Tested on Planex_MZK-W300NAG (SoC is RT2880) Submitted by: Hiroki Mori Differential Revision: https://reviews.freebsd.org/D12833 r328956: Use const pointers for input data not modified by clock utility functions. r329170: Replace the existing print_ct() private debugging function with a set of three public functions to format and print the three major data structures used by realtime clock drivers (clocktime, bcd_clocktime, and timespec). r329172: Add a set of convenience routines for RTC drivers to use for debug output, and a debug.clock_show_io sysctl to control debugging output. r329173: Add a new sysctl, debug.clock_do_io, to allow manully triggering a one-shot read or write of all registered realtime clocks. In the read case, the values read are simply discarded. For writes, there's no alternative but to actually write the current system time to the device. r329224: Fix bad indentation. Whitespace only, no functional changes. Reported by: bde@ r330403: Add calls to the new clock_dbgprint_xxx() functions. r330404: Add calls to the new clock_dbgprint_xxx() functions. r330405: Oops, fix a paste-o. r330406: Add calls to the new clock_dbgprint_xxx() functions. r330407: Add calls to the new clock_dbgprint_xxx() functions. Also, stop applying a local .5 second adjustment to the time, since that is now done by the code in subr_rtc.c. r330411: Convert to the new(ish) bcd_clocktime conversion functions, add calls to the new debug output functions, and when setting the clock, propagate the timespec nsecs to the 1/100ths register. r330412: Build iicbus/rtc8583 as a module. r330416: The year is stored in a single byte in sram, in binary format, as a count of years since the century, so strip the century out when converting to or from bcd_clocktime format (the conversion routines will infer century by pivoting on 70). r330430: Switch to the new bcd_clocktime conversion routines, and add calls to the new clock_dbgprint_xxx() functions. r330431: Switch to the new bcd_clocktime conversion routines, and add calls to the new clock_dbgprint_xxx() functions. r330433: Switch to the new bcd_clocktime conversion routines, and add calls to the new clock_dbgprint_xxx() functions. r330528: Fix a paste-o that broke the build. There is no softc pointer here, just use the dev arg. Reported by: Jonathan Looney Pointy hat: ian@ r330529: Build the ds1672 driver as a module. Add a detach() to unregister the rtc. r330767: Convert atrtc the new style rtc debugging output. Remove the db show command handler which provided much the same information. Removing the possibility of accessing the hardware regs from the debugger context paves the way for simplifying the locking code in the driver. Added: stable/11/sys/dev/iicbus/rtc8583.c - copied, changed from r325233, head/sys/dev/iicbus/rtc8583.c stable/11/sys/modules/i2c/ds1672/ - copied from r330529, head/sys/modules/i2c/ds1672/ stable/11/sys/modules/i2c/rtc8583/ - copied from r330412, head/sys/modules/i2c/rtc8583/ Modified: stable/11/sys/conf/files stable/11/sys/dev/iicbus/ds1307.c stable/11/sys/dev/iicbus/ds13rtc.c stable/11/sys/dev/iicbus/ds1672.c stable/11/sys/dev/iicbus/ds3231.c stable/11/sys/dev/iicbus/isl12xx.c stable/11/sys/dev/iicbus/nxprtc.c stable/11/sys/dev/iicbus/s35390a.c stable/11/sys/kern/subr_clock.c stable/11/sys/kern/subr_fattime.c stable/11/sys/kern/subr_rtc.c stable/11/sys/modules/i2c/Makefile stable/11/sys/sys/clock.h stable/11/sys/x86/isa/atrtc.c Directory Properties: stable/11/ (props changed) Modified: stable/11/sys/conf/files ============================================================================== --- stable/11/sys/conf/files Sat Mar 24 22:50:59 2018 (r331502) +++ stable/11/sys/conf/files Sat Mar 24 23:01:10 2018 (r331503) @@ -1768,6 +1768,7 @@ dev/iicbus/ds1307.c optional ds1307 dev/iicbus/ds13rtc.c optional ds13rtc | ds133x | ds1374 dev/iicbus/ds1672.c optional ds1672 dev/iicbus/ds3231.c optional ds3231 +dev/iicbus/rtc8583.c optional rtc8583 dev/iicbus/icee.c optional icee dev/iicbus/if_ic.c optional ic dev/iicbus/iic.c optional iic Modified: stable/11/sys/dev/iicbus/ds1307.c ============================================================================== --- stable/11/sys/dev/iicbus/ds1307.c Sat Mar 24 22:50:59 2018 (r331502) +++ stable/11/sys/dev/iicbus/ds1307.c Sat Mar 24 23:01:10 2018 (r331503) @@ -359,6 +359,7 @@ ds1307_gettime(device_t dev, struct timespec *ts) bct.mon = data[DS1307_MONTH] & DS1307_MONTH_MASK; bct.year = data[DS1307_YEAR] & DS1307_YEAR_MASK; + clock_dbgprint_bcd(sc->sc_dev, CLOCK_DBG_READ, &bct); return (clock_bcd_to_ts(&bct, ts, sc->sc_use_ampm)); } @@ -379,6 +380,7 @@ ds1307_settime(device_t dev, struct timespec *ts) */ ts->tv_sec -= utc_offset(); clock_ts_to_bcd(ts, &bct, sc->sc_use_ampm); + clock_dbgprint_bcd(sc->sc_dev, CLOCK_DBG_WRITE, &bct); /* If the chip is in AM/PM mode, adjust hour and set flags as needed. */ if (sc->sc_use_ampm) { Modified: stable/11/sys/dev/iicbus/ds13rtc.c ============================================================================== --- stable/11/sys/dev/iicbus/ds13rtc.c Sat Mar 24 22:50:59 2018 (r331502) +++ stable/11/sys/dev/iicbus/ds13rtc.c Sat Mar 24 23:01:10 2018 (r331503) @@ -395,6 +395,7 @@ ds13rtc_gettime(device_t dev, struct timespec *ts) if (sc->use_century) bct.year += (tregs.month & DS13xx_B_MONTH_CENTURY) ? 0x100 : 0; + clock_dbgprint_bcd(sc->dev, CLOCK_DBG_READ, &bct); err = clock_bcd_to_ts(&bct, ts, sc->use_ampm); return (err); @@ -422,6 +423,7 @@ ds13rtc_settime(device_t dev, struct timespec *ts) return (write_timeword(sc, ts->tv_sec)); clock_ts_to_bcd(ts, &bct, sc->use_ampm); + clock_dbgprint_bcd(sc->dev, CLOCK_DBG_WRITE, &bct); /* If the chip is in AMPM mode deal with the PM flag. */ pmflags = 0; Modified: stable/11/sys/dev/iicbus/ds1672.c ============================================================================== --- stable/11/sys/dev/iicbus/ds1672.c Sat Mar 24 22:50:59 2018 (r331502) +++ stable/11/sys/dev/iicbus/ds1672.c Sat Mar 24 23:01:10 2018 (r331503) @@ -54,8 +54,6 @@ __FBSDID("$FreeBSD$"); #define DS1672_CTRL_EOSC (1 << 7) /* Stop/start flag. */ -#define NANOSEC 1000000000 - #define MAX_IIC_DATA_SIZE 4 struct ds1672_softc { @@ -120,6 +118,14 @@ ds1672_init(device_t dev) } static int +ds1672_detach(device_t dev) +{ + + clock_unregister(dev); + return (0); +} + +static int ds1672_attach(device_t dev) { struct ds1672_softc *sc = device_get_softc(dev); @@ -144,8 +150,9 @@ ds1672_gettime(device_t dev, struct timespec *ts) /* counter has seconds since epoch */ ts->tv_sec = (secs[3] << 24) | (secs[2] << 16) | (secs[1] << 8) | (secs[0] << 0); - ts->tv_nsec = NANOSEC / 2; + ts->tv_nsec = 0; } + clock_dbgprint_ts(dev, CLOCK_DBG_READ, ts); return (error); } @@ -159,12 +166,15 @@ ds1672_settime(device_t dev, struct timespec *ts) data[2] = (ts->tv_sec >> 16) & 0xff; data[3] = (ts->tv_sec >> 24) & 0xff; + ts->tv_nsec = 0; + clock_dbgprint_ts(dev, CLOCK_DBG_WRITE, ts); return (ds1672_write(dev, DS1672_COUNTER, data, 4)); } static device_method_t ds1672_methods[] = { DEVMETHOD(device_probe, ds1672_probe), DEVMETHOD(device_attach, ds1672_attach), + DEVMETHOD(device_detach, ds1672_detach), DEVMETHOD(clock_gettime, ds1672_gettime), DEVMETHOD(clock_settime, ds1672_settime), Modified: stable/11/sys/dev/iicbus/ds3231.c ============================================================================== --- stable/11/sys/dev/iicbus/ds3231.c Sat Mar 24 22:50:59 2018 (r331502) +++ stable/11/sys/dev/iicbus/ds3231.c Sat Mar 24 23:01:10 2018 (r331503) @@ -377,7 +377,7 @@ ds3231_attach(device_t dev) sc->sc_dev = dev; sc->sc_addr = iicbus_get_addr(dev); sc->sc_last_c = -1; - sc->sc_year0 = 1900; + sc->sc_year0 = 0; sc->enum_hook.ich_func = ds3231_start; sc->enum_hook.ich_arg = dev; @@ -477,7 +477,7 @@ static int ds3231_gettime(device_t dev, struct timespec *ts) { int c, error; - struct clocktime ct; + struct bcd_clocktime bct; struct ds3231_softc *sc; uint8_t data[7], hourmask; @@ -505,13 +505,14 @@ ds3231_gettime(device_t dev, struct timespec *ts) } else hourmask = DS3231_HOUR_MASK_24HR; - ct.nsec = 0; - ct.sec = FROMBCD(data[DS3231_SECS] & DS3231_SECS_MASK); - ct.min = FROMBCD(data[DS3231_MINS] & DS3231_MINS_MASK); - ct.hour = FROMBCD(data[DS3231_HOUR] & hourmask); - ct.day = FROMBCD(data[DS3231_DATE] & DS3231_DATE_MASK); - ct.mon = FROMBCD(data[DS3231_MONTH] & DS3231_MONTH_MASK); - ct.year = FROMBCD(data[DS3231_YEAR] & DS3231_YEAR_MASK); + bct.nsec = 0; + bct.sec = data[DS3231_SECS] & DS3231_SECS_MASK; + bct.min = data[DS3231_MINS] & DS3231_MINS_MASK; + bct.hour = data[DS3231_HOUR] & hourmask; + bct.day = data[DS3231_DATE] & DS3231_DATE_MASK; + bct.mon = data[DS3231_MONTH] & DS3231_MONTH_MASK; + bct.year = data[DS3231_YEAR] & DS3231_YEAR_MASK; + bct.ispm = data[DS3231_HOUR] & DS3231_HOUR_IS_PM; /* * If the century flag has toggled since we last saw it, there has been @@ -522,29 +523,20 @@ ds3231_gettime(device_t dev, struct timespec *ts) if (sc->sc_last_c == -1) sc->sc_last_c = c; else if (c != sc->sc_last_c) { - sc->sc_year0 += 100; + sc->sc_year0 += 0x100; sc->sc_last_c = c; } - ct.year += sc->sc_year0; - if (ct.year < POSIX_BASE_YEAR) - ct.year += 100; /* assume [1970, 2069] */ + bct.year |= sc->sc_year0; - /* If running in AM/PM mode, deal with it. */ - if (sc->sc_use_ampm) { - if (ct.hour == 12) - ct.hour = 0; - if (data[DS3231_HOUR] & DS3231_HOUR_IS_PM) - ct.hour += 12; - } - - return (clock_ct_to_ts(&ct, ts)); + clock_dbgprint_bcd(sc->sc_dev, CLOCK_DBG_READ, &bct); + return (clock_bcd_to_ts(&bct, ts, sc->sc_use_ampm)); } static int ds3231_settime(device_t dev, struct timespec *ts) { int error; - struct clocktime ct; + struct bcd_clocktime bct; struct ds3231_softc *sc; uint8_t data[7]; uint8_t pmflags; @@ -556,27 +548,24 @@ ds3231_settime(device_t dev, struct timespec *ts) * disables utc adjustment, so apply that ourselves. */ ts->tv_sec -= utc_offset(); - clock_ts_to_ct(ts, &ct); + clock_ts_to_bcd(ts, &bct, sc->sc_use_ampm); + clock_dbgprint_bcd(sc->sc_dev, CLOCK_DBG_WRITE, &bct); /* If the chip is in AM/PM mode, adjust hour and set flags as needed. */ if (sc->sc_use_ampm) { pmflags = DS3231_HOUR_USE_AMPM; - if (ct.hour >= 12) { - ct.hour -= 12; + if (bct.ispm) pmflags |= DS3231_HOUR_IS_PM; - } - if (ct.hour == 0) - ct.hour = 12; } else pmflags = 0; - data[DS3231_SECS] = TOBCD(ct.sec); - data[DS3231_MINS] = TOBCD(ct.min); - data[DS3231_HOUR] = TOBCD(ct.hour) | pmflags; - data[DS3231_DATE] = TOBCD(ct.day); - data[DS3231_WEEKDAY] = ct.dow + 1; - data[DS3231_MONTH] = TOBCD(ct.mon); - data[DS3231_YEAR] = TOBCD(ct.year % 100); + data[DS3231_SECS] = bct.sec; + data[DS3231_MINS] = bct.min; + data[DS3231_HOUR] = bct.hour | pmflags; + data[DS3231_DATE] = bct.day; + data[DS3231_WEEKDAY] = bct.dow + 1; + data[DS3231_MONTH] = bct.mon; + data[DS3231_YEAR] = bct.year & 0xff; if (sc->sc_last_c) data[DS3231_MONTH] |= DS3231_C_MASK; Modified: stable/11/sys/dev/iicbus/isl12xx.c ============================================================================== --- stable/11/sys/dev/iicbus/isl12xx.c Sat Mar 24 22:50:59 2018 (r331502) +++ stable/11/sys/dev/iicbus/isl12xx.c Sat Mar 24 23:01:10 2018 (r331503) @@ -233,7 +233,7 @@ static int isl12xx_gettime(device_t dev, struct timespec *ts) { struct isl12xx_softc *sc = device_get_softc(dev); - struct clocktime ct; + struct bcd_clocktime bct; struct time_regs tregs; int err; uint8_t hourmask, sreg; @@ -263,29 +263,24 @@ isl12xx_gettime(device_t dev, struct timespec *ts) hourmask = ISL12xx_12HR_MASK; } - ct.nsec = 0; - ct.sec = FROMBCD(tregs.sec); - ct.min = FROMBCD(tregs.min); - ct.hour = FROMBCD(tregs.hour & hourmask); - ct.day = FROMBCD(tregs.day); - ct.mon = FROMBCD(tregs.month); - ct.year = FROMBCD(tregs.year); + bct.nsec = 0; + bct.sec = tregs.sec; + bct.min = tregs.min; + bct.hour = tregs.hour & hourmask; + bct.day = tregs.day; + bct.mon = tregs.month; + bct.year = tregs.year; + bct.ispm = tregs.hour & ISL12XX_PM_FLAG; - if (sc->use_ampm) { - if (ct.hour == 12) - ct.hour = 0; - if (tregs.hour & ISL12XX_PM_FLAG) - ct.hour += 12; - } - - return (clock_ct_to_ts(&ct, ts)); + clock_dbgprint_bcd(sc->dev, CLOCK_DBG_READ, &bct); + return (clock_bcd_to_ts(&bct, ts, sc->use_ampm)); } static int isl12xx_settime(device_t dev, struct timespec *ts) { struct isl12xx_softc *sc = device_get_softc(dev); - struct clocktime ct; + struct bcd_clocktime bct; struct time_regs tregs; int err; uint8_t ampmflags, sreg; @@ -296,27 +291,21 @@ isl12xx_settime(device_t dev, struct timespec *ts) */ ts->tv_sec -= utc_offset(); ts->tv_nsec = 0; - clock_ts_to_ct(ts, &ct); + clock_ts_to_bcd(ts, &bct, sc->use_ampm); + clock_dbgprint_bcd(sc->dev, CLOCK_DBG_WRITE, &bct); - /* If the chip is in AM/PM mode, adjust hour and set flags as needed. */ - if (!sc->use_ampm) { + /* If the chip is in AM/PM mode, set flags as needed. */ + if (!sc->use_ampm) ampmflags = ISL12XX_24HR_FLAG; - } else { - ampmflags = 0; - if (ct.hour >= 12) { - ct.hour -= 12; - ampmflags |= ISL12XX_PM_FLAG; - } - if (ct.hour == 0) - ct.hour = 12; - } + else + ampmflags = bct.ispm ? ISL12XX_PM_FLAG : 0; - tregs.sec = TOBCD(ct.sec); - tregs.min = TOBCD(ct.min); - tregs.hour = TOBCD(ct.hour) | ampmflags; - tregs.day = TOBCD(ct.day); - tregs.month = TOBCD(ct.mon); - tregs.year = TOBCD(ct.year % 100); + tregs.sec = bct.sec; + tregs.min = bct.min; + tregs.hour = bct.hour | ampmflags; + tregs.day = bct.day; + tregs.month = bct.mon; + tregs.year = bct.year % 100; /* * To set the time we have to set the WRTC enable bit in the control Modified: stable/11/sys/dev/iicbus/nxprtc.c ============================================================================== --- stable/11/sys/dev/iicbus/nxprtc.c Sat Mar 24 22:50:59 2018 (r331502) +++ stable/11/sys/dev/iicbus/nxprtc.c Sat Mar 24 23:01:10 2018 (r331503) @@ -608,6 +608,7 @@ nxprtc_gettime(device_t dev, struct timespec *ts) sc->flags |= SC_F_CPOL; } + clock_dbgprint_bcd(sc->dev, CLOCK_DBG_READ, &bct); err = clock_bcd_to_ts(&bct, ts, sc->use_ampm); ts->tv_sec += utc_offset(); @@ -648,6 +649,7 @@ nxprtc_settime(device_t dev, struct timespec *ts) ts->tv_sec -= utc_offset(); ts->tv_nsec = 0; clock_ts_to_bcd(ts, &bct, sc->use_ampm); + clock_dbgprint_bcd(sc->dev, CLOCK_DBG_WRITE, &bct); /* On 8563 set the century based on the polarity seen when reading. */ cflag = 0; Copied and modified: stable/11/sys/dev/iicbus/rtc8583.c (from r325233, head/sys/dev/iicbus/rtc8583.c) ============================================================================== --- head/sys/dev/iicbus/rtc8583.c Tue Oct 31 12:15:00 2017 (r325233, copy source) +++ stable/11/sys/dev/iicbus/rtc8583.c Sat Mar 24 23:01:10 2018 (r331503) @@ -190,7 +190,7 @@ static int rtc8583_gettime(device_t dev, struct timespec *ts) { struct rtc8583_softc *sc; - struct clocktime ct; + struct bcd_clocktime bct; struct time_regs tregs; uint8_t y, ytmp, sreg; int err; @@ -227,42 +227,49 @@ rtc8583_gettime(device_t dev, struct timespec *ts) iicbus_release_bus(sc->busdev, sc->dev); } - ct.nsec = FROMBCD(tregs.msec) * 10 * 1000 * 1000; - ct.sec = FROMBCD(tregs.sec); - ct.min = FROMBCD(tregs.min); - ct.hour = FROMBCD(tregs.hour & 0x3f); - ct.day = FROMBCD(tregs.day & 0x3f); - ct.mon = FROMBCD(tregs.month & 0x1f); - ct.year = 2000 + sreg; + if (!validbcd(tregs.msec)) + return (EINVAL); - return (clock_ct_to_ts(&ct, ts)); + /* The 'msec' reg is actually 1/100ths, in bcd. */ + bct.nsec = bcd2bin(tregs.msec) * 10 * 1000 * 1000; + bct.sec = tregs.sec; + bct.min = tregs.min; + bct.hour = tregs.hour & 0x3f; + bct.day = tregs.day & 0x3f; + bct.mon = tregs.month & 0x1f; + bct.year = bin2bcd(sreg % 100); + + clock_dbgprint_bcd(sc->dev, CLOCK_DBG_READ, &bct); + return (clock_bcd_to_ts(&bct, ts, false)); } static int rtc8583_settime(device_t dev, struct timespec *ts) { struct rtc8583_softc *sc; - struct clocktime ct; + struct bcd_clocktime bct; struct time_regs tregs; uint8_t sreg; int err; sc = device_get_softc(dev); ts->tv_sec -= utc_offset(); - ts->tv_nsec = 0; - clock_ts_to_ct(ts, &ct); + clock_ts_to_bcd(ts, &bct, false); + clock_dbgprint_bcd(sc->dev, CLOCK_DBG_WRITE, &bct); - tregs.sec = TOBCD(ct.sec); - tregs.min = TOBCD(ct.min); - tregs.hour = TOBCD(ct.hour); - tregs.day = TOBCD(ct.day) | ((ct.year & 0x03) << 6); - tregs.month = TOBCD(ct.mon); + /* The 'msec' reg is actually 1/100ths, in bcd. */ + tregs.msec = bin2bcd(ts->tv_nsec / (10 * 1000 * 1000)); + tregs.sec = bct.sec; + tregs.min = bct.min; + tregs.hour = bct.hour; + tregs.day = bct.day | (bct.year & 0x03 << 6); + tregs.month = bct.mon; if ((err = iicbus_request_bus(sc->busdev, sc->dev, IIC_WAIT)) != 0) return (err); err = rtc8583_writeto(sc->dev, RTC8583_SC_REG, &tregs, sizeof(tregs), IIC_WAIT); - sreg = ct.year - 2000; + sreg = bcd2bin(bct.year & 0xff); /* save to year to sram */ rtc8583_write1(sc, RTC8583_USERSRAM_REG, sreg); iicbus_release_bus(sc->busdev, sc->dev); Modified: stable/11/sys/dev/iicbus/s35390a.c ============================================================================== --- stable/11/sys/dev/iicbus/s35390a.c Sat Mar 24 22:50:59 2018 (r331502) +++ stable/11/sys/dev/iicbus/s35390a.c Sat Mar 24 23:01:10 2018 (r331503) @@ -297,7 +297,7 @@ static int s390rtc_gettime(device_t dev, struct timespec *ts) { uint8_t bcd[S390_RT1_NBYTES]; - struct clocktime ct; + struct bcd_clocktime bct; int error; error = s390rtc_read(dev, S390_REALTIME1, bcd, S390_RT1_NBYTES); @@ -310,37 +310,39 @@ s390rtc_gettime(device_t dev, struct timespec *ts) /* * Convert the register values into something useable. */ - ct.nsec = 0; - ct.sec = FROMBCD(bcd[S390_RT1_SECOND]); - ct.min = FROMBCD(bcd[S390_RT1_MINUTE]); - ct.hour = FROMBCD(bcd[S390_RT1_HOUR] & 0x3f); - ct.day = FROMBCD(bcd[S390_RT1_DAY]); - ct.dow = bcd[S390_RT1_WDAY] & 0x07; - ct.mon = FROMBCD(bcd[S390_RT1_MONTH]); - ct.year = FROMBCD(bcd[S390_RT1_YEAR]) + 2000; + bct.nsec = 0; + bct.sec = bcd[S390_RT1_SECOND]; + bct.min = bcd[S390_RT1_MINUTE]; + bct.hour = bcd[S390_RT1_HOUR] & 0x3f; + bct.day = bcd[S390_RT1_DAY]; + bct.dow = bcd[S390_RT1_WDAY] & 0x07; + bct.mon = bcd[S390_RT1_MONTH]; + bct.year = bcd[S390_RT1_YEAR]; - return (clock_ct_to_ts(&ct, ts)); + clock_dbgprint_bcd(dev, CLOCK_DBG_READ, &bct); + return (clock_bcd_to_ts(&bct, ts, false)); } static int s390rtc_settime(device_t dev, struct timespec *ts) { uint8_t bcd[S390_RT1_NBYTES]; - struct clocktime ct; + struct bcd_clocktime bct; - clock_ts_to_ct(ts, &ct); + clock_ts_to_bcd(ts, &bct, false); + clock_dbgprint_bcd(dev, CLOCK_DBG_WRITE, &bct); /* * Convert our time representation into something the S-xx390 * can understand. */ - bcd[S390_RT1_SECOND] = TOBCD(ct.sec); - bcd[S390_RT1_MINUTE] = TOBCD(ct.min); - bcd[S390_RT1_HOUR] = TOBCD(ct.hour); - bcd[S390_RT1_DAY] = TOBCD(ct.day); - bcd[S390_RT1_WDAY] = ct.dow; - bcd[S390_RT1_MONTH] = TOBCD(ct.mon); - bcd[S390_RT1_YEAR] = TOBCD(ct.year % 100); + bcd[S390_RT1_SECOND] = bct.sec; + bcd[S390_RT1_MINUTE] = bct.min; + bcd[S390_RT1_HOUR] = bct.hour; + bcd[S390_RT1_DAY] = bct.day; + bcd[S390_RT1_WDAY] = bct.dow; + bcd[S390_RT1_MONTH] = bct.mon; + bcd[S390_RT1_YEAR] = bct.year & 0xff; return (s390rtc_write(dev, S390_REALTIME1, bcd, S390_RT1_NBYTES)); } Modified: stable/11/sys/kern/subr_clock.c ============================================================================== --- stable/11/sys/kern/subr_clock.c Sat Mar 24 22:50:59 2018 (r331502) +++ stable/11/sys/kern/subr_clock.c Sat Mar 24 23:01:10 2018 (r331503) @@ -108,6 +108,14 @@ static const int recent_base_year = 2017; static const int recent_base_days = 17167; /* + * Table to 'calculate' pow(10, 9 - nsdigits) via lookup of nsdigits. + * Before doing the lookup, the code asserts 0 <= nsdigits <= 9. + */ +static u_int nsdivisors[] = { + 1000000000, 100000000, 10000000, 1000000, 100000, 10000, 1000, 100, 10, 1 +}; + +/* * This inline avoids some unnecessary modulo operations * as compared with the usual macro: * ( ((year % 4) == 0 && @@ -131,23 +139,15 @@ leapyear(int year) return (rv); } -static void -print_ct(struct clocktime *ct) -{ - printf("[%04d-%02d-%02d %02d:%02d:%02d]", - ct->year, ct->mon, ct->day, - ct->hour, ct->min, ct->sec); -} - int -clock_ct_to_ts(struct clocktime *ct, struct timespec *ts) +clock_ct_to_ts(const struct clocktime *ct, struct timespec *ts) { int i, year, days; if (ct_debug) { - printf("ct_to_ts("); - print_ct(ct); - printf(")"); + printf("ct_to_ts(["); + clock_print_ct(ct, 9); + printf("])"); } /* @@ -200,7 +200,7 @@ clock_ct_to_ts(struct clocktime *ct, struct timespec * } int -clock_bcd_to_ts(struct bcd_clocktime *bct, struct timespec *ts, bool ampm) +clock_bcd_to_ts(const struct bcd_clocktime *bct, struct timespec *ts, bool ampm) { struct clocktime ct; int bcent, byear; @@ -249,7 +249,7 @@ clock_bcd_to_ts(struct bcd_clocktime *bct, struct time } void -clock_ts_to_ct(struct timespec *ts, struct clocktime *ct) +clock_ts_to_ct(const struct timespec *ts, struct clocktime *ct) { int i, year, days; time_t rsec; /* remainder seconds */ @@ -288,15 +288,15 @@ clock_ts_to_ct(struct timespec *ts, struct clocktime * ct->sec = rsec; ct->nsec = ts->tv_nsec; if (ct_debug) { - printf("ts_to_ct(%jd.%09ld) = ", + printf("ts_to_ct(%jd.%09ld) = [", (intmax_t)ts->tv_sec, ts->tv_nsec); - print_ct(ct); - printf("\n"); + clock_print_ct(ct, 9); + printf("]\n"); } } void -clock_ts_to_bcd(struct timespec *ts, struct bcd_clocktime *bct, bool ampm) +clock_ts_to_bcd(const struct timespec *ts, struct bcd_clocktime *bct, bool ampm) { struct clocktime ct; @@ -321,6 +321,51 @@ clock_ts_to_bcd(struct timespec *ts, struct bcd_clockt bct->sec = TOBCD(ct.sec); bct->dow = ct.dow; bct->nsec = ct.nsec; +} + +void +clock_print_bcd(const struct bcd_clocktime *bct, int nsdigits) +{ + + KASSERT(nsdigits >= 0 && nsdigits <= 9, ("bad nsdigits %d", nsdigits)); + + if (nsdigits > 0) { + printf("%4.4x-%2.2x-%2.2x %2.2x:%2.2x:%2.2x.%*.*ld", + bct->year, bct->mon, bct->day, + bct->hour, bct->min, bct->sec, + nsdigits, nsdigits, bct->nsec / nsdivisors[nsdigits]); + } else { + printf("%4.4x-%2.2x-%2.2x %2.2x:%2.2x:%2.2x", + bct->year, bct->mon, bct->day, + bct->hour, bct->min, bct->sec); + } +} + +void +clock_print_ct(const struct clocktime *ct, int nsdigits) +{ + + KASSERT(nsdigits >= 0 && nsdigits <= 9, ("bad nsdigits %d", nsdigits)); + + if (nsdigits > 0) { + printf("%04d-%02d-%02d %02d:%02d:%02d.%*.*ld", + ct->year, ct->mon, ct->day, + ct->hour, ct->min, ct->sec, + nsdigits, nsdigits, ct->nsec / nsdivisors[nsdigits]); + } else { + printf("%04d-%02d-%02d %02d:%02d:%02d", + ct->year, ct->mon, ct->day, + ct->hour, ct->min, ct->sec); + } +} + +void +clock_print_ts(const struct timespec *ts, int nsdigits) +{ + struct clocktime ct; + + clock_ts_to_ct(ts, &ct); + clock_print_ct(&ct, nsdigits); } int Modified: stable/11/sys/kern/subr_fattime.c ============================================================================== --- stable/11/sys/kern/subr_fattime.c Sat Mar 24 22:50:59 2018 (r331502) +++ stable/11/sys/kern/subr_fattime.c Sat Mar 24 23:01:10 2018 (r331503) @@ -135,7 +135,8 @@ static const struct { void -timespec2fattime(struct timespec *tsp, int utc, uint16_t *ddp, uint16_t *dtp, uint8_t *dhp) +timespec2fattime(const struct timespec *tsp, int utc, uint16_t *ddp, + uint16_t *dtp, uint8_t *dhp) { time_t t1; unsigned t2, l, m; @@ -215,7 +216,8 @@ static const uint16_t daytab[64] = { }; void -fattime2timespec(unsigned dd, unsigned dt, unsigned dh, int utc, struct timespec *tsp) +fattime2timespec(unsigned dd, unsigned dt, unsigned dh, int utc, + struct timespec *tsp) { unsigned day; Modified: stable/11/sys/kern/subr_rtc.c ============================================================================== --- stable/11/sys/kern/subr_rtc.c Sat Mar 24 22:50:59 2018 (r331502) +++ stable/11/sys/kern/subr_rtc.c Sat Mar 24 23:01:10 2018 (r331503) @@ -76,6 +76,15 @@ __FBSDID("$FreeBSD$"); #include "clock_if.h" +static int show_io; +SYSCTL_INT(_debug, OID_AUTO, clock_show_io, CTLFLAG_RWTUN, &show_io, 0, + "Enable debug printing of RTC clock I/O; 1=reads, 2=writes, 3=both."); + +static int sysctl_clock_do_io(SYSCTL_HANDLER_ARGS); +SYSCTL_PROC(_debug, OID_AUTO, clock_do_io, CTLTYPE_INT | CTLFLAG_RW, + 0, 0, sysctl_clock_do_io, "I", + "Trigger one-time IO on RTC clocks; 1=read (and discard), 2=write"); + /* XXX: should be kern. now, it's no longer machdep. */ static int disable_rtc_set; SYSCTL_INT(_machdep, OID_AUTO, disable_rtc_set, CTLFLAG_RW, &disable_rtc_set, @@ -144,7 +153,61 @@ settime_task_func(void *arg, int pending) CLOCK_SETTIME(rtc->clockdev, &ts); } +static void +clock_dbgprint_hdr(device_t dev, int rw) +{ + struct timespec now; + + getnanotime(&now); + device_printf(dev, "%s at ", (rw & CLOCK_DBG_READ) ? "read " : "write"); + clock_print_ts(&now, 9); + printf(": "); +} + void +clock_dbgprint_bcd(device_t dev, int rw, const struct bcd_clocktime *bct) +{ + + if (show_io & rw) { + clock_dbgprint_hdr(dev, rw); + clock_print_bcd(bct, 9); + printf("\n"); + } +} + +void +clock_dbgprint_ct(device_t dev, int rw, const struct clocktime *ct) +{ + + if (show_io & rw) { + clock_dbgprint_hdr(dev, rw); + clock_print_ct(ct, 9); + printf("\n"); + } +} + +void +clock_dbgprint_err(device_t dev, int rw, int err) +{ + + if (show_io & rw) { + clock_dbgprint_hdr(dev, rw); + printf("error = %d\n", err); + } +} + +void +clock_dbgprint_ts(device_t dev, int rw, const struct timespec *ts) +{ + + if (show_io & rw) { + clock_dbgprint_hdr(dev, rw); + clock_print_ts(ts, 9); + printf("\n"); + } +} + +void clock_register_flags(device_t clockdev, long resolution, int flags) { struct rtc_instance *rtc, *newrtc; @@ -203,7 +266,7 @@ clock_unregister(device_t clockdev) if (rtc != NULL) { taskqueue_cancel_timeout(taskqueue_thread, &rtc->stask, NULL); taskqueue_drain_timeout(taskqueue_thread, &rtc->stask); - free(rtc, M_DEVBUF); + free(rtc, M_DEVBUF); } } @@ -222,6 +285,36 @@ clock_schedule(device_t clockdev, u_int offsetns) sx_xunlock(&rtc_list_lock); } +static int +read_clocks(struct timespec *ts, bool debug_read) +{ + struct rtc_instance *rtc; + int error; + + error = ENXIO; + sx_xlock(&rtc_list_lock); + LIST_FOREACH(rtc, &rtc_list, rtc_entries) { + if ((error = CLOCK_GETTIME(rtc->clockdev, ts)) != 0) + continue; + if (ts->tv_sec < 0 || ts->tv_nsec < 0) { + error = EINVAL; + continue; + } + if (!(rtc->flags & CLOCKF_GETTIME_NO_ADJ)) { + timespecadd(ts, &rtc->resadj); + ts->tv_sec += utc_offset(); + } + if (!debug_read) { + if (bootverbose) + device_printf(rtc->clockdev, + "providing initial system time\n"); + break; + } + } + sx_xunlock(&rtc_list_lock); + return (error); +} + /* * Initialize the system time. Must be called from a context which does not * restrict any locking or sleeping that clock drivers may need to do. @@ -238,28 +331,9 @@ void inittodr(time_t base) { struct timespec ts; - struct rtc_instance *rtc; int error; - error = ENXIO; - sx_xlock(&rtc_list_lock); - LIST_FOREACH(rtc, &rtc_list, rtc_entries) { - if ((error = CLOCK_GETTIME(rtc->clockdev, &ts)) != 0) - continue; - if (ts.tv_sec < 0 || ts.tv_nsec < 0) { - error = EINVAL; - continue; - } - if (!(rtc->flags & CLOCKF_GETTIME_NO_ADJ)) { - timespecadd(&ts, &rtc->resadj); - ts.tv_sec += utc_offset(); - } - if (bootverbose) - device_printf(rtc->clockdev, - "providing initial system time\n"); - break; - } - sx_xunlock(&rtc_list_lock); + error = read_clocks(&ts, false); /* * Do not report errors from each clock; it is expected that some clocks @@ -321,4 +395,30 @@ resettodr(void) &rtc->stask, -sbt, 0, C_PREL(31)); } sx_xunlock(&rtc_list_lock); +} + +static int +sysctl_clock_do_io(SYSCTL_HANDLER_ARGS) +{ + struct timespec ts_discard; + int error, value; + + value = 0; + error = sysctl_handle_int(oidp, &value, 0, req); + if (error != 0 || req->newptr == NULL) + return (error); + + switch (value) { + case CLOCK_DBG_READ: + if (read_clocks(&ts_discard, true) == ENXIO) + printf("No registered RTC clocks\n"); + break; + case CLOCK_DBG_WRITE: + resettodr(); + break; + default: + return (EINVAL); + } + + return (0); } Modified: stable/11/sys/modules/i2c/Makefile ============================================================================== --- stable/11/sys/modules/i2c/Makefile Sat Mar 24 22:50:59 2018 (r331502) +++ stable/11/sys/modules/i2c/Makefile Sat Mar 24 23:01:10 2018 (r331503) @@ -5,6 +5,7 @@ SUBDIR = \ cyapa \ ds1307 \ ds13rtc \ + ds1672 \ ds3231 \ icee \ if_ic \ @@ -17,6 +18,7 @@ SUBDIR = \ jedec_dimm \ jedec_ts \ nxprtc \ + rtc8583 \ s35390a \ smb \ smbus \ Modified: stable/11/sys/sys/clock.h ============================================================================== --- stable/11/sys/sys/clock.h Sat Mar 24 22:50:59 2018 (r331502) +++ stable/11/sys/sys/clock.h Sat Mar 24 23:01:10 2018 (r331503) @@ -88,8 +88,8 @@ struct clocktime { long nsec; /* nano seconds */ }; -int clock_ct_to_ts(struct clocktime *, struct timespec *); -void clock_ts_to_ct(struct timespec *, struct clocktime *); +int clock_ct_to_ts(const struct clocktime *, struct timespec *); +void clock_ts_to_ct(const struct timespec *, struct clocktime *); /* * Structure to hold the values typically reported by time-of-day clocks, @@ -125,8 +125,8 @@ struct bcd_clocktime { bool ispm; /* true if hour represents pm time */ }; -int clock_bcd_to_ts(struct bcd_clocktime *, struct timespec *, bool ampm); -void clock_ts_to_bcd(struct timespec *, struct bcd_clocktime *, bool ampm); +int clock_bcd_to_ts(const struct bcd_clocktime *, struct timespec *, bool ampm); +void clock_ts_to_bcd(const struct timespec *, struct bcd_clocktime *, bool ampm); /* * Time-of-day clock functions and flags. These functions might sleep. @@ -177,8 +177,31 @@ void clock_unregister(device_t _clockdev); /* Traditional POSIX base year */ #define POSIX_BASE_YEAR 1970 -void timespec2fattime(struct timespec *tsp, int utc, u_int16_t *ddp, u_int16_t *dtp, u_int8_t *dhp); -void fattime2timespec(unsigned dd, unsigned dt, unsigned dh, int utc, struct timespec *tsp); +void timespec2fattime(const struct timespec *tsp, int utc, u_int16_t *ddp, + u_int16_t *dtp, u_int8_t *dhp); +void fattime2timespec(unsigned dd, unsigned dt, unsigned dh, int utc, + struct timespec *tsp); + +/* + * Print a [bcd_]clocktime or timespec, optionally with fractional seconds. The + * nsdig argument can range from 0-9, and specifies how many decimal digits to + * display for fractional seconds. + */ +void clock_print_bcd(const struct bcd_clocktime *bct, int nsdig); +void clock_print_ct(const struct clocktime *ct, int nsdig); +void clock_print_ts(const struct timespec *ts, int nsdig); + +/* + * Debugging helpers for RTC clock drivers. Print a [bcd_]clocktime or + * timespec, only if rtc clock debugging has been enabled. The rw argument is + * one of CLOCK_DBG_READ or CLOCK_DBG_WRITE. + */ +#define CLOCK_DBG_READ 0x01 +#define CLOCK_DBG_WRITE 0x02 +void clock_dbgprint_bcd(device_t dev, int rw, const struct bcd_clocktime *bct); +void clock_dbgprint_ct(device_t dev, int rw, const struct clocktime *ct); +void clock_dbgprint_err(device_t dev, int rw, int err); +void clock_dbgprint_ts(device_t dev, int rw, const struct timespec *ts); #endif /* _KERNEL */ Modified: stable/11/sys/x86/isa/atrtc.c ============================================================================== --- stable/11/sys/x86/isa/atrtc.c Sat Mar 24 22:50:59 2018 (r331502) +++ stable/11/sys/x86/isa/atrtc.c Sat Mar 24 23:01:10 2018 (r331503) @@ -316,6 +316,7 @@ atrtc_settime(device_t dev __unused, struct timespec * struct bcd_clocktime bct; clock_ts_to_bcd(ts, &bct, false); + clock_dbgprint_bcd(dev, CLOCK_DBG_WRITE, &bct); mtx_lock(&atrtc_time_lock); RTC_LOCK; @@ -383,6 +384,7 @@ atrtc_gettime(device_t dev, struct timespec *ts) /* dow is unused in timespec conversion and we have no nsec info. */ bct.dow = 0; bct.nsec = 0; + clock_dbgprint_bcd(dev, CLOCK_DBG_READ, &bct); return (clock_bcd_to_ts(&bct, ts, false)); } @@ -413,16 +415,3 @@ static devclass_t atrtc_devclass; DRIVER_MODULE(atrtc, isa, atrtc_driver, atrtc_devclass, 0, 0); DRIVER_MODULE(atrtc, acpi, atrtc_driver, atrtc_devclass, 0, 0); - -#include "opt_ddb.h" -#ifdef DDB -#include - -DB_SHOW_COMMAND(rtc, rtc) -{ - printf("%02x/%02x/%02x %02x:%02x:%02x, A = %02x, B = %02x, C = %02x\n", - rtcin(RTC_YEAR), rtcin(RTC_MONTH), rtcin(RTC_DAY), - rtcin(RTC_HRS), rtcin(RTC_MIN), rtcin(RTC_SEC), - rtcin(RTC_STATUSA), rtcin(RTC_STATUSB), rtcin(RTC_INTR)); -} -#endif /* DDB */