From nobody Sun Nov 14 12:34:23 2021 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 4BD79183C147; Sun, 14 Nov 2021 12:34:24 +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 4HsWwc0wkMz4c5s; Sun, 14 Nov 2021 12:34:24 +0000 (UTC) (envelope-from git@FreeBSD.org) 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 D0A7B2688E; Sun, 14 Nov 2021 12:34:23 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 1AECYNv1068472; Sun, 14 Nov 2021 12:34:23 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 1AECYNSO068471; Sun, 14 Nov 2021 12:34:23 GMT (envelope-from git) Date: Sun, 14 Nov 2021 12:34:23 GMT Message-Id: <202111141234.1AECYNSO068471@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: 328077bb8ff1 - main - pmic: rockchip: Split the rtc part in its own file 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: 328077bb8ff1a55d20ca7f8fdbb898e8c07bb057 Auto-Submitted: auto-generated X-ThisMailContainsUnwantedMimeParts: N The branch main has been updated by manu: URL: https://cgit.FreeBSD.org/src/commit/?id=328077bb8ff1a55d20ca7f8fdbb898e8c07bb057 commit 328077bb8ff1a55d20ca7f8fdbb898e8c07bb057 Author: Emmanuel Vadot AuthorDate: 2021-11-11 19:41:52 +0000 Commit: Emmanuel Vadot CommitDate: 2021-11-14 11:31:18 +0000 pmic: rockchip: Split the rtc part in its own file Even if for now all the RTC-related register are at the same offset don't use some hardcoded values for them but set them based on the PMIC type. No functional changes intended. --- sys/conf/files.arm64 | 1 + sys/dev/iicbus/pmic/rockchip/rk805.c | 204 ++++++------------------------- sys/dev/iicbus/pmic/rockchip/rk8xx.h | 109 +++++++++++++++++ sys/dev/iicbus/pmic/rockchip/rk8xx_rtc.c | 142 +++++++++++++++++++++ 4 files changed, 289 insertions(+), 167 deletions(-) diff --git a/sys/conf/files.arm64 b/sys/conf/files.arm64 index 1f344d0273b8..a3c325070469 100644 --- a/sys/conf/files.arm64 +++ b/sys/conf/files.arm64 @@ -541,6 +541,7 @@ arm64/rockchip/rk_dwc3.c optional fdt rk_dwc3 soc_rockchip_rk3399 arm64/rockchip/rk_i2c.c optional fdt rk_i2c soc_rockchip_rk3328 | fdt rk_i2c soc_rockchip_rk3399 arm64/rockchip/rk_i2s.c optional fdt sound soc_rockchip_rk3328 | fdt sound soc_rockchip_rk3399 dev/iicbus/pmic/rockchip/rk805.c optional fdt rk805 soc_rockchip_rk3328 | fdt rk805 soc_rockchip_rk3399 +dev/iicbus/pmic/rockchip/rk8xx_rtc.c optional fdt rk805 soc_rockchip_rk3328 | fdt rk805 soc_rockchip_rk3399 arm64/rockchip/rk_grf.c optional fdt soc_rockchip_rk3328 | fdt soc_rockchip_rk3399 arm64/rockchip/rk_pinctrl.c optional fdt rk_pinctrl soc_rockchip_rk3328 | fdt rk_pinctrl soc_rockchip_rk3399 arm64/rockchip/rk_gpio.c optional fdt rk_gpio soc_rockchip_rk3328 | fdt rk_gpio soc_rockchip_rk3399 diff --git a/sys/dev/iicbus/pmic/rockchip/rk805.c b/sys/dev/iicbus/pmic/rockchip/rk805.c index 76c8462e694e..ab4006ad63f9 100644 --- a/sys/dev/iicbus/pmic/rockchip/rk805.c +++ b/sys/dev/iicbus/pmic/rockchip/rk805.c @@ -50,6 +50,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include "clock_if.h" #include "regdev_if.h" @@ -59,55 +60,12 @@ MALLOC_DEFINE(M_RK805_REG, "RK805 regulator", "RK805 power regulator"); /* #define dprintf(sc, format, arg...) device_printf(sc->base_dev, "%s: " format, __func__, arg) */ #define dprintf(sc, format, arg...) -enum rk_pmic_type { - RK805 = 1, - RK808, -}; - static struct ofw_compat_data compat_data[] = { {"rockchip,rk805", RK805}, {"rockchip,rk808", RK808}, {NULL, 0} }; -struct rk8xx_regdef { - intptr_t id; - char *name; - uint8_t enable_reg; - uint8_t enable_mask; - uint8_t voltage_reg; - uint8_t voltage_mask; - int voltage_min; - int voltage_max; - int voltage_step; - int voltage_nstep; -}; - -struct rk8xx_reg_sc { - struct regnode *regnode; - device_t base_dev; - struct rk8xx_regdef *def; - phandle_t xref; - struct regnode_std_param *param; -}; - -struct reg_list { - TAILQ_ENTRY(reg_list) next; - struct rk8xx_reg_sc *reg; -}; - -struct rk8xx_softc { - device_t dev; - struct mtx mtx; - struct resource * res[1]; - void * intrcookie; - struct intr_config_hook intr_hook; - enum rk_pmic_type type; - - TAILQ_HEAD(, reg_list) regs; - int nregs; -}; - static int rk8xx_regnode_status(struct regnode *regnode, int *status); static int rk8xx_regnode_set_voltage(struct regnode *regnode, int min_uvolt, int max_uvolt, int *udelay); @@ -352,7 +310,7 @@ static struct rk8xx_regdef rk808_regdefs[] = { }, }; -static int +int rk8xx_read(device_t dev, uint8_t reg, uint8_t *data, uint8_t size) { int err; @@ -361,7 +319,7 @@ rk8xx_read(device_t dev, uint8_t reg, uint8_t *data, uint8_t size) return (err); } -static int +int rk8xx_write(device_t dev, uint8_t reg, uint8_t *data, uint8_t size) { @@ -748,128 +706,6 @@ rk8xx_start(void *pdev) config_intrhook_disestablish(&sc->intr_hook); } -static int -rk8xx_gettime(device_t dev, struct timespec *ts) -{ - struct bcd_clocktime bct; - uint8_t data[7]; - uint8_t ctrl; - int error; - - /* Latch the RTC value into the shadow registers and set 24hr mode */ - error = rk8xx_read(dev, RK805_RTC_CTRL, &ctrl, 1); - if (error != 0) - return (error); - - ctrl |= RK805_RTC_READSEL; - ctrl &= ~(RK805_RTC_AMPM_MODE | RK805_RTC_GET_TIME); - error = rk8xx_write(dev, RK805_RTC_CTRL, &ctrl, 1); - if (error != 0) - return (error); - ctrl |= RK805_RTC_GET_TIME; - error = rk8xx_write(dev, RK805_RTC_CTRL, &ctrl, 1); - if (error != 0) - return (error); - ctrl &= ~RK805_RTC_GET_TIME; - error = rk8xx_write(dev, RK805_RTC_CTRL, &ctrl, 1); - if (error != 0) - return (error); - - /* This works as long as RK805_RTC_SECS = 0 */ - error = rk8xx_read(dev, RK805_RTC_SECS, data, 7); - if (error != 0) - return (error); - - /* - * If the reported year is earlier than 2019, assume the clock is unset. - * This is both later than the reset value for the RK805 and RK808 as - * well as being prior to the current time. - */ - if (data[RK805_RTC_YEARS] < 0x19) - return (EINVAL); - - memset(&bct, 0, sizeof(bct)); - bct.year = data[RK805_RTC_YEARS]; - bct.mon = data[RK805_RTC_MONTHS] & RK805_RTC_MONTHS_MASK; - bct.day = data[RK805_RTC_DAYS] & RK805_RTC_DAYS_MASK; - bct.hour = data[RK805_RTC_HOURS] & RK805_RTC_HOURS_MASK; - bct.min = data[RK805_RTC_MINUTES] & RK805_RTC_MINUTES_MASK; - bct.sec = data[RK805_RTC_SECS] & RK805_RTC_SECS_MASK; - bct.dow = data[RK805_RTC_WEEKS] & RK805_RTC_WEEKS_MASK; - /* The day of week is reported as 1-7 with 1 = Monday */ - if (bct.dow == 7) - bct.dow = 0; - bct.ispm = 0; - - if (bootverbose) - device_printf(dev, "Read RTC: %02x-%02x-%02x %02x:%02x:%02x\n", - bct.year, bct.mon, bct.day, bct.hour, bct.min, bct.sec); - - return (clock_bcd_to_ts(&bct, ts, false)); -} - -static int -rk8xx_settime(device_t dev, struct timespec *ts) -{ - struct bcd_clocktime bct; - uint8_t data[7]; - int error; - uint8_t ctrl; - - clock_ts_to_bcd(ts, &bct, false); - - /* This works as long as RK805_RTC_SECS = 0 */ - data[RK805_RTC_YEARS] = bct.year; - data[RK805_RTC_MONTHS] = bct.mon; - data[RK805_RTC_DAYS] = bct.day; - data[RK805_RTC_HOURS] = bct.hour; - data[RK805_RTC_MINUTES] = bct.min; - data[RK805_RTC_SECS] = bct.sec; - data[RK805_RTC_WEEKS] = bct.dow; - /* The day of week is reported as 1-7 with 1 = Monday */ - if (data[RK805_RTC_WEEKS] == 0) - data[RK805_RTC_WEEKS] = 7; - - error = rk8xx_read(dev, RK805_RTC_CTRL, &ctrl, 1); - if (error != 0) - return (error); - - ctrl |= RK805_RTC_CTRL_STOP; - ctrl &= ~RK805_RTC_AMPM_MODE; - error = rk8xx_write(dev, RK805_RTC_CTRL, &ctrl, 1); - if (error != 0) - return (error); - - error = rk8xx_write(dev, RK805_RTC_SECS, data, 7); - ctrl &= ~RK805_RTC_CTRL_STOP; - rk8xx_write(dev, RK805_RTC_CTRL, &ctrl, 1); - - return (error); -} - -static void -rk805_poweroff(void *arg, int howto) -{ - device_t dev = arg; - int error; - uint8_t val; - - if ((howto & RB_POWEROFF) == 0) - return; - - device_printf(dev, "Powering off...\n"); - error = rk805_read(dev, RK805_DEV_CTRL, &val, 1); - if (error == 0) { - val |= RK805_DEV_CTRL_OFF; - error = rk805_write(dev, RK805_DEV_CTRL, &val, 1); - - /* Wait a bit for the command to take effect. */ - if (error == 0) - DELAY(100); - } - device_printf(dev, "Power off failed\n"); -} - static int rk8xx_attach(device_t dev) { @@ -896,10 +732,44 @@ rk8xx_attach(device_t dev) case RK805: regdefs = rk805_regdefs; sc->nregs = nitems(rk805_regdefs); + sc->rtc_regs.secs = RK805_RTC_SECS; + sc->rtc_regs.secs_mask = RK805_RTC_SECS_MASK; + sc->rtc_regs.minutes = RK805_RTC_MINUTES; + sc->rtc_regs.minutes_mask = RK805_RTC_MINUTES_MASK; + sc->rtc_regs.hours = RK805_RTC_HOURS; + sc->rtc_regs.hours_mask = RK805_RTC_HOURS_MASK; + sc->rtc_regs.days = RK805_RTC_DAYS; + sc->rtc_regs.days_mask = RK805_RTC_DAYS_MASK; + sc->rtc_regs.months = RK805_RTC_MONTHS; + sc->rtc_regs.months_mask = RK805_RTC_MONTHS_MASK; + sc->rtc_regs.years = RK805_RTC_YEARS; + sc->rtc_regs.weeks = RK805_RTC_WEEKS_MASK; + sc->rtc_regs.ctrl = RK805_RTC_CTRL; + sc->rtc_regs.ctrl_stop_mask = RK805_RTC_CTRL_STOP; + sc->rtc_regs.ctrl_ampm_mask = RK805_RTC_AMPM_MODE; + sc->rtc_regs.ctrl_gettime_mask = RK805_RTC_GET_TIME; + sc->rtc_regs.ctrl_readsel_mask = RK805_RTC_READSEL; break; case RK808: regdefs = rk808_regdefs; sc->nregs = nitems(rk808_regdefs); + sc->rtc_regs.secs = RK808_RTC_SECS; + sc->rtc_regs.secs_mask = RK808_RTC_SECS_MASK; + sc->rtc_regs.minutes = RK808_RTC_MINUTES; + sc->rtc_regs.minutes_mask = RK808_RTC_MINUTES_MASK; + sc->rtc_regs.hours = RK808_RTC_HOURS; + sc->rtc_regs.hours_mask = RK808_RTC_HOURS_MASK; + sc->rtc_regs.days = RK808_RTC_DAYS; + sc->rtc_regs.days_mask = RK808_RTC_DAYS_MASK; + sc->rtc_regs.months = RK808_RTC_MONTHS; + sc->rtc_regs.months_mask = RK808_RTC_MONTHS_MASK; + sc->rtc_regs.years = RK808_RTC_YEARS; + sc->rtc_regs.weeks = RK808_RTC_WEEKS_MASK; + sc->rtc_regs.ctrl = RK808_RTC_CTRL; + sc->rtc_regs.ctrl_stop_mask = RK808_RTC_CTRL_STOP; + sc->rtc_regs.ctrl_ampm_mask = RK808_RTC_AMPM_MODE; + sc->rtc_regs.ctrl_gettime_mask = RK808_RTC_GET_TIME; + sc->rtc_regs.ctrl_readsel_mask = RK808_RTC_READSEL; break; default: device_printf(dev, "Unknown type %d\n", sc->type); diff --git a/sys/dev/iicbus/pmic/rockchip/rk8xx.h b/sys/dev/iicbus/pmic/rockchip/rk8xx.h new file mode 100644 index 000000000000..4351f8fe254c --- /dev/null +++ b/sys/dev/iicbus/pmic/rockchip/rk8xx.h @@ -0,0 +1,109 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2021 Emmanuel Vadot + * + * 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. + */ + +#ifndef _RK8XX_H_ +#define _RK8XX_H_ + +#include + +#include +#include + +enum rk_pmic_type { + RK805 = 1, + RK808, +}; + +struct rk8xx_regdef { + intptr_t id; + char *name; + uint8_t enable_reg; + uint8_t enable_mask; + uint8_t voltage_reg; + uint8_t voltage_mask; + int voltage_min; + int voltage_max; + int voltage_step; + int voltage_nstep; +}; + +struct rk8xx_reg_sc { + struct regnode *regnode; + device_t base_dev; + struct rk8xx_regdef *def; + phandle_t xref; + struct regnode_std_param *param; +}; + +struct reg_list { + TAILQ_ENTRY(reg_list) next; + struct rk8xx_reg_sc *reg; +}; + +struct rk8xx_rtc_reg { + uint8_t secs; + uint8_t secs_mask; + uint8_t minutes; + uint8_t minutes_mask; + uint8_t hours; + uint8_t hours_mask; + uint8_t days; + uint8_t days_mask; + uint8_t months; + uint8_t months_mask; + uint8_t years; + uint8_t weeks; + uint8_t weeks_mask; + uint8_t ctrl; + uint8_t ctrl_stop_mask; + uint8_t ctrl_ampm_mask; + uint8_t ctrl_gettime_mask; + uint8_t ctrl_readsel_mask; +}; + +struct rk8xx_softc { + device_t dev; + struct mtx mtx; + struct resource * res[1]; + void * intrcookie; + struct intr_config_hook intr_hook; + enum rk_pmic_type type; + + TAILQ_HEAD(, reg_list) regs; + int nregs; + + struct rk8xx_rtc_reg rtc_regs; +}; + +int rk8xx_read(device_t dev, uint8_t reg, uint8_t *data, uint8_t size); +int rk8xx_write(device_t dev, uint8_t reg, uint8_t *data, uint8_t size); + +/* rk8xx_rtc.c */ +int rk8xx_gettime(device_t dev, struct timespec *ts); +int rk8xx_settime(device_t dev, struct timespec *ts); + +#endif /* _RK8XX_H_ */ diff --git a/sys/dev/iicbus/pmic/rockchip/rk8xx_rtc.c b/sys/dev/iicbus/pmic/rockchip/rk8xx_rtc.c new file mode 100644 index 000000000000..2f755d16b164 --- /dev/null +++ b/sys/dev/iicbus/pmic/rockchip/rk8xx_rtc.c @@ -0,0 +1,142 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2021 Emmanuel Vadot + * Copyright (c) 2021 Peter Jeremy + * + * 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 +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include + +#include + +int +rk8xx_gettime(device_t dev, struct timespec *ts) +{ + struct rk8xx_softc *sc; + struct bcd_clocktime bct; + uint8_t data[7]; + uint8_t ctrl; + int error; + + sc = device_get_softc(dev); + + /* Latch the RTC value into the shadow registers and set 24hr mode */ + error = rk8xx_read(dev, sc->rtc_regs.ctrl, &ctrl, 1); + if (error != 0) + return (error); + + ctrl |= sc->rtc_regs.ctrl_readsel_mask; + ctrl &= ~(sc->rtc_regs.ctrl_ampm_mask | sc->rtc_regs.ctrl_gettime_mask); + error = rk8xx_write(dev, sc->rtc_regs.ctrl, &ctrl, 1); + if (error != 0) + return (error); + ctrl |= sc->rtc_regs.ctrl_gettime_mask; + error = rk8xx_write(dev, sc->rtc_regs.ctrl, &ctrl, 1); + if (error != 0) + return (error); + ctrl &= ~sc->rtc_regs.ctrl_gettime_mask; + error = rk8xx_write(dev, sc->rtc_regs.ctrl, &ctrl, 1); + if (error != 0) + return (error); + + /* This works as long as sc->rtc_regs.secs = 0 */ + error = rk8xx_read(dev, sc->rtc_regs.secs, data, 7); + if (error != 0) + return (error); + + /* + * If the reported year is earlier than 2019, assume the clock is unset. + * This is both later than the reset value for the RK805 and RK808 as + * well as being prior to the current time. + */ + if (data[sc->rtc_regs.years] < 0x19) + return (EINVAL); + + memset(&bct, 0, sizeof(bct)); + bct.year = data[sc->rtc_regs.years]; + bct.mon = data[sc->rtc_regs.months] & sc->rtc_regs.months_mask; + bct.day = data[sc->rtc_regs.days] & sc->rtc_regs.days_mask; + bct.hour = data[sc->rtc_regs.hours] & sc->rtc_regs.hours_mask; + bct.min = data[sc->rtc_regs.minutes] & sc->rtc_regs.minutes_mask; + bct.sec = data[sc->rtc_regs.secs] & sc->rtc_regs.secs_mask; + bct.dow = data[sc->rtc_regs.weeks] & sc->rtc_regs.weeks_mask; + /* The day of week is reported as 1-7 with 1 = Monday */ + if (bct.dow == 7) + bct.dow = 0; + bct.ispm = 0; + + if (bootverbose) + device_printf(dev, "Read RTC: %02x-%02x-%02x %02x:%02x:%02x\n", + bct.year, bct.mon, bct.day, bct.hour, bct.min, bct.sec); + + return (clock_bcd_to_ts(&bct, ts, false)); +} + +int +rk8xx_settime(device_t dev, struct timespec *ts) +{ + struct rk8xx_softc *sc; + struct bcd_clocktime bct; + uint8_t data[7]; + int error; + uint8_t ctrl; + + sc = device_get_softc(dev); + + clock_ts_to_bcd(ts, &bct, false); + + /* This works as long as RK805_RTC_SECS = 0 */ + data[sc->rtc_regs.years] = bct.year; + data[sc->rtc_regs.months] = bct.mon; + data[sc->rtc_regs.days] = bct.day; + data[sc->rtc_regs.hours] = bct.hour; + data[sc->rtc_regs.minutes] = bct.min; + data[sc->rtc_regs.secs] = bct.sec; + data[sc->rtc_regs.weeks] = bct.dow; + /* The day of week is reported as 1-7 with 1 = Monday */ + if (data[sc->rtc_regs.weeks] == 0) + data[sc->rtc_regs.weeks] = 7; + + error = rk8xx_read(dev, sc->rtc_regs.ctrl, &ctrl, 1); + if (error != 0) + return (error); + + ctrl |= sc->rtc_regs.ctrl_stop_mask; + ctrl &= ~sc->rtc_regs.ctrl_ampm_mask; + error = rk8xx_write(dev, sc->rtc_regs.ctrl, &ctrl, 1); + if (error != 0) + return (error); + + error = rk8xx_write(dev, sc->rtc_regs.secs, data, 7); + ctrl &= ~sc->rtc_regs.ctrl_stop_mask; + rk8xx_write(dev, sc->rtc_regs.ctrl, &ctrl, 1); + + return (error); +}