Module Name: src
Committed By: jmcneill
Date: Thu May 3 01:15:49 UTC 2018
Modified Files:
src/sys/dev/i2c: axp806.c files.i2c
Removed Files:
src/sys/dev/i2c: axp806.h
Log Message:
FDT-ize X-Powers AXP805/806 PMIC driver.
To generate a diff of this commit:
cvs rdiff -u -r1.1 -r1.2 src/sys/dev/i2c/axp806.c
cvs rdiff -u -r1.1 -r0 src/sys/dev/i2c/axp806.h
cvs rdiff -u -r1.87 -r1.88 src/sys/dev/i2c/files.i2c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/dev/i2c/axp806.c
diff -u src/sys/dev/i2c/axp806.c:1.1 src/sys/dev/i2c/axp806.c:1.2
--- src/sys/dev/i2c/axp806.c:1.1 Sun Dec 7 00:33:26 2014
+++ src/sys/dev/i2c/axp806.c Thu May 3 01:15:49 2018
@@ -1,7 +1,7 @@
-/* $NetBSD: axp806.c,v 1.1 2014/12/07 00:33:26 jmcneill Exp $ */
+/* $NetBSD: axp806.c,v 1.2 2018/05/03 01:15:49 jmcneill Exp $ */
/*-
- * Copyright (c) 2014 Jared D. McNeill <[email protected]>
+ * Copyright (c) 2014-2018 Jared McNeill <[email protected]>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -26,10 +26,8 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-#define AXP_DEBUG
-
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: axp806.c,v 1.1 2014/12/07 00:33:26 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: axp806.c,v 1.2 2018/05/03 01:15:49 jmcneill Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -40,7 +38,8 @@ __KERNEL_RCSID(0, "$NetBSD: axp806.c,v 1
#include <sys/kmem.h>
#include <dev/i2c/i2cvar.h>
-#include <dev/i2c/axp806.h>
+
+#include <dev/fdt/fdtvar.h>
#define AXP_STARTUP_SOURCE_REG 0x00
#define AXP_IC_TYPE_REG 0x03
@@ -117,35 +116,35 @@ struct axp806_ctrl {
.c_voltage_reg = AXP_##vreg##_REG, .c_voltage_mask = (vmask) }
static const struct axp806_ctrl axp806_ctrls[] = {
- AXP_CTRL2("DCDCA", 600, 1520, 10, 51, 20, 21,
+ AXP_CTRL2("dcdca", 600, 1520, 10, 51, 20, 21,
OUT_CTRL1, __BIT(0), DCDCA_CTRL, __BITS(6,0)),
- AXP_CTRL("DCDCB", 1000, 2550, 50,
+ AXP_CTRL("dcdcb", 1000, 2550, 50,
OUT_CTRL1, __BIT(1), DCDCB_CTRL, __BITS(4,0)),
- AXP_CTRL2("DCDCC", 600, 1520, 10, 51, 20, 21,
+ AXP_CTRL2("dcdcc", 600, 1520, 10, 51, 20, 21,
OUT_CTRL1, __BIT(2), DCDCC_CTRL, __BITS(6,0)),
- AXP_CTRL2("DCDCD", 600, 3300, 20, 46, 100, 18,
+ AXP_CTRL2("dcdcd", 600, 3300, 20, 46, 100, 18,
OUT_CTRL1, __BIT(3), DCDCD_CTRL, __BITS(5,0)),
- AXP_CTRL("DCDCE", 1100, 3400, 100,
+ AXP_CTRL("dcdce", 1100, 3400, 100,
OUT_CTRL1, __BIT(4), DCDCE_CTRL, __BITS(4,0)),
- AXP_CTRL("ALDO1", 700, 3300, 100,
+ AXP_CTRL("aldo1", 700, 3300, 100,
OUT_CTRL1, __BIT(5), ALDO1_CTRL, __BITS(4,0)),
- AXP_CTRL("ALDO2", 700, 3400, 100,
+ AXP_CTRL("aldo2", 700, 3400, 100,
OUT_CTRL1, __BIT(6), ALDO2_CTRL, __BITS(4,0)),
- AXP_CTRL("ALDO3", 700, 3300, 100,
+ AXP_CTRL("aldo3", 700, 3300, 100,
OUT_CTRL1, __BIT(7), ALDO3_CTRL, __BITS(4,0)),
- AXP_CTRL("BLDO1", 700, 1900, 100,
+ AXP_CTRL("bldo1", 700, 1900, 100,
OUT_CTRL2, __BIT(0), BLDO1_CTRL, __BITS(3,0)),
- AXP_CTRL("BLDO2", 700, 1900, 100,
+ AXP_CTRL("bldo2", 700, 1900, 100,
OUT_CTRL2, __BIT(1), BLDO2_CTRL, __BITS(3,0)),
- AXP_CTRL("BLDO3", 700, 1900, 100,
+ AXP_CTRL("bldo3", 700, 1900, 100,
OUT_CTRL2, __BIT(2), BLDO3_CTRL, __BITS(3,0)),
- AXP_CTRL("BLDO4", 700, 1900, 100,
+ AXP_CTRL("bldo4", 700, 1900, 100,
OUT_CTRL2, __BIT(3), BLDO4_CTRL, __BITS(3,0)),
- AXP_CTRL("CLDO1", 700, 3300, 100,
+ AXP_CTRL("cldo1", 700, 3300, 100,
OUT_CTRL2, __BIT(4), CLDO1_CTRL, __BITS(4,0)),
- AXP_CTRL2("CLDO2", 700, 4200, 100, 28, 200, 4,
+ AXP_CTRL2("cldo2", 700, 4200, 100, 28, 200, 4,
OUT_CTRL2, __BIT(5), CLDO2_CTRL, __BITS(4,0)),
- AXP_CTRL("CLDO3", 700, 3300, 100,
+ AXP_CTRL("cldo3", 700, 3300, 100,
OUT_CTRL2, __BIT(6), CLDO3_CTRL, __BITS(4,0)),
};
@@ -153,117 +152,47 @@ struct axp806_softc {
device_t sc_dev;
i2c_tag_t sc_i2c;
i2c_addr_t sc_addr;
-
- u_int sc_nctrl;
- struct axp806_ctrl *sc_ctrl;
+ int sc_phandle;
};
-static int axp806_match(device_t, cfdata_t, void *);
-static void axp806_attach(device_t, device_t, void *);
-
-static int axp806_read(struct axp806_softc *, uint8_t, uint8_t *);
-static int axp806_write(struct axp806_softc *, uint8_t, uint8_t);
-
-static void axp806_print(struct axp806_ctrl *c);
-
-CFATTACH_DECL_NEW(axp806pm, sizeof(struct axp806_softc),
- axp806_match, axp806_attach, NULL, NULL);
-
-static int
-axp806_match(device_t parent, cfdata_t match, void *aux)
-{
- return 1;
-}
-
-static void
-axp806_attach(device_t parent, device_t self, void *aux)
-{
- struct axp806_softc *sc = device_private(self);
- struct i2c_attach_args *ia = aux;
- u_int n;
-
- sc->sc_dev = self;
- sc->sc_i2c = ia->ia_tag;
- sc->sc_addr = ia->ia_addr;
-
- aprint_naive("\n");
- aprint_normal("\n");
+struct axp806reg_softc {
+ device_t sc_dev;
+ i2c_tag_t sc_i2c;
+ i2c_addr_t sc_addr;
+ const struct axp806_ctrl *sc_ctrl;
+};
- sc->sc_nctrl = __arraycount(axp806_ctrls);
- sc->sc_ctrl = kmem_alloc(sizeof(axp806_ctrls), KM_SLEEP);
- memcpy(sc->sc_ctrl, axp806_ctrls, sizeof(axp806_ctrls));
- for (n = 0; n < sc->sc_nctrl; n++) {
- sc->sc_ctrl[n].c_dev = self;
- }
+struct axp806reg_attach_args {
+ const struct axp806_ctrl *reg_ctrl;
+ int reg_phandle;
+ i2c_tag_t reg_i2c;
+ i2c_addr_t reg_addr;
+};
-#ifdef AXP_DEBUG
- for (n = 0; n < sc->sc_nctrl; n++) {
- axp806_print(&sc->sc_ctrl[n]);
- }
-#endif
-}
+static const char *compatible[] = {
+ "x-powers,axp805",
+ "x-powers,axp806",
+ NULL
+};
static int
-axp806_read(struct axp806_softc *sc, uint8_t reg, uint8_t *val)
+axp806_read(i2c_tag_t tag, i2c_addr_t addr, uint8_t reg, uint8_t *val)
{
- return iic_smbus_read_byte(sc->sc_i2c, sc->sc_addr, reg, val,
+ return iic_smbus_read_byte(tag, addr, reg, val,
cold ? I2C_F_POLL : 0);
}
static int
-axp806_write(struct axp806_softc *sc, uint8_t reg, uint8_t val)
+axp806_write(i2c_tag_t tag, i2c_addr_t addr, uint8_t reg, uint8_t val)
{
- return iic_smbus_write_byte(sc->sc_i2c, sc->sc_addr, reg, val,
+ return iic_smbus_write_byte(tag, addr, reg, val,
cold ? I2C_F_POLL : 0);
}
-static void
-axp806_print(struct axp806_ctrl *c)
-{
- struct axp806_softc *sc = device_private(c->c_dev);
- u_int voltage;
- bool enabled;
-
- device_printf(sc->sc_dev, "%s:", c->c_name);
- if (c->c_voltage_reg) {
- if (axp806_get_voltage(c, &voltage)) {
- printf(" [??? V]");
- } else {
- printf(" [%d.%03dV]", voltage / 1000,
- voltage % 1000);
- }
- }
- if (c->c_enable_reg) {
- if (axp806_is_enabled(c, &enabled)) {
- printf(" [unknown state]");
- } else {
- printf(" [%s]", enabled ? "ON" : "OFF");
- }
- }
- printf("\n");
-}
-
-struct axp806_ctrl *
-axp806_lookup(device_t dev, const char *name)
-{
- struct axp806_softc *sc = device_private(dev);
- struct axp806_ctrl *c;
- u_int n;
-
- for (n = 0; n < sc->sc_nctrl; n++) {
- c = &sc->sc_ctrl[n];
- if (strcmp(c->c_name, name) == 0) {
- return c;
- }
- }
-
- return NULL;
-}
-
-int
-axp806_set_voltage(struct axp806_ctrl *c, u_int min, u_int max)
+static int
+axp806_set_voltage(i2c_tag_t tag, i2c_addr_t addr, const struct axp806_ctrl *c, u_int min, u_int max)
{
- struct axp806_softc *sc = device_private(c->c_dev);
+ const int flags = (cold ? I2C_F_POLL : 0);
u_int vol, reg_val;
int nstep, error;
uint8_t val;
@@ -290,35 +219,30 @@ axp806_set_voltage(struct axp806_ctrl *c
if (vol > max)
return EINVAL;
- iic_acquire_bus(sc->sc_i2c, 0);
- if ((error = axp806_read(sc, c->c_voltage_reg, &val)) != 0)
- goto done;
- val &= ~c->c_voltage_mask;
- val |= __SHIFTIN(reg_val, c->c_voltage_mask);
- error = axp806_write(sc, c->c_voltage_reg, val);
-
-done:
- iic_release_bus(sc->sc_i2c, 0);
-#ifdef AXP_DEBUG
- if (error == 0)
- axp806_print(c);
-#endif
+ iic_acquire_bus(tag, flags);
+ if ((error = axp806_read(tag, addr, c->c_voltage_reg, &val)) == 0) {
+ val &= ~c->c_voltage_mask;
+ val |= __SHIFTIN(reg_val, c->c_voltage_mask);
+ error = axp806_write(tag, addr, c->c_voltage_reg, val);
+ }
+ iic_release_bus(tag, flags);
+
return error;
}
-int
-axp806_get_voltage(struct axp806_ctrl *c, u_int *pvol)
+static int
+axp806_get_voltage(i2c_tag_t tag, i2c_addr_t addr, const struct axp806_ctrl *c, u_int *pvol)
{
- struct axp806_softc *sc = device_private(c->c_dev);
+ const int flags = (cold ? I2C_F_POLL : 0);
int reg_val, error;
uint8_t val;
if (!c->c_voltage_mask)
return EINVAL;
- iic_acquire_bus(sc->sc_i2c, 0);
- error = axp806_read(sc, c->c_voltage_reg, &val);
- iic_release_bus(sc->sc_i2c, 0);
+ iic_acquire_bus(tag, flags);
+ error = axp806_read(tag, addr, c->c_voltage_reg, &val);
+ iic_release_bus(tag, flags);
if (error)
return error;
@@ -333,72 +257,152 @@ axp806_get_voltage(struct axp806_ctrl *c
return 0;
}
-int
-axp806_is_enabled(struct axp806_ctrl *c, bool *penabled)
+static int
+axp806_match(device_t parent, cfdata_t match, void *aux)
{
- struct axp806_softc *sc = device_private(c->c_dev);
- uint8_t val;
- int error;
+ struct i2c_attach_args *ia = aux;
- if (!c->c_enable_mask)
- return EINVAL;
+ if (ia->ia_name != NULL)
+ return iic_compat_match(ia, compatible);
- iic_acquire_bus(sc->sc_i2c, 0);
- error = axp806_read(sc, c->c_enable_reg, &val);
- iic_release_bus(sc->sc_i2c, 0);
- if (error)
- return error;
+ return 1;
+}
+
+static void
+axp806_attach(device_t parent, device_t self, void *aux)
+{
+ struct axp806_softc *sc = device_private(self);
+ struct axp806reg_attach_args aaa;
+ struct i2c_attach_args *ia = aux;
+ int phandle, child, i;
+
+ sc->sc_dev = self;
+ sc->sc_i2c = ia->ia_tag;
+ sc->sc_addr = ia->ia_addr;
+ sc->sc_phandle = ia->ia_cookie;
+
+ aprint_naive("\n");
+ aprint_normal(": PMIC\n");
- *penabled = !!(val & c->c_enable_mask);
+ phandle = of_find_firstchild_byname(sc->sc_phandle, "regulators");
+ if (phandle <= 0)
+ return;
+
+ aaa.reg_i2c = sc->sc_i2c;
+ aaa.reg_addr = sc->sc_addr;
+ for (i = 0; i < __arraycount(axp806_ctrls); i++) {
+ const struct axp806_ctrl *ctrl = &axp806_ctrls[i];
+ child = of_find_firstchild_byname(phandle, ctrl->c_name);
+ if (child <= 0)
+ continue;
+ aaa.reg_ctrl = ctrl;
+ aaa.reg_phandle = child;
+ config_found(sc->sc_dev, &aaa, NULL);
+ }
+}
+
+static int
+axp806reg_acquire(device_t dev)
+{
return 0;
}
-int
-axp806_enable(struct axp806_ctrl *c)
+static void
+axp806reg_release(device_t dev)
+{
+}
+
+static int
+axp806reg_enable(device_t dev, bool enable)
{
- struct axp806_softc *sc = device_private(c->c_dev);
+ struct axp806reg_softc *sc = device_private(dev);
+ const struct axp806_ctrl *c = sc->sc_ctrl;
+ const int flags = (cold ? I2C_F_POLL : 0);
uint8_t val;
int error;
if (!c->c_enable_mask)
return EINVAL;
- iic_acquire_bus(sc->sc_i2c, 0);
- if ((error = axp806_read(sc, c->c_enable_reg, &val)) != 0)
- goto done;
- val |= c->c_enable_mask;
- error = axp806_write(sc, c->c_enable_reg, val);
-done:
- iic_release_bus(sc->sc_i2c, 0);
-#ifdef AXP_DEBUG
- if (error == 0)
- axp806_print(c);
-#endif
+ iic_acquire_bus(sc->sc_i2c, flags);
+ if ((error = axp806_read(sc->sc_i2c, sc->sc_addr, c->c_enable_reg, &val)) == 0) {
+ if (enable)
+ val |= c->c_enable_mask;
+ else
+ val &= ~c->c_enable_mask;
+ error = axp806_write(sc->sc_i2c, sc->sc_addr, c->c_enable_reg, val);
+ }
+ iic_release_bus(sc->sc_i2c, flags);
return error;
}
-int
-axp806_disable(struct axp806_ctrl *c)
+static int
+axp806reg_set_voltage(device_t dev, u_int min_uvol, u_int max_uvol)
{
- struct axp806_softc *sc = device_private(c->c_dev);
- uint8_t val;
+ struct axp806reg_softc *sc = device_private(dev);
+ const struct axp806_ctrl *c = sc->sc_ctrl;
+
+ return axp806_set_voltage(sc->sc_i2c, sc->sc_addr, c,
+ min_uvol / 1000, max_uvol / 1000);
+}
+
+static int
+axp806reg_get_voltage(device_t dev, u_int *puvol)
+{
+ struct axp806reg_softc *sc = device_private(dev);
+ const struct axp806_ctrl *c = sc->sc_ctrl;
int error;
+ u_int vol;
- if (!c->c_enable_mask)
- return EINVAL;
+ error = axp806_get_voltage(sc->sc_i2c, sc->sc_addr, c, &vol);
+ if (error)
+ return error;
- iic_acquire_bus(sc->sc_i2c, 0);
- if ((error = axp806_read(sc, c->c_enable_reg, &val)) != 0)
- goto done;
- val &= ~c->c_enable_mask;
- error = axp806_write(sc, c->c_enable_reg, val);
-done:
- iic_release_bus(sc->sc_i2c, 0);
-#ifdef AXP_DEBUG
- if (error == 0)
- axp806_print(c);
-#endif
+ *puvol = vol * 1000;
+ return 0;
+}
- return error;
+static struct fdtbus_regulator_controller_func axp806reg_funcs = {
+ .acquire = axp806reg_acquire,
+ .release = axp806reg_release,
+ .enable = axp806reg_enable,
+ .set_voltage = axp806reg_set_voltage,
+ .get_voltage = axp806reg_get_voltage,
+};
+
+static int
+axp806reg_match(device_t parent, cfdata_t match, void *aux)
+{
+ return 1;
+}
+
+static void
+axp806reg_attach(device_t parent, device_t self, void *aux)
+{
+ struct axp806reg_softc *sc = device_private(self);
+ struct axp806reg_attach_args *aaa = aux;
+ const int phandle = aaa->reg_phandle;
+ const char *name;
+
+ sc->sc_dev = self;
+ sc->sc_i2c = aaa->reg_i2c;
+ sc->sc_addr = aaa->reg_addr;
+ sc->sc_ctrl = aaa->reg_ctrl;
+
+ fdtbus_register_regulator_controller(self, phandle,
+ &axp806reg_funcs);
+
+ aprint_naive("\n");
+ name = fdtbus_get_string(phandle, "regulator-name");
+ if (name)
+ aprint_normal(": %s\n", name);
+ else
+ aprint_normal("\n");
}
+
+CFATTACH_DECL_NEW(axp806pmic, sizeof(struct axp806_softc),
+ axp806_match, axp806_attach, NULL, NULL);
+
+CFATTACH_DECL_NEW(axp806reg, sizeof(struct axp806reg_softc),
+ axp806reg_match, axp806reg_attach, NULL, NULL);
Index: src/sys/dev/i2c/files.i2c
diff -u src/sys/dev/i2c/files.i2c:1.87 src/sys/dev/i2c/files.i2c:1.88
--- src/sys/dev/i2c/files.i2c:1.87 Fri Mar 16 22:11:53 2018
+++ src/sys/dev/i2c/files.i2c Thu May 3 01:15:49 2018
@@ -1,4 +1,4 @@
-# $NetBSD: files.i2c,v 1.87 2018/03/16 22:11:53 macallan Exp $
+# $NetBSD: files.i2c,v 1.88 2018/05/03 01:15:49 jmcneill Exp $
obsolete defflag opt_i2cbus.h I2C_SCAN
define i2cbus { }
@@ -233,9 +233,11 @@ attach axp22x at iic
file dev/i2c/axp22x.c axp22x
# AXP806 Power Management Unit
-device axp806pm
-attach axp806pm at iic
-file dev/i2c/axp806.c axp806pm needs-flag
+device axp806pmic { }
+device axp806reg: axp806pmic
+attach axp806pmic at iic
+attach axp806reg at axp806pmic
+file dev/i2c/axp806.c axp806pmic needs-flag
# AXP809 Power Management Unit
device axp809pm