From nobody Tue Oct 3 07:56:42 2023 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4S09Bg0nTcz4vwY0; Tue, 3 Oct 2023 07:56:43 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4S09Bf6dHZz3Snt; Tue, 3 Oct 2023 07:56:42 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1696319802; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=i/tRPd02dgEIVtssDy/s3l6tcRW2zQfdtRGDIU+YdbM=; b=n1ss1dINS2vHG1/+S1Wt7VWpebkFAKWGNRT9LasDCffgFfFU3SoBRYA1esFmLevrmdxWb8 CfahC+okp4eMKvOFKVrhj+BH9GXdMpbweVVdO3aaef0II2tUlQZidFIDi1pFkArxvZot+4 P1NY2qIlg6duDJgooS7Sa8CqHp88/1ZUPmzxeDPP3ojeKTW21fS+TRq7TlZBxeX+fAVNdO o8zyAQ3qytT8MQXUIhjd+YwypQuJeL/U3iuKId/GMU9zK4jzOdm2EBKz2y1DcoJOeUfb/r xtaht33Hf2FsjLTHR75LNtiTXZdlICreeg5AyQtDvYgLmtY/m5w40Pf3U9xHBA== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1696319802; a=rsa-sha256; cv=none; b=X6T1v0sW5soMeEXZ63YtCUANe4K0xJtcEvyx1PgaGNMZJ6mg+D+xsBeQoz1FfGo49NVdh5 U0b+jH6LjwJmQS5fbigZxF8YA++/fRPlWOjNKvg+a3PI1/q3P3VHwt2Fk86eiAPSbvsTWi UtWKscDzlYFSFDSF0UjvPxnIdsx4Y/pJ4EQW8Jy6mXsdiC93+sZpmyhB3uLRaP6I6C+G38 nwCljbBCZ8OEKkAHGn6Q/K/aL7N7SxrOlrurdMkkJLpDhitf38hd3M3FYGUsQIRX56STH8 8EQhb7gxU59aOpa8zV/vu/lBvwAfYO/DJujXbT2q94cf08zdiuMyfhCSr9XxxA== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1696319802; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=i/tRPd02dgEIVtssDy/s3l6tcRW2zQfdtRGDIU+YdbM=; b=SATvkflyhDaW4NL21k3R3CEDe17n6HocU+7uWP1hjKLA2eKlekk8FzQ19vWvz9wKfHUqnM C7oUAc6MiLAopivOIPGLjNsiytS9zJ6ClZ/IzEgeXEq99LCHsTvBZAhG2v9RNwpOk386+A QRd1vbeOxsjuBMKfhSRQn2sJ7VMClV8+dlWSAWCSzZvmHXArp3ktTQjfjROATDQPzwLr07 fk/w7H1Tquzo+pvEhFJQjIRPaNyQO0JYXcJ+k3FIQpYCJYXjj/XX1JmQSJHu6x8jtCw6EJ lVryrW/++LmgAzi8nNpWPk8e6CA+sdG6clYHp/jZ1vhH6veZp04DEC0NTGNP5g== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4S09Bf5jk0zn49; Tue, 3 Oct 2023 07:56:42 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.17.1/8.17.1) with ESMTP id 3937ugRB035929; Tue, 3 Oct 2023 07:56:42 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.17.1/8.17.1/Submit) id 3937ugOX035926; Tue, 3 Oct 2023 07:56:42 GMT (envelope-from git) Date: Tue, 3 Oct 2023 07:56:42 GMT Message-Id: <202310030756.3937ugOX035926@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Emmanuel Vadot Subject: git: 1d6a6a524409 - main - i2c: Add Microcrystal RV3032 RTC driver List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-all@freebsd.org X-BeenThere: dev-commits-src-all@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: manu X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 1d6a6a524409662992ca96bc91ae69b2a2a5ff35 Auto-Submitted: auto-generated The branch main has been updated by manu: URL: https://cgit.FreeBSD.org/src/commit/?id=1d6a6a524409662992ca96bc91ae69b2a2a5ff35 commit 1d6a6a524409662992ca96bc91ae69b2a2a5ff35 Author: Emmanuel Vadot AuthorDate: 2023-09-27 07:58:52 +0000 Commit: Emmanuel Vadot CommitDate: 2023-10-03 07:56:20 +0000 i2c: Add Microcrystal RV3032 RTC driver This is a simple RTC driver for the rv3032 from Microcrystal. Just the basic functionality is implemented (no timer, alarm etc ..). Sponsored by: Beckhoff Automation GmbH & Co. KG Differential Revision: https://reviews.freebsd.org/D41995 --- sys/conf/files | 1 + sys/dev/iicbus/rtc/rv3032.c | 455 ++++++++++++++++++++++++++++++++++++++++ sys/modules/i2c/Makefile | 3 +- sys/modules/i2c/rv3032/Makefile | 13 ++ 4 files changed, 471 insertions(+), 1 deletion(-) diff --git a/sys/conf/files b/sys/conf/files index 7701efbaac25..5d5e8f30347c 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -1825,6 +1825,7 @@ dev/iicbus/rtc/isl12xx.c optional isl12xx dev/iicbus/rtc/nxprtc.c optional nxprtc | pcf8563 dev/iicbus/rtc/pcf85063.c optional pcf85063 iicbus fdt dev/iicbus/rtc/rtc8583.c optional rtc8583 +dev/iicbus/rtc/rv3032.c optional rv3032 iicbus fdt dev/iicbus/rtc/rx8803.c optional rx8803 iicbus fdt dev/iicbus/rtc/s35390a.c optional s35390a dev/iicbus/sensor/htu21.c optional htu21 diff --git a/sys/dev/iicbus/rtc/rv3032.c b/sys/dev/iicbus/rtc/rv3032.c new file mode 100644 index 000000000000..67805dcb7939 --- /dev/null +++ b/sys/dev/iicbus/rtc/rv3032.c @@ -0,0 +1,455 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2023 Beckhoff Automation GmbH & Co. KG + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include "opt_platform.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include "clock_if.h" +#include "iicbus_if.h" + +/* Date registers */ +#define RV3032_SECS_100TH 0x00 +#define RV3032_SECS 0x01 +#define RV3032_MINS 0x02 +#define RV3032_HOURS 0x03 +#define RV3032_WEEKDAY 0x04 +#define RV3032_DATE 0x05 +#define RV3032_MONTH 0x06 +#define RV3032_YEAR 0x07 + +/* Alarm registers */ +#define RV3032_ALARM_MINUTES 0x08 +#define RV3032_ALARM_HOURS 0x09 +#define RV3032_ALARM_DATE 0x0A + +/* Periodic countdown timer registers */ +#define RV3032_TIMER_VALUE0 0x0B +#define RV3032_TIMER_VALUE1 0x0C + +/* Status register */ +#define RV3032_STATUS 0x0D +#define RV3032_STATUS_VLF (1 << 0) /* Voltage Low Flag */ +#define RV3032_STATUS_PORF (1 << 1) /* Power On Reset Flag */ +#define RV3032_STATUS_EVF (1 << 2) /* External eVent Flag */ +#define RV3032_STATUS_AF (1 << 3) /* Alarm Flag */ +#define RV3032_STATUS_TF (1 << 4) /* periodic countdown Timer Flag */ +#define RV3032_STATUS_UF (1 << 5) /* periodic time Update Flag */ +#define RV3032_STATUS_TLF (1 << 6) /* Temperature Low Flag */ +#define RV3032_STATUS_THF (1 << 7) /* Temperature High Flag */ + +/* Temperature registers */ +#define RV3032_TEMP_LSB 0x0E +#define RV3032_TEMP_LSB_BSF (1 << 0) +#define RV3032_TEMP_LSB_CLKF (1 << 1) +#define RV3032_TEMP_LSB_EEBUSY (1 << 2) +#define RV3032_TEMP_LSB_EEF (1 << 3) +#define RV3032_TEMP_LSB_MASK (0xF0) +#define RV3032_TEMP_LSB_SHIFT 4 + +#define RV3032_TEMP_MSB 0x0F + +#define TEMP_DIV 16 +#define TEMP_C_TO_K 273 + +/* Control registers */ +#define RV3032_CTRL1 0x10 +#define RV3032_CTRL1_TD_MASK 0x3 /* Timer clock frequency */ +#define RV3032_CTRL1_TD_SHIFT 0 +#define RV3032_CTRL1_TD_4096 0 +#define RV3032_CTRL1_TD_64 1 +#define RV3032_CTRL1_TD_1 2 +#define RV3032_CTRL1_TD_1_60 3 +#define RV3032_CTRL1_EERD (1 << 2) /* EEPROM memory refresh disable bit */ +#define RV3032_CTRL1_TE (1 << 3) /* Periodic countdown timer enable bit */ +#define RV3032_CTRL1_USEL (1 << 4) /* Update interrupt select bit */ +#define RV3032_CTRL1_GP0 (1 << 5) /* General Purpose bit 0 */ + +#define RV3032_CTRL2 0x11 +#define RV3032_CTRL2_STOP (1 << 0) /* Stop bit */ +#define RV3032_CTRL2_GP1 (1 << 1) /* General Purpose bit 1 */ +#define RV3032_CTRL2_EIE (1 << 2) /* External event interrupt enable bit */ +#define RV3032_CTRL2_AIE (1 << 3) /* Alarm interrupt enable bit */ +#define RV3032_CTRL2_TIE (1 << 4) /* Periodic countdown timer interrupt enable bit */ +#define RV3032_CTRL2_UIE (1 << 5) /* Periodic time update interrupt enable bit */ +#define RV3032_CTRL2_CLKIE (1 << 6) /* Interrupt Controlled Clock Output Enable bit */ +#define RV3032_CTRL3 0x12 +#define RV3032_CTRL3_TLIE (1 << 0) /* Temperature Low Interrupt Enable bit */ +#define RV3032_CTRL3_THIE (1 << 1) /* Temperature High Interrupt Enable bit */ +#define RV3032_CTRL3_TLE (1 << 2) /* Temperature Low Enable bit */ +#define RV3032_CTRL3_THE (1 << 3) /* Temperature High Enable bit */ +#define RV3032_CTRL3_BSIE (1 << 4) /* Backup Switchover Interrupt Enable bit */ + +/* EEPROM registers */ +#define RV3032_EEPROM_ADDRESS 0x3D +#define RV3032_EEPROM_DATA 0x3E +#define RV3032_EEPROM_COMMAND 0x3F +#define RV3032_EEPROM_CMD_UPDATE 0x11 +#define RV3032_EEPROM_CMD_REFRESH 0x12 +#define RV3032_EEPROM_CMD_WRITE_ONE 0x21 +#define RV3032_EEPROM_CMD_READ_ONE 0x22 + +/* PMU register */ +#define RV3032_EEPROM_PMU 0xC0 +#define RV3032_PMU_TCM_MASK 0x3 +#define RV3032_PMU_TCM_SHIFT 0 +#define RV3032_PMU_TCM_OFF 0 +#define RV3032_PMU_TCM_175V 1 +#define RV3032_PMU_TCM_30V 2 +#define RV3032_PMU_TCM_45V 3 +#define RV3032_PMU_TCR_MASK 0x3 +#define RV3032_PMU_TCR_SHIFT 2 +#define RV3032_PMU_TCR_06K 0 +#define RV3032_PMU_TCR_2K 1 +#define RV3032_PMU_TCR_7K 2 +#define RV3032_PMU_TCR_12K 3 +#define RV3032_PMU_BSM_MASK 0x3 +#define RV3032_PMU_BSM_SHIFT 4 +#define RV3032_PMU_BSM_OFF 0 +#define RV3032_PMU_BSM_DSM 1 +#define RV3032_PMU_BSM_LSM 2 +#define RV3032_PMU_BSM_OFF2 3 +#define RV3032_PMU_NCLKE (1 << 6) + +struct rv3032_softc { + device_t dev; + device_t busdev; + struct intr_config_hook init_hook; +}; + +struct rv3032_timeregs { + uint8_t secs; + uint8_t mins; + uint8_t hours; + uint8_t weekday; + uint8_t date; + uint8_t month; + uint8_t year; +}; + +static struct ofw_compat_data compat_data[] = { + {"microcrystal,rv3032", 1}, + {NULL, 0}, +}; + +static int +rv3032_update_register(struct rv3032_softc *sc, uint8_t reg, uint8_t value, uint8_t mask) +{ + int rv; + uint8_t data; + + if ((rv = iicdev_readfrom(sc->dev, reg, &data, 1, IIC_WAIT)) != 0) + return (rv); + data &= mask; + data |= value; + if ((rv = iicdev_writeto(sc->dev, reg, &data, 1, IIC_WAIT)) != 0) + return (rv); + return (0); +} + +static int +rv3032_eeprom_wait(struct rv3032_softc *sc) +{ + int rv, timeout; + uint8_t data; + + for (timeout = 1000; timeout > 0; timeout--) { + if ((rv = iicdev_readfrom(sc->dev, RV3032_TEMP_LSB, &data, sizeof(data), IIC_WAIT)) != 0) + return (rv); + if ((data & RV3032_TEMP_LSB_EEBUSY) == 0) { + break; + } + } + if (timeout == 0) { + device_printf(sc->dev, "Timeout updating the eeprom\n"); + return (ETIMEDOUT); + } + /* Wait 1ms before allowing another eeprom access */ + DELAY(1000); + + return (0); +} + +static int +rv3032_eeprom_disable(struct rv3032_softc *sc) +{ + int rv; + + if ((rv = rv3032_update_register(sc, RV3032_CTRL1, RV3032_CTRL1_EERD, ~RV3032_CTRL1_EERD)) != 0) + return (rv); + /* Wait 1ms before checking EBUSY */ + DELAY(1000); + return (rv3032_eeprom_wait(sc)); +} + +static int +rv3032_eeprom_update(struct rv3032_softc *sc) +{ + int rv; + uint8_t data; + + data = RV3032_EEPROM_CMD_UPDATE; + if ((rv = iicdev_writeto(sc->dev, RV3032_EEPROM_COMMAND, &data, sizeof(data), IIC_WAIT)) != 0) + return (rv); + /* Wait 1ms before checking EBUSY */ + DELAY(1000); + return (rv3032_eeprom_wait(sc)); +} + +static int +rv3032_eeprom_enable(struct rv3032_softc *sc) +{ + int rv; + + /* Restore eeprom refresh */ + if ((rv = rv3032_update_register(sc, RV3032_CTRL1, 0, ~RV3032_CTRL1_EERD)) != 0) + return (rv); + DELAY(1000); + + return (0); +} + +static int +rv3032_update_cfg(struct rv3032_softc *sc) +{ + int rv; + + if ((rv = rv3032_eeprom_disable(sc)) != 0) + return (rv); + + /* Save configuration in eeprom and re-enable it */ + if ((rv = rv3032_eeprom_update(sc)) != 0) + return (rv); + return (rv3032_eeprom_enable(sc)); +} + +static int +rv3032_temp_read(struct rv3032_softc *sc, int *temp) +{ + int rv, temp2; + uint8_t data[2]; + + if ((rv = iicdev_readfrom(sc->dev, RV3032_TEMP_LSB, &data, sizeof(data), IIC_WAIT)) != 0) + return (rv); + + /* Wait for temp to be stable */ + *temp = (((data[0] & RV3032_TEMP_LSB_MASK) >> RV3032_TEMP_LSB_SHIFT) | + (data[1] << RV3032_TEMP_LSB_SHIFT)); + do { + temp2 = *temp; + *temp = (((data[0] & RV3032_TEMP_LSB_MASK) >> RV3032_TEMP_LSB_SHIFT) | + (data[1] << RV3032_TEMP_LSB_SHIFT)); + } while (temp2 != *temp); + *temp = (*temp / TEMP_DIV) + TEMP_C_TO_K; + return (0); +} + +static int +rv3032_temp_sysctl(SYSCTL_HANDLER_ARGS) +{ + int error, temp; + struct rv3032_softc *sc; + + sc = (struct rv3032_softc *)arg1; + if (rv3032_temp_read(sc, &temp) != 0) + return (EIO); + error = sysctl_handle_int(oidp, &temp, 0, req); + + return (error); +} + +static void +rv3032_init(void *arg) +{ + struct rv3032_softc *sc; + struct sysctl_ctx_list *ctx; + struct sysctl_oid *tree_node; + struct sysctl_oid_list *tree; + int rv; + + sc = (struct rv3032_softc*)arg; + config_intrhook_disestablish(&sc->init_hook); + + /* Set direct switching mode */ + rv3032_update_register(sc, + RV3032_EEPROM_PMU, + RV3032_PMU_BSM_DSM << RV3032_PMU_BSM_SHIFT, + RV3032_PMU_BSM_MASK); + if ((rv = rv3032_update_cfg(sc)) != 0) { + device_printf(sc->dev, "Cannot set to DSM mode (%d)\n", rv); + return; + } + + /* Register as clock source */ + clock_register_flags(sc->dev, 1000000, CLOCKF_SETTIME_NO_ADJ); + clock_schedule(sc->dev, 1); + + ctx = device_get_sysctl_ctx(sc->dev); + tree_node = device_get_sysctl_tree(sc->dev); + tree = SYSCTL_CHILDREN(tree_node); + SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "temperature", + CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, sc, 0, + rv3032_temp_sysctl, "IK0", "Current temperature"); + return; +} + +static int +rv3032_probe(device_t dev) +{ + + if (!ofw_bus_status_okay(dev)) + return (ENXIO); + if (ofw_bus_search_compatible(dev, compat_data)->ocd_data != 0) { + device_set_desc(dev, "Microcrystal RV3032"); + return (BUS_PROBE_DEFAULT); + } + return (ENXIO); +} + +static int +rv3032_attach(device_t dev) +{ + struct rv3032_softc *sc; + + sc = device_get_softc(dev); + sc->dev = dev; + sc->busdev = device_get_parent(sc->dev); + + sc->init_hook.ich_func = rv3032_init; + sc->init_hook.ich_arg = sc; + if (config_intrhook_establish(&sc->init_hook) != 0) + return (ENOMEM); + + return (0); +} + +static int +rv3032_detach(device_t dev) +{ + + clock_unregister(dev); + return (0); +} + +static int +rv3032_gettime(device_t dev, struct timespec *ts) +{ + struct rv3032_softc *sc; + struct rv3032_timeregs time_regs; + struct clocktime ct; + uint8_t status; + int rv; + + sc = device_get_softc(dev); + + if ((rv = iicdev_readfrom(sc->dev, RV3032_STATUS, &status, sizeof(status), IIC_WAIT)) != 0) + return (rv); + if (status & (RV3032_STATUS_PORF | RV3032_STATUS_VLF)) + return (EINVAL); + if ((rv = iicdev_readfrom(sc->dev, RV3032_SECS, &time_regs, sizeof(time_regs), IIC_WAIT)) != 0) + return (rv); + + bzero(&ct, sizeof(ct)); + ct.sec = FROMBCD(time_regs.secs & 0x7f); + ct.min = FROMBCD(time_regs.mins & 0x7f); + ct.hour = FROMBCD(time_regs.hours & 0x3f); + ct.day = FROMBCD(time_regs.date & 0x3f); + ct.mon = FROMBCD(time_regs.month & 0x1f) - 1; + ct.year = FROMBCD(time_regs.year) + 2000; + + return (clock_ct_to_ts(&ct, ts)); +} + +static int +rv3032_settime(device_t dev, struct timespec *ts) +{ + struct rv3032_softc *sc; + struct rv3032_timeregs time_regs; + struct clocktime ct; + uint8_t status; + int rv; + + sc = device_get_softc(dev); + if ((rv = iicdev_readfrom(sc->dev, RV3032_STATUS, &status, sizeof(status), IIC_WAIT)) != 0) + return (rv); + + clock_ts_to_ct(ts, &ct); + + time_regs.secs = TOBCD(ct.sec); + time_regs.mins = TOBCD(ct.min); + time_regs.hours = TOBCD(ct.hour); + time_regs.date = TOBCD(ct.day); + time_regs.month = TOBCD(ct.mon + 1); + time_regs.year = TOBCD(ct.year - 2000); + + if ((rv = iicdev_writeto(sc->dev, RV3032_SECS, &time_regs, sizeof(time_regs), IIC_WAIT)) != 0) + return (rv); + + /* Force a power on reset event so rv3032 reload the registers */ + status &= ~(RV3032_STATUS_PORF | RV3032_STATUS_VLF); + if ((rv = iicdev_writeto(sc->dev, RV3032_STATUS, &status, sizeof(status), IIC_WAIT)) != 0) + return (rv); + return (0); +} + +static device_method_t rv3032_methods[] = { + /* device_if methods */ + DEVMETHOD(device_probe, rv3032_probe), + DEVMETHOD(device_attach, rv3032_attach), + DEVMETHOD(device_detach, rv3032_detach), + + /* clock_if methods */ + DEVMETHOD(clock_gettime, rv3032_gettime), + DEVMETHOD(clock_settime, rv3032_settime), + + DEVMETHOD_END, +}; + +static driver_t rv3032_driver = { + "rv3032", + rv3032_methods, + sizeof(struct rv3032_softc), +}; + +DRIVER_MODULE(rv3032, iicbus, rv3032_driver, NULL, NULL); +MODULE_VERSION(rv3032, 1); +MODULE_DEPEND(rv3032, iicbus, IICBUS_MINVER, IICBUS_PREFVER, IICBUS_MAXVER); +IICBUS_FDT_PNP_INFO(compat_data); diff --git a/sys/modules/i2c/Makefile b/sys/modules/i2c/Makefile index b0b002b2309a..abbb390b0e07 100644 --- a/sys/modules/i2c/Makefile +++ b/sys/modules/i2c/Makefile @@ -28,7 +28,8 @@ SUBDIR = \ smbus \ .if !empty(OPT_FDT) -SUBDIR += rx8803 \ +SUBDIR += rv3032 \ + rx8803 \ tca64xx \ tmp461 .endif diff --git a/sys/modules/i2c/rv3032/Makefile b/sys/modules/i2c/rv3032/Makefile new file mode 100644 index 000000000000..7d3f8ac47aa6 --- /dev/null +++ b/sys/modules/i2c/rv3032/Makefile @@ -0,0 +1,13 @@ + +.PATH: ${SRCTOP}/sys/dev/iicbus/rtc +KMOD= rv3032 +SRCS= rv3032.c + +SRCS+= bus_if.h \ + clock_if.h \ + device_if.h \ + iicbus_if.h \ + opt_platform.h \ + ofw_bus_if.h + +.include