aboutsummaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorSøren Schmidt <sos@FreeBSD.org>2022-08-16 07:55:18 +0000
committerGanbold Tsagaankhuu <ganbold@FreeBSD.org>2022-08-16 07:55:18 +0000
commit66a3e513412a818ea802f994c08c2d307f439d81 (patch)
tree474f7fb29423f63718fa2e28274d1bf9651fd2a2 /sys
parentb80572fe3b3a93e0490c90901c7e5336f0210303 (diff)
downloadsrc-66a3e513412a818ea802f994c08c2d307f439d81.tar.gz
src-66a3e513412a818ea802f994c08c2d307f439d81.zip
Add RockChip rk809/rk817 pmic support to existing
RockChip pmic drivers. Reviewed by: manu Differential Revision: https://reviews.freebsd.org/D36149
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/iicbus/pmic/rockchip/rk817.c532
-rw-r--r--sys/dev/iicbus/pmic/rockchip/rk817reg.h121
-rw-r--r--sys/dev/iicbus/pmic/rockchip/rk8xx.c15
-rw-r--r--sys/dev/iicbus/pmic/rockchip/rk8xx.h6
-rw-r--r--sys/dev/iicbus/pmic/rockchip/rk8xx_regulators.c58
-rw-r--r--sys/dev/iicbus/pmic/rockchip/rk8xx_rtc.c14
6 files changed, 738 insertions, 8 deletions
diff --git a/sys/dev/iicbus/pmic/rockchip/rk817.c b/sys/dev/iicbus/pmic/rockchip/rk817.c
new file mode 100644
index 000000000000..54431aaa4735
--- /dev/null
+++ b/sys/dev/iicbus/pmic/rockchip/rk817.c
@@ -0,0 +1,532 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSS
+ *
+ * Copyright (c) 2021, 2022 Soren Schmidt <sos@deepcore.dk>
+ *
+ * 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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/clock.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/rman.h>
+#include <machine/bus.h>
+
+#include <dev/iicbus/iiconf.h>
+#include <dev/iicbus/iicbus.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <dev/iicbus/pmic/rockchip/rk817reg.h>
+#include <dev/iicbus/pmic/rockchip/rk8xx.h>
+
+
+static struct ofw_compat_data compat_data[] = {
+ {"rockchip,rk809", RK809},
+ {"rockchip,rk817", RK817},
+ {NULL, 0}
+};
+
+static struct rk8xx_regdef rk809_regdefs[] = {
+ {
+ .id = RK809_DCDC1,
+ .name = "DCDC_REG1",
+ .enable_reg = RK817_DCDC_EN,
+ .enable_mask = 0x11,
+ .voltage_reg = RK817_DCDC1_ON_VSEL,
+ .voltage_mask = 0x7f,
+ .voltage_min = 500000,
+ .voltage_max = 1487500,
+ .voltage_min2 = 1500000,
+ .voltage_max2 = 2400000,
+ .voltage_step = 12500,
+ .voltage_step2 = 100000,
+ .voltage_nstep = 177,
+ },
+ {
+ .id = RK809_DCDC2,
+ .name = "DCDC_REG2",
+ .enable_reg = RK817_DCDC_EN,
+ .enable_mask = 0x22,
+ .voltage_reg = RK817_DCDC2_ON_VSEL,
+ .voltage_mask = 0x7f,
+ .voltage_min = 500000,
+ .voltage_max = 1487500,
+ .voltage_min2 = 1500000,
+ .voltage_max2 = 2400000,
+ .voltage_step = 12500,
+ .voltage_step2 = 100000,
+ .voltage_nstep = 177,
+ },
+ {
+ .id = RK809_DCDC3,
+ .name = "DCDC_REG3",
+ .enable_reg = RK817_DCDC_EN,
+ .enable_mask = 0x44,
+ .voltage_reg = RK817_DCDC3_ON_VSEL,
+ .voltage_mask = 0x7f,
+ .voltage_min = 500000,
+ .voltage_max = 1487500,
+ .voltage_min2 = 1500000,
+ .voltage_max2 = 2400000,
+ .voltage_step = 12500,
+ .voltage_step2 = 100000,
+ .voltage_nstep = 177,
+ },
+ {
+ .id = RK809_DCDC4,
+ .name = "DCDC_REG4",
+ .enable_reg = RK817_DCDC_EN,
+ .enable_mask = 0x88,
+ .voltage_reg = RK817_DCDC4_ON_VSEL,
+ .voltage_mask = 0x7f,
+ .voltage_min = 500000,
+ .voltage_max = 1487500,
+ .voltage_min2 = 1500000,
+ .voltage_max2 = 3400000,
+ .voltage_step = 12500,
+ .voltage_step2 = 100000,
+ .voltage_nstep = 195,
+ },
+ {
+ .id = RK809_DCDC5,
+ .name = "DCDC_REG5",
+ .enable_reg = RK817_LDO_EN3,
+ .enable_mask = 0x22,
+ .voltage_reg = RK817_BOOST_ON_VSEL,
+ .voltage_mask = 0x07,
+ .voltage_min = 1600000, /* cheat is 1.5V */
+ .voltage_max = 3400000,
+ .voltage_min2 = 3500000,
+ .voltage_max2 = 3600000,
+ .voltage_step = 200000,
+ .voltage_step2 = 300000,
+ .voltage_nstep = 8,
+ },
+ {
+ .id = RK809_LDO1,
+ .name = "LDO_REG1",
+ .enable_reg = RK817_LDO_EN1,
+ .enable_mask = 0x11,
+ .voltage_reg = RK817_LDO1_ON_VSEL,
+ .voltage_mask = 0x7f,
+ .voltage_min = 600000,
+ .voltage_max = 3400000,
+ .voltage_step = 25000,
+ .voltage_nstep = 112,
+ },
+ {
+ .id = RK809_LDO2,
+ .name = "LDO_REG2",
+ .enable_reg = RK817_LDO_EN1,
+ .enable_mask = 0x22,
+ .voltage_reg = RK817_LDO2_ON_VSEL,
+ .voltage_mask = 0x7f,
+ .voltage_min = 600000,
+ .voltage_max = 3400000,
+ .voltage_step = 25000,
+ .voltage_nstep = 112,
+ },
+ {
+ .id = RK809_LDO3,
+ .name = "LDO_REG3",
+ .enable_reg = RK817_LDO_EN1,
+ .enable_mask = 0x44,
+ .voltage_reg = RK817_LDO3_ON_VSEL,
+ .voltage_mask = 0x7f,
+ .voltage_min = 600000,
+ .voltage_max = 3400000,
+ .voltage_step = 25000,
+ .voltage_nstep = 112,
+ },
+ {
+ .id = RK809_LDO4,
+ .name = "LDO_REG4",
+ .enable_reg = RK817_LDO_EN1,
+ .enable_mask = 0x88,
+ .voltage_reg = RK817_LDO4_ON_VSEL,
+ .voltage_mask = 0x7f,
+ .voltage_min = 600000,
+ .voltage_max = 3400000,
+ .voltage_step = 25000,
+ .voltage_nstep = 112,
+ },
+ {
+ .id = RK809_LDO5,
+ .name = "LDO_REG5",
+ .enable_reg = RK817_LDO_EN2,
+ .enable_mask = 0x11,
+ .voltage_reg = RK817_LDO5_ON_VSEL,
+ .voltage_mask = 0x7f,
+ .voltage_min = 600000,
+ .voltage_max = 3400000,
+ .voltage_step = 25000,
+ .voltage_nstep = 112,
+ },
+ {
+ .id = RK809_LDO6,
+ .name = "LDO_REG6",
+ .enable_reg = RK817_LDO_EN2,
+ .enable_mask = 0x22,
+ .voltage_reg = RK817_LDO6_ON_VSEL,
+ .voltage_mask = 0x7f,
+ .voltage_min = 600000,
+ .voltage_max = 3400000,
+ .voltage_step = 25000,
+ .voltage_nstep = 112,
+ },
+ {
+ .id = RK809_LDO7,
+ .name = "LDO_REG7",
+ .enable_reg = RK817_LDO_EN2,
+ .enable_mask = 0x44,
+ .voltage_reg = RK817_LDO7_ON_VSEL,
+ .voltage_mask = 0x7f,
+ .voltage_min = 600000,
+ .voltage_max = 3400000,
+ .voltage_step = 25000,
+ .voltage_nstep = 112,
+ },
+ {
+ .id = RK809_LDO8,
+ .name = "LDO_REG8",
+ .enable_reg = RK817_LDO_EN2,
+ .enable_mask = 0x88,
+ .voltage_reg = RK817_LDO8_ON_VSEL,
+ .voltage_mask = 0x7f,
+ .voltage_min = 600000,
+ .voltage_max = 3400000,
+ .voltage_step = 25000,
+ .voltage_nstep = 112,
+ },
+ {
+ .id = RK809_LDO9,
+ .name = "LDO_REG9",
+ .enable_reg = RK817_LDO_EN3,
+ .enable_mask = 0x11,
+ .voltage_reg = RK817_LDO9_ON_VSEL,
+ .voltage_mask = 0x7f,
+ .voltage_min = 600000,
+ .voltage_max = 3400000,
+ .voltage_step = 25000,
+ .voltage_nstep = 112,
+ },
+ {
+ .id = RK809_SWITCH1,
+ .name = "SWITCH_REG1",
+ .enable_reg = RK817_LDO_EN3,
+ .enable_mask = 0x44,
+ .voltage_min = 3300000,
+ .voltage_max = 3300000,
+ .voltage_nstep = 0,
+ },
+ {
+ .id = RK809_SWITCH2,
+ .name = "SWITCH_REG2",
+ .enable_reg = RK817_LDO_EN3,
+ .enable_mask = 0x88,
+ .voltage_min = 3300000,
+ .voltage_max = 3300000,
+ .voltage_nstep = 0,
+ },
+};
+
+static struct rk8xx_regdef rk817_regdefs[] = {
+ {
+ .id = RK817_DCDC1,
+ .name = "DCDC_REG1",
+ .enable_reg = RK817_DCDC_EN,
+ .enable_mask = 0x11,
+ .voltage_reg = RK817_DCDC1_ON_VSEL,
+ .voltage_mask = 0x7f,
+ .voltage_min = 500000,
+ .voltage_max = 1487500,
+ .voltage_min2 = 1500000,
+ .voltage_max2 = 2400000,
+ .voltage_step = 12500,
+ .voltage_step2 = 100000,
+ .voltage_nstep = 177,
+ },
+ {
+ .id = RK817_DCDC2,
+ .name = "DCDC_REG2",
+ .enable_reg = RK817_DCDC_EN,
+ .enable_mask = 0x22,
+ .voltage_reg = RK817_DCDC2_ON_VSEL,
+ .voltage_mask = 0x7f,
+ .voltage_min = 500000,
+ .voltage_max = 1487500,
+ .voltage_min2 = 1500000,
+ .voltage_max2 = 2400000,
+ .voltage_step = 12500,
+ .voltage_step2 = 100000,
+ .voltage_nstep = 177,
+ },
+ {
+ .id = RK817_DCDC3,
+ .name = "DCDC_REG3",
+ .enable_reg = RK817_DCDC_EN,
+ .enable_mask = 0x44,
+ .voltage_reg = RK817_DCDC3_ON_VSEL,
+ .voltage_mask = 0x7f,
+ .voltage_min = 500000,
+ .voltage_max = 1487500,
+ .voltage_min2 = 1500000,
+ .voltage_max2 = 2400000,
+ .voltage_step = 12500,
+ .voltage_step2 = 100000,
+ .voltage_nstep = 177,
+ },
+ {
+ .id = RK817_DCDC4,
+ .name = "DCDC_REG4",
+ .enable_reg = RK817_DCDC_EN,
+ .enable_mask = 0x88,
+ .voltage_reg = RK817_DCDC4_ON_VSEL,
+ .voltage_mask = 0x7f,
+ .voltage_min = 500000,
+ .voltage_max = 1487500,
+ .voltage_min2 = 1500000,
+ .voltage_max2 = 3400000,
+ .voltage_step = 12500,
+ .voltage_step2 = 100000,
+ .voltage_nstep = 195,
+ },
+ {
+ .id = RK817_LDO1,
+ .name = "LDO_REG1",
+ .enable_reg = RK817_LDO_EN1,
+ .enable_mask = 0x11,
+ .voltage_reg = RK817_LDO1_ON_VSEL,
+ .voltage_mask = 0x7f,
+ .voltage_min = 600000,
+ .voltage_max = 3400000,
+ .voltage_step = 25000,
+ .voltage_nstep = 112,
+ },
+ {
+ .id = RK817_LDO2,
+ .name = "LDO_REG2",
+ .enable_reg = RK817_LDO_EN1,
+ .enable_mask = 0x22,
+ .voltage_reg = RK817_LDO2_ON_VSEL,
+ .voltage_mask = 0x7f,
+ .voltage_min = 600000,
+ .voltage_max = 3400000,
+ .voltage_step = 25000,
+ .voltage_nstep = 112,
+ },
+ {
+ .id = RK817_LDO3,
+ .name = "LDO_REG3",
+ .enable_reg = RK817_LDO_EN1,
+ .enable_mask = 0x44,
+ .voltage_reg = RK817_LDO3_ON_VSEL,
+ .voltage_mask = 0x7f,
+ .voltage_min = 600000,
+ .voltage_max = 3400000,
+ .voltage_step = 25000,
+ .voltage_nstep = 112,
+ },
+ {
+ .id = RK817_LDO4,
+ .name = "LDO_REG4",
+ .enable_reg = RK817_LDO_EN1,
+ .enable_mask = 0x88,
+ .voltage_reg = RK817_LDO4_ON_VSEL,
+ .voltage_mask = 0x7f,
+ .voltage_min = 600000,
+ .voltage_max = 3400000,
+ .voltage_step = 25000,
+ .voltage_nstep = 112,
+ },
+ {
+ .id = RK817_LDO5,
+ .name = "LDO_REG5",
+ .enable_reg = RK817_LDO_EN2,
+ .enable_mask = 0x11,
+ .voltage_reg = RK817_LDO5_ON_VSEL,
+ .voltage_mask = 0x7f,
+ .voltage_min = 600000,
+ .voltage_max = 3400000,
+ .voltage_step = 25000,
+ .voltage_nstep = 112,
+ },
+ {
+ .id = RK817_LDO6,
+ .name = "LDO_REG6",
+ .enable_reg = RK817_LDO_EN2,
+ .enable_mask = 0x22,
+ .voltage_reg = RK817_LDO6_ON_VSEL,
+ .voltage_mask = 0x7f,
+ .voltage_min = 600000,
+ .voltage_max = 3400000,
+ .voltage_step = 25000,
+ .voltage_nstep = 112,
+ },
+ {
+ .id = RK817_LDO7,
+ .name = "LDO_REG7",
+ .enable_reg = RK817_LDO_EN2,
+ .enable_mask = 0x44,
+ .voltage_reg = RK817_LDO7_ON_VSEL,
+ .voltage_mask = 0x7f,
+ .voltage_min = 600000,
+ .voltage_max = 3400000,
+ .voltage_step = 25000,
+ .voltage_nstep = 112,
+ },
+ {
+ .id = RK817_LDO8,
+ .name = "LDO_REG8",
+ .enable_reg = RK817_LDO_EN2,
+ .enable_mask = 0x88,
+ .voltage_reg = RK817_LDO8_ON_VSEL,
+ .voltage_mask = 0x7f,
+ .voltage_min = 600000,
+ .voltage_max = 3400000,
+ .voltage_step = 25000,
+ .voltage_nstep = 112,
+ },
+ {
+ .id = RK817_LDO9,
+ .name = "LDO_REG9",
+ .enable_reg = RK817_LDO_EN3,
+ .enable_mask = 0x11,
+ .voltage_reg = RK817_LDO9_ON_VSEL,
+ .voltage_mask = 0x7f,
+ .voltage_min = 600000,
+ .voltage_max = 3400000,
+ .voltage_step = 25000,
+ .voltage_nstep = 112,
+ },
+ {
+ .id = RK817_BOOST,
+ .name = "BOOST",
+ .enable_reg = RK817_LDO_EN3,
+ .enable_mask = 0x22,
+ .voltage_reg = RK817_BOOST_ON_VSEL,
+ .voltage_mask = 0x07,
+ .voltage_min = 4700000,
+ .voltage_max = 5400000,
+ .voltage_step = 100000,
+ .voltage_nstep = 8,
+ },
+ {
+ .id = RK817_OTG_SWITCH,
+ .name = "OTG_SWITCH",
+ .enable_reg = RK817_LDO_EN3,
+ .enable_mask = 0x44,
+ .voltage_nstep = 0,
+ },
+};
+
+static int
+rk817_probe(device_t dev)
+{
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ switch (ofw_bus_search_compatible(dev, compat_data)->ocd_data) {
+ case RK809:
+ device_set_desc(dev, "RockChip RK809 PMIC");
+ break;
+ case RK817:
+ device_set_desc(dev, "RockChip RK817 PMIC");
+ break;
+ default:
+ return (ENXIO);
+ }
+
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+rk817_attach(device_t dev)
+{
+ struct rk8xx_softc *sc;
+
+ sc = device_get_softc(dev);
+ sc->dev = dev;
+
+ sc->type = ofw_bus_search_compatible(dev, compat_data)->ocd_data;
+ switch (sc->type) {
+ case RK809:
+ sc->regdefs = rk809_regdefs;
+ sc->nregs = nitems(rk809_regdefs);
+ break;
+ case RK817:
+ sc->regdefs = rk817_regdefs;
+ sc->nregs = nitems(rk817_regdefs);
+ break;
+ default:
+ device_printf(dev, "Unknown type %d\n", sc->type);
+ return (ENXIO);
+ }
+ sc->rtc_regs.secs = RK817_RTC_SECONDS;
+ sc->rtc_regs.secs_mask = RK817_RTC_SECONDS_MASK;
+ sc->rtc_regs.minutes = RK817_RTC_MINUTES;
+ sc->rtc_regs.minutes_mask = RK817_RTC_MINUTES_MASK;
+ sc->rtc_regs.hours = RK817_RTC_HOURS;
+ sc->rtc_regs.hours_mask = RK817_RTC_HOURS_MASK;
+ sc->rtc_regs.days = RK817_RTC_DAYS;
+ sc->rtc_regs.days_mask = RK817_RTC_DAYS_MASK;
+ sc->rtc_regs.months = RK817_RTC_MONTHS;
+ sc->rtc_regs.months_mask = RK817_RTC_MONTHS_MASK;
+ sc->rtc_regs.years = RK817_RTC_YEARS;
+ sc->rtc_regs.weeks = RK817_RTC_WEEKS_MASK;
+ sc->rtc_regs.ctrl = RK817_RTC_CTRL;
+ sc->rtc_regs.ctrl_stop_mask = RK817_RTC_CTRL_STOP;
+ sc->rtc_regs.ctrl_ampm_mask = RK817_RTC_AMPM_MODE;
+ sc->rtc_regs.ctrl_gettime_mask = RK817_RTC_GET_TIME;
+ sc->rtc_regs.ctrl_readsel_mask = RK817_RTC_READSEL;
+ sc->dev_ctrl.dev_ctrl_reg = RK817_SYS_CFG3;
+ sc->dev_ctrl.pwr_off_mask = RK817_SYS_CFG3_OFF;
+ sc->dev_ctrl.pwr_rst_mask = RK817_SYS_CFG3_RST;
+
+ return (rk8xx_attach(sc));
+}
+
+static device_method_t rk817_methods[] = {
+ DEVMETHOD(device_probe, rk817_probe),
+ DEVMETHOD(device_attach, rk817_attach),
+
+ DEVMETHOD_END
+};
+
+DEFINE_CLASS_1(rk817_pmu, rk817_driver, rk817_methods,
+ sizeof(struct rk8xx_softc), rk8xx_driver);
+
+EARLY_DRIVER_MODULE(rk817_pmu, iicbus, rk817_driver, 0, 0,
+ BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LAST);
+EARLY_DRIVER_MODULE(iicbus, rk817_pmu, iicbus_driver, 0, 0,
+ BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LAST);
+MODULE_DEPEND(rk817_pmu, iicbus, IICBUS_MINVER, IICBUS_PREFVER, IICBUS_MAXVER);
+MODULE_VERSION(rk817_pmu, 1);
diff --git a/sys/dev/iicbus/pmic/rockchip/rk817reg.h b/sys/dev/iicbus/pmic/rockchip/rk817reg.h
new file mode 100644
index 000000000000..607243826d04
--- /dev/null
+++ b/sys/dev/iicbus/pmic/rockchip/rk817reg.h
@@ -0,0 +1,121 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBS
+ *
+ * Copyright (c) 2021, 2022 Soren Schmidt <sos@deepcore.dk>
+ *
+ * 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 _RK817REG_H_
+#define _RK817REG_H_
+
+#define RK817_RTC_SECONDS 0x00
+#define RK817_RTC_SECONDS_MASK 0x7f
+#define RK817_RTC_MINUTES 0x01
+#define RK817_RTC_MINUTES_MASK 0x7f
+#define RK817_RTC_HOURS 0x02
+#define RK817_RTC_HOURS_MASK 0x3f
+#define RK817_RTC_DAYS 0x03
+#define RK817_RTC_DAYS_MASK 0x3f
+#define RK817_RTC_MONTHS 0x04
+#define RK817_RTC_MONTHS_MASK 0x1f
+#define RK817_RTC_YEARS 0x05
+#define RK817_RTC_WEEKS 0x06
+#define RK817_RTC_WEEKS_MASK 0x07
+#define RK817_ALARM_SECONDS 0x7
+#define RK817_ALARM_MINUTES 0x8
+#define RK817_ALARM_HOURS 0x9
+#define RK817_ALARM_DAYS 0xA
+#define RK817_ALARM_MONTHS 0xB
+#define RK817_ALARM_YEARS 0xC
+#define RK817_RTC_CTRL 0x0d
+#define RK817_RTC_CTRL_STOP (1 << 0)
+#define RK817_RTC_AMPM_MODE (1 << 3)
+#define RK817_RTC_GET_TIME (1 << 6)
+#define RK817_RTC_READSEL (1 << 7)
+#define RK817_RTC_STATUS 0x0e
+#define RK817_RTC_INT 0x0f
+#define RK817_RTC_COMP_LSB 0x10
+#define RK817_RTC_COMP_MSB 0x11
+
+#define RK817_DCDC_EN 0xb1
+#define RK817_LDO_EN1 0xb2
+#define RK817_LDO_EN2 0xb3
+#define RK817_LDO_EN3 0xb4
+#define RK817_DCDC1_ON_VSEL 0xbb
+#define RK817_DCDC2_ON_VSEL 0xbe
+#define RK817_DCDC3_ON_VSEL 0xc1
+#define RK817_DCDC4_ON_VSEL 0xc4
+#define RK817_LDO1_ON_VSEL 0xcc
+#define RK817_LDO2_ON_VSEL 0xce
+#define RK817_LDO3_ON_VSEL 0xd0
+#define RK817_LDO4_ON_VSEL 0xd2
+#define RK817_LDO5_ON_VSEL 0xd4
+#define RK817_LDO6_ON_VSEL 0xd6
+#define RK817_LDO7_ON_VSEL 0xd8
+#define RK817_LDO8_ON_VSEL 0xda
+#define RK817_LDO9_ON_VSEL 0xdc
+#define RK817_BOOST_ON_VSEL 0xde
+#define RK817_SYS_CFG3 0xf4
+#define RK817_SYS_CFG3_OFF (1 << 0)
+#define RK817_SYS_CFG3_SLP (1 << 1)
+#define RK817_SYS_CFG3_RST (1 << 2)
+
+enum rk809_regulator {
+ RK809_DCDC1 = 0,
+ RK809_DCDC2,
+ RK809_DCDC3,
+ RK809_DCDC4,
+ RK809_DCDC5,
+ RK809_LDO1,
+ RK809_LDO2,
+ RK809_LDO3,
+ RK809_LDO4,
+ RK809_LDO5,
+ RK809_LDO6,
+ RK809_LDO7,
+ RK809_LDO8,
+ RK809_LDO9,
+ RK809_SWITCH1,
+ RK809_SWITCH2,
+};
+
+enum rk817_regulator {
+ RK817_DCDC1 = 0,
+ RK817_DCDC2,
+ RK817_DCDC3,
+ RK817_DCDC4,
+ RK817_LDO1,
+ RK817_LDO2,
+ RK817_LDO3,
+ RK817_LDO4,
+ RK817_LDO5,
+ RK817_LDO6,
+ RK817_LDO7,
+ RK817_LDO8,
+ RK817_LDO9,
+ RK817_BOOST,
+ RK817_OTG_SWITCH,
+};
+#endif /* _RK817REG_H_ */
diff --git a/sys/dev/iicbus/pmic/rockchip/rk8xx.c b/sys/dev/iicbus/pmic/rockchip/rk8xx.c
index 0e6839ff0152..bf6e5833665a 100644
--- a/sys/dev/iicbus/pmic/rockchip/rk8xx.c
+++ b/sys/dev/iicbus/pmic/rockchip/rk8xx.c
@@ -115,7 +115,20 @@ rk8xx_poweroff(void *arg, int howto)
device_printf(sc->dev, "Powering off...\n");
error = rk8xx_read(sc->dev, sc->dev_ctrl.dev_ctrl_reg, &val, 1);
if (error == 0) {
- val |= sc->dev_ctrl.pwr_off_mask;
+ if (howto & RB_POWEROFF)
+ val |= sc->dev_ctrl.pwr_off_mask;
+ else if (howto & RB_POWERCYCLE) {
+ if (sc->type == RK809 || sc->type == RK817) {
+ if (bootverbose) {
+ device_printf(sc->dev,
+ "Powercycle PMIC\n");
+ }
+ val |= sc->dev_ctrl.pwr_rst_mask;;
+ } else {
+ /* Poweroff PMIC that can't powercycle */
+ val |= sc->dev_ctrl.pwr_off_mask;
+ }
+ }
error = rk8xx_write(sc->dev, sc->dev_ctrl.dev_ctrl_reg,
&val, 1);
diff --git a/sys/dev/iicbus/pmic/rockchip/rk8xx.h b/sys/dev/iicbus/pmic/rockchip/rk8xx.h
index 739b57c5f0bb..0edd0fd7fe24 100644
--- a/sys/dev/iicbus/pmic/rockchip/rk8xx.h
+++ b/sys/dev/iicbus/pmic/rockchip/rk8xx.h
@@ -36,6 +36,8 @@
enum rk_pmic_type {
RK805 = 1,
RK808,
+ RK809,
+ RK817,
};
struct rk8xx_regdef {
@@ -47,7 +49,10 @@ struct rk8xx_regdef {
uint8_t voltage_mask;
int voltage_min;
int voltage_max;
+ int voltage_min2;
+ int voltage_max2;
int voltage_step;
+ int voltage_step2;
int voltage_nstep;
};
@@ -88,6 +93,7 @@ struct rk8xx_rtc_reg {
struct rk8xx_dev_ctrl {
uint8_t dev_ctrl_reg;
uint8_t pwr_off_mask;
+ uint8_t pwr_rst_mask;
};
struct rk8xx_softc {
diff --git a/sys/dev/iicbus/pmic/rockchip/rk8xx_regulators.c b/sys/dev/iicbus/pmic/rockchip/rk8xx_regulators.c
index 74bf2ab6ff73..be214228e817 100644
--- a/sys/dev/iicbus/pmic/rockchip/rk8xx_regulators.c
+++ b/sys/dev/iicbus/pmic/rockchip/rk8xx_regulators.c
@@ -113,11 +113,38 @@ rk8xx_regnode_enable(struct regnode *regnode, bool enable, int *udelay)
static void
rk8xx_regnode_reg_to_voltage(struct rk8xx_reg_sc *sc, uint8_t val, int *uv)
{
- if (val < sc->def->voltage_nstep)
- *uv = sc->def->voltage_min + val * sc->def->voltage_step;
- else
- *uv = sc->def->voltage_min +
- (sc->def->voltage_nstep * sc->def->voltage_step);
+ struct rk8xx_softc *sc1;
+
+ sc1 = device_get_softc(sc->base_dev);
+ if (sc1->type == RK809 || sc1->type == RK817) {
+ if (sc->def->voltage_step2) {
+ int change;
+
+ change =
+ ((sc->def->voltage_min2 - sc->def->voltage_min) /
+ sc->def->voltage_step);
+ if (val > change) {
+ if (val < sc->def->voltage_nstep) {
+ *uv = sc->def->voltage_min2 +
+ (val - change) *
+ sc->def->voltage_step2;
+ } else
+ *uv = sc->def->voltage_max2;
+ return;
+ }
+ }
+ if (val < sc->def->voltage_nstep)
+ *uv = sc->def->voltage_min + val * sc->def->voltage_step;
+ else
+ *uv = sc->def->voltage_max;
+
+ } else {
+ if (val < sc->def->voltage_nstep)
+ *uv = sc->def->voltage_min + val * sc->def->voltage_step;
+ else
+ *uv = sc->def->voltage_min +
+ (sc->def->voltage_nstep * sc->def->voltage_step);
+ }
}
static int
@@ -126,14 +153,25 @@ rk8xx_regnode_voltage_to_reg(struct rk8xx_reg_sc *sc, int min_uvolt,
{
uint8_t nval;
int nstep, uvolt;
+ struct rk8xx_softc *sc1;
+ sc1 = device_get_softc(sc->base_dev);
nval = 0;
uvolt = sc->def->voltage_min;
for (nstep = 0; nstep < sc->def->voltage_nstep && uvolt < min_uvolt;
nstep++) {
++nval;
- uvolt += sc->def->voltage_step;
+ if (sc1->type == RK809 || sc1->type == RK817) {
+ if (sc->def->voltage_step2) {
+ if (uvolt < sc->def->voltage_min2)
+ uvolt += sc->def->voltage_step;
+ else
+ uvolt += sc->def->voltage_step2;
+ } else
+ uvolt += sc->def->voltage_step;
+ } else
+ uvolt += sc->def->voltage_step;
}
if (uvolt > max_uvolt)
return (EINVAL);
@@ -163,10 +201,12 @@ rk8xx_regnode_set_voltage(struct regnode *regnode, int min_uvolt,
int max_uvolt, int *udelay)
{
struct rk8xx_reg_sc *sc;
- uint8_t val;
+ uint8_t val, old;
int uvolt;
+ struct rk8xx_softc *sc1;
sc = regnode_get_softc(regnode);
+ sc1 = device_get_softc(sc->base_dev);
if (!sc->def->voltage_step)
return (ENXIO);
@@ -176,9 +216,13 @@ rk8xx_regnode_set_voltage(struct regnode *regnode, int min_uvolt,
min_uvolt,
max_uvolt);
rk8xx_read(sc->base_dev, sc->def->voltage_reg, &val, 1);
+ old = val;
if (rk8xx_regnode_voltage_to_reg(sc, min_uvolt, max_uvolt, &val) != 0)
return (ERANGE);
+ if (sc1->type == RK809 || sc1->type == RK817)
+ val |= (old &= ~sc->def->voltage_mask);
+
rk8xx_write(sc->base_dev, sc->def->voltage_reg, &val, 1);
rk8xx_read(sc->base_dev, sc->def->voltage_reg, &val, 1);
diff --git a/sys/dev/iicbus/pmic/rockchip/rk8xx_rtc.c b/sys/dev/iicbus/pmic/rockchip/rk8xx_rtc.c
index 2f755d16b164..91991b4f41be 100644
--- a/sys/dev/iicbus/pmic/rockchip/rk8xx_rtc.c
+++ b/sys/dev/iicbus/pmic/rockchip/rk8xx_rtc.c
@@ -61,6 +61,10 @@ rk8xx_gettime(device_t dev, struct timespec *ts)
error = rk8xx_write(dev, sc->rtc_regs.ctrl, &ctrl, 1);
if (error != 0)
return (error);
+ if (sc->type == RK809 || sc->type == RK817) {
+ /* wait one 32khz cycle for clock shadow registers to latch */
+ DELAY(1000000 / 32000);
+ }
ctrl &= ~sc->rtc_regs.ctrl_gettime_mask;
error = rk8xx_write(dev, sc->rtc_regs.ctrl, &ctrl, 1);
if (error != 0)
@@ -91,6 +95,8 @@ rk8xx_gettime(device_t dev, struct timespec *ts)
if (bct.dow == 7)
bct.dow = 0;
bct.ispm = 0;
+ if (sc->type == RK809 || sc->type == RK817)
+ bct.year += 0x2000; /* valid for 2000-2099 only */
if (bootverbose)
device_printf(dev, "Read RTC: %02x-%02x-%02x %02x:%02x:%02x\n",
@@ -113,6 +119,14 @@ rk8xx_settime(device_t dev, struct timespec *ts)
clock_ts_to_bcd(ts, &bct, false);
/* This works as long as RK805_RTC_SECS = 0 */
+ if (sc->type == RK809 || sc->type == RK817) {
+ /* valid for 2000-2099 only */
+ if ((bct.year & 0xff00) != 0x2000) {
+ device_printf(dev, "year out of range\n");
+ return (EINVAL);
+ }
+ bct.year &= 0x00ff;
+ }
data[sc->rtc_regs.years] = bct.year;
data[sc->rtc_regs.months] = bct.mon;
data[sc->rtc_regs.days] = bct.day;