summaryrefslogtreecommitdiff
path: root/sys/dev/fdt
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2018-08-03 21:07:35 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2018-08-03 21:07:35 +0000
commit987a6f16d55420565b5ae86de5670490c4b22b11 (patch)
tree5ca2eb7c371195e58f1c30db0ceedaff5c4006bc /sys/dev/fdt
parent01e4221776e6cad5f19bdf12e5b6b13d82e85a35 (diff)
Also attach as a regulator if the FDT provides the fixed voltage value.
Restore fixed voltage at reboot time to prevent hangs after a warm reset if DVFS is active.
Diffstat (limited to 'sys/dev/fdt')
-rw-r--r--sys/dev/fdt/sypwr.c48
1 files changed, 41 insertions, 7 deletions
diff --git a/sys/dev/fdt/sypwr.c b/sys/dev/fdt/sypwr.c
index e626256df9e..5a0b5c80ced 100644
--- a/sys/dev/fdt/sypwr.c
+++ b/sys/dev/fdt/sypwr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sypwr.c,v 1.1 2017/12/31 11:13:59 kettenis Exp $ */
+/* $OpenBSD: sypwr.c,v 1.2 2018/08/03 21:07:34 kettenis Exp $ */
/*
* Copyright (c) 2017 Mark Kettenis <kettenis@openbsd.org>
*
@@ -35,14 +35,18 @@ struct sypwr_softc {
i2c_tag_t sc_tag;
i2c_addr_t sc_addr;
+ uint32_t sc_fixed_microvolt;
+
struct regulator_device sc_rd;
};
int sypwr_match(struct device *, void *, void *);
void sypwr_attach(struct device *, struct device *, void *);
+int sypwr_activate(struct device *, int);
struct cfattach sypwr_ca = {
- sizeof(struct sypwr_softc), sypwr_match, sypwr_attach
+ sizeof(struct sypwr_softc), sypwr_match, sypwr_attach,
+ NULL, sypwr_activate
};
struct cfdriver sypwr_cd = {
@@ -74,14 +78,18 @@ sypwr_attach(struct device *parent, struct device *self, void *aux)
sc->sc_tag = ia->ia_tag;
sc->sc_addr = ia->ia_addr;
+ sc->sc_fixed_microvolt =
+ OF_getpropint(node, "silergy,fixed-microvolt", 0);
+
/*
* Only register the regulator if it is under I2C control
- * (i.e. initialized by the firmware). Otherwise we have no
- * idea what the current output voltage is, which will confuse
- * the regulator framework.
+ * (i.e. initialized by the firmware) or if the device tree
+ * specifies its fixed voltage. Otherwise we have no idea
+ * what the current output voltage is, which will confuse the
+ * regulator framework.
*/
reg = sypwr_read(sc, SY8106A_VOUT1_SEL);
- if (reg & SY8106A_VOUT1_SEL_I2C) {
+ if (reg & SY8106A_VOUT1_SEL_I2C || sc->sc_fixed_microvolt != 0) {
uint32_t voltage;
voltage = sypwr_get_voltage(sc);
@@ -98,6 +106,29 @@ sypwr_attach(struct device *parent, struct device *self, void *aux)
printf("\n");
}
+int
+sypwr_activate(struct device *self, int act)
+{
+ struct sypwr_softc *sc = (struct sypwr_softc *)self;
+ uint8_t reg;
+
+ switch (act) {
+ case DVACT_POWERDOWN:
+ /*
+ * Restore fixed voltage otherwise we might hang after
+ * a warm reset.
+ */
+ if (sc->sc_fixed_microvolt != 0) {
+ reg = sypwr_read(sc, SY8106A_VOUT1_SEL);
+ reg &= ~SY8106A_VOUT1_SEL_I2C;
+ sypwr_write(sc, SY8106A_VOUT1_SEL, reg);
+ }
+ break;
+ }
+
+ return 0;
+}
+
uint8_t
sypwr_read(struct sypwr_softc *sc, int reg)
{
@@ -144,7 +175,10 @@ sypwr_get_voltage(void *cookie)
uint8_t value;
value = sypwr_read(sc, SY8106A_VOUT1_SEL);
- return 680000 + (value & SY8106A_VOUT1_SEL_MASK) * 10000;
+ if (value & SY8106A_VOUT1_SEL_I2C)
+ return 680000 + (value & SY8106A_VOUT1_SEL_MASK) * 10000;
+ else
+ return sc->sc_fixed_microvolt;
}
int