summaryrefslogtreecommitdiff
path: root/sys/dev/fdt/axp20x.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/fdt/axp20x.c')
-rw-r--r--sys/dev/fdt/axp20x.c135
1 files changed, 135 insertions, 0 deletions
diff --git a/sys/dev/fdt/axp20x.c b/sys/dev/fdt/axp20x.c
new file mode 100644
index 00000000000..f09f38c97a3
--- /dev/null
+++ b/sys/dev/fdt/axp20x.c
@@ -0,0 +1,135 @@
+/* $OpenBSD: axp20x.c,v 1.1 2017/07/23 19:26:03 kettenis Exp $ */
+/*
+ * Copyright (c) 2014,2016 Artturi Alm
+ *
+ * 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/sensors.h>
+
+#include <dev/i2c/i2cvar.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/fdt.h>
+
+#include <armv7/armv7/armv7_machdep.h> /* needed for powerdownfn */
+
+/* Power Status Register / Input power status */
+#define AXP209_PSR 0x00
+#define AXP209_PSR_ACIN (1 << 7) /* ACIN Exists */
+#define AXP209_PSR_VBUS (1 << 5) /* VBUS Exists */
+
+/* Shutdown settings, battery detection, and CHGLED Pin control */
+#define AXP209_SDR 0x32
+#define AXP209_SDR_SHUTDOWN (1 << 7) /* Shutdown Control */
+
+struct axp20x_softc {
+ struct device sc_dev;
+ i2c_tag_t sc_i2c;
+ i2c_addr_t sc_addr;
+};
+
+int axp20x_match(struct device *, void *, void *);
+void axp20x_attach(struct device *, struct device *, void *);
+
+int axp20x_readb(uint8_t, uint8_t *);
+int axp20x_writeb(uint8_t, uint8_t);
+void axp20x_shutdown(void);
+
+struct cfattach axppmic_ca = {
+ sizeof(struct axp20x_softc), axp20x_match, axp20x_attach
+};
+
+struct cfdriver axppmic_cd = {
+ NULL, "axppmic", DV_DULL
+};
+
+int
+axp20x_match(struct device *parent, void *match, void *aux)
+{
+ struct i2c_attach_args *ia = aux;
+ int node = *(int *)ia->ia_cookie;
+
+ return OF_is_compatible(node, "x-powers,axp209");
+}
+
+void
+axp20x_attach(struct device *parent, struct device *self, void *aux)
+{
+ struct axp20x_softc *sc = (struct axp20x_softc *)self;
+ struct i2c_attach_args *ia = aux;
+ uint8_t psr;
+
+ sc->sc_i2c = ia->ia_tag;
+ sc->sc_addr = ia->ia_addr;
+
+ axp20x_readb(AXP209_PSR, &psr);
+ printf(": AXP209,");
+ if ((psr & (AXP209_PSR_ACIN | AXP209_PSR_VBUS)) == 0)
+ printf(" BAT");
+ else {
+ if (psr & AXP209_PSR_ACIN)
+ printf(" ACIN");
+ if (psr & AXP209_PSR_VBUS)
+ printf(" VBUS");
+ }
+ printf("\n");
+
+ powerdownfn = axp20x_shutdown;
+}
+
+int
+axp20x_readb(uint8_t reg, uint8_t *val)
+{
+ struct axp20x_softc *sc = axppmic_cd.cd_devs[0];
+ int flags = I2C_F_POLL;
+ int ret;
+
+ if (sc == NULL)
+ return ENXIO;
+
+ iic_acquire_bus(sc->sc_i2c, flags);
+ ret = iic_smbus_read_byte(sc->sc_i2c, sc->sc_addr, reg, val, flags);
+ iic_release_bus(sc->sc_i2c, flags);
+ return ret;
+
+}
+
+int
+axp20x_writeb(uint8_t reg, uint8_t data)
+{
+ struct axp20x_softc *sc = axppmic_cd.cd_devs[0];
+ int flags = I2C_F_POLL;
+ int ret;
+
+ if (sc == NULL)
+ return ENXIO;
+
+ iic_acquire_bus(sc->sc_i2c, flags);
+ ret = iic_smbus_write_byte(sc->sc_i2c, sc->sc_addr, reg, data, flags);
+ iic_release_bus(sc->sc_i2c, flags);
+
+ return ret;
+}
+
+void
+axp20x_shutdown(void)
+{
+ axp20x_writeb(AXP209_SDR, AXP209_SDR_SHUTDOWN);
+}