summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/fdt/files.fdt20
-rw-r--r--sys/dev/fdt/imxanatop.c187
2 files changed, 199 insertions, 8 deletions
diff --git a/sys/dev/fdt/files.fdt b/sys/dev/fdt/files.fdt
index 32644969204..08e3b2b283c 100644
--- a/sys/dev/fdt/files.fdt
+++ b/sys/dev/fdt/files.fdt
@@ -1,4 +1,4 @@
-# $OpenBSD: files.fdt,v 1.50 2018/03/30 20:02:28 patrick Exp $
+# $OpenBSD: files.fdt,v 1.51 2018/03/30 20:38:27 patrick Exp $
#
# Config file and device description for machine-independent FDT code.
# Included by ports that need it.
@@ -182,9 +182,13 @@ device acrtc
attach acrtc at rsb
file dev/fdt/acrtc.c acrtc
-device imxuart
-attach imxuart at fdt
-file dev/fdt/imxuart.c imxuart
+device imxanatop
+attach imxanatop at fdt
+file dev/fdt/imxanatop.c imxanatop
+
+device imxesdhc: sdmmcbus
+attach imxesdhc at fdt
+file dev/fdt/imxesdhc.c imxesdhc
device imxgpc
attach imxgpc at fdt
@@ -194,10 +198,10 @@ device imxgpio
attach imxgpio at fdt
file dev/fdt/imxgpio.c imxgpio
-device imxesdhc: sdmmcbus
-attach imxesdhc at fdt
-file dev/fdt/imxesdhc.c imxesdhc
-
device imxiic: i2cbus
attach imxiic at fdt
file dev/fdt/imxiic.c imxiic
+
+device imxuart
+attach imxuart at fdt
+file dev/fdt/imxuart.c imxuart
diff --git a/sys/dev/fdt/imxanatop.c b/sys/dev/fdt/imxanatop.c
new file mode 100644
index 00000000000..1835bbb222b
--- /dev/null
+++ b/sys/dev/fdt/imxanatop.c
@@ -0,0 +1,187 @@
+/* $OpenBSD: imxanatop.c,v 1.1 2018/03/30 20:38:27 patrick Exp $ */
+/*
+ * Copyright (c) 2016 Mark Kettenis <kettenis@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/malloc.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_misc.h>
+#include <dev/ofw/ofw_regulator.h>
+#include <dev/ofw/fdt.h>
+
+#define HREAD4(sc, reg) \
+ (bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg)))
+#define HWRITE4(sc, reg, val) \
+ bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val))
+
+struct imxanatop_softc {
+ struct device sc_dev;
+ bus_space_tag_t sc_iot;
+ bus_space_handle_t sc_ioh;
+};
+
+struct imxanatop_regulator {
+ struct imxanatop_softc *ir_sc;
+
+ uint32_t ir_reg_offset;
+ uint32_t ir_vol_bit_shift;
+ uint32_t ir_vol_bit_width;
+ uint32_t ir_min_bit_val;
+ uint32_t ir_min_voltage;
+ uint32_t ir_max_voltage;
+
+ uint32_t ir_delay_reg_offset;
+ uint32_t ir_delay_bit_shift;
+ uint32_t ir_delay_bit_width;
+
+ struct regulator_device ir_rd;
+};
+
+int imxanatop_match(struct device *, void *, void *);
+void imxanatop_attach(struct device *, struct device *, void *);
+
+struct cfattach imxanatop_ca = {
+ sizeof(struct imxanatop_softc), imxanatop_match, imxanatop_attach
+};
+
+struct cfdriver imxanatop_cd = {
+ NULL, "imxanatop", DV_DULL
+};
+
+void imxanatop_attach_regulator(struct imxanatop_softc *, int);
+uint32_t imxanatop_get_voltage(void *);
+int imxanatop_set_voltage(void *, uint32_t);
+
+int
+imxanatop_match(struct device *parent, void *match, void *aux)
+{
+ struct fdt_attach_args *faa = aux;
+
+ if (OF_is_compatible(faa->fa_node, "fsl,imx6q-anatop"))
+ return 10; /* Must beat simplebus(4) and syscon(4). */
+
+ return 0;
+}
+
+void
+imxanatop_attach(struct device *parent, struct device *self, void *aux)
+{
+ struct imxanatop_softc *sc = (struct imxanatop_softc *)self;
+ struct fdt_attach_args *faa = aux;
+ int node;
+
+ if (faa->fa_nreg < 1) {
+ printf(": no registers\n");
+ return;
+ }
+
+ sc->sc_iot = faa->fa_iot;
+
+ if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr,
+ faa->fa_reg[0].size, 0, &sc->sc_ioh)) {
+ printf(": can't map registers\n");
+ return;
+ }
+
+ regmap_register(faa->fa_node, sc->sc_iot, sc->sc_ioh,
+ faa->fa_reg[0].size);
+
+ printf("\n");
+
+ for (node = OF_child(faa->fa_node); node; node = OF_peer(node))
+ if (OF_is_compatible(node, "fsl,anatop-regulator"))
+ imxanatop_attach_regulator(sc, node);
+}
+
+void
+imxanatop_attach_regulator(struct imxanatop_softc *sc, int node)
+{
+ struct imxanatop_regulator *ir;
+
+ ir = malloc(sizeof(*ir), M_DEVBUF, M_WAITOK | M_ZERO);
+ ir->ir_sc = sc;
+
+ ir->ir_reg_offset = OF_getpropint(node, "anatop-reg-offset", -1);
+ ir->ir_vol_bit_shift = OF_getpropint(node, "anatop-vol-bit-shift", -1);
+ ir->ir_vol_bit_width = OF_getpropint(node, "anatop-vol-bit-width", -1);
+ ir->ir_min_bit_val = OF_getpropint(node, "anatop-min-bit-val", -1);
+ ir->ir_min_voltage = OF_getpropint(node, "anatop-min-voltage", -1);
+ ir->ir_max_voltage = OF_getpropint(node, "anatop-max-voltage", -1);
+ if (ir->ir_reg_offset == -1 || ir->ir_vol_bit_shift == -1 ||
+ ir->ir_vol_bit_width == -1 || ir->ir_min_bit_val == -1 ||
+ ir->ir_min_voltage == -1 || ir->ir_max_voltage == -1)
+ return;
+
+ ir->ir_delay_reg_offset =
+ OF_getpropint(node, "anatop-delay-reg-offset", 0);
+ ir->ir_delay_bit_shift =
+ OF_getpropint(node, "anatop-delay-bit-shift", 0);
+ ir->ir_delay_bit_width =
+ OF_getpropint(node, "anatop-delay-bit-width", 0);
+
+ ir->ir_rd.rd_node = node;
+ ir->ir_rd.rd_cookie = ir;
+ ir->ir_rd.rd_get_voltage = imxanatop_get_voltage;
+ ir->ir_rd.rd_set_voltage = imxanatop_set_voltage;
+ regulator_register(&ir->ir_rd);
+}
+
+uint32_t
+imxanatop_get_voltage(void *cookie)
+{
+ struct imxanatop_regulator *ir = cookie;
+ uint32_t bit_val;
+
+ bit_val = HREAD4(ir->ir_sc, ir->ir_reg_offset) >> ir->ir_vol_bit_shift;
+ bit_val &= ((1 << ir->ir_vol_bit_width) - 1);
+ return (ir->ir_min_voltage + (bit_val - ir->ir_min_bit_val) * 25000);
+}
+
+int
+imxanatop_set_voltage(void *cookie, uint32_t voltage)
+{
+ struct imxanatop_regulator *ir = cookie;
+ uint32_t bit_val, old_bit_val, reg;
+ int steps, usecs;
+
+ if (voltage < ir->ir_min_voltage || voltage > ir->ir_max_voltage)
+ return -1;
+
+ bit_val = ir->ir_min_bit_val + (voltage - ir->ir_min_voltage) / 25000;
+ reg = HREAD4(ir->ir_sc, ir->ir_reg_offset);
+ old_bit_val = (reg >> ir->ir_vol_bit_shift);
+ old_bit_val &= ((1 << ir->ir_vol_bit_width) -1);
+ reg &= ~((1 << ir->ir_vol_bit_width) - 1) << ir->ir_vol_bit_shift;
+ reg |= (bit_val << ir->ir_vol_bit_shift);
+ HWRITE4(ir->ir_sc, ir->ir_reg_offset, reg);
+
+ steps = bit_val - old_bit_val;
+ if (steps > 0 && ir->ir_delay_bit_width > 0) {
+ reg = HREAD4(ir->ir_sc, ir->ir_delay_reg_offset);
+ reg >>= ir->ir_delay_bit_shift;
+ reg &= ((1 << ir->ir_delay_bit_width) - 1);
+ usecs = ((reg + 1) * steps * 64 * 1000000) / 24000000;
+ delay(usecs);
+ }
+
+ return 0;
+}