Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/i2c Add LDO6 regulator support.
details: https://anonhg.NetBSD.org/src/rev/547e4918166a
branches: trunk
changeset: 353182:547e4918166a
user: jmcneill <jmcneill%NetBSD.org@localhost>
date: Sat Apr 22 21:48:56 2017 +0000
description:
Add LDO6 regulator support.
diffstat:
sys/dev/i2c/as3722.c | 224 +++++++++++++++++++++++++++++++++++++++++++++++++-
sys/dev/i2c/files.i2c | 6 +-
2 files changed, 226 insertions(+), 4 deletions(-)
diffs (truncated from 306 to 300 lines):
diff -r a221b918571f -r 547e4918166a sys/dev/i2c/as3722.c
--- a/sys/dev/i2c/as3722.c Sat Apr 22 21:47:41 2017 +0000
+++ b/sys/dev/i2c/as3722.c Sat Apr 22 21:48:56 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: as3722.c,v 1.6 2017/04/22 13:26:05 jmcneill Exp $ */
+/* $NetBSD: as3722.c,v 1.7 2017/04/22 21:48:56 jmcneill Exp $ */
/*-
* Copyright (c) 2015 Jared D. McNeill <jmcneill%invisible.ca@localhost>
@@ -29,7 +29,7 @@
#include "opt_fdt.h"
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: as3722.c,v 1.6 2017/04/22 13:26:05 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: as3722.c,v 1.7 2017/04/22 21:48:56 jmcneill Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -61,6 +61,8 @@
#define AS3722_GPIO0_CTRL_MODE __BITS(2,0)
#define AS3722_GPIO0_CTRL_MODE_PULLDOWN 5
+#define AS3722_LDO6_VOLTAGE_REG 0x16
+
#define AS3722_RESET_CTRL_REG 0x36
#define AS3722_RESET_CTRL_POWER_OFF __BIT(1)
#define AS3722_RESET_CTRL_FORCE_RESET __BIT(0)
@@ -76,6 +78,8 @@
#define AS3722_WATCHDOG_SIGNAL_PWM_DIV __BITS(7,6)
#define AS3722_WATCHDOG_SIGNAL_SW_SIG __BIT(0)
+#define AS3722_LDOCONTROL0_REG 0x4e
+
#define AS3722_RTC_CONTROL_REG 0x60
#define AS3722_RTC_CONTROL_RTC_ON __BIT(2)
@@ -100,6 +104,35 @@
struct todr_chip_handle sc_todr;
};
+#ifdef FDT
+static const struct as3722regdef {
+ const char *name;
+ u_int vsel_reg;
+ u_int vsel_mask;
+ u_int enable_reg;
+ u_int enable_mask;
+ u_int n_voltages;
+} as3722regdefs[] = {
+ { .name = "ldo6",
+ .vsel_reg = AS3722_LDO6_VOLTAGE_REG,
+ .vsel_mask = 0x7f,
+ .enable_reg = AS3722_LDOCONTROL0_REG,
+ .enable_mask = 0x40,
+ .n_voltages = 0x80 },
+};
+
+struct as3722reg_softc {
+ device_t sc_dev;
+ int sc_phandle;
+ const struct as3722regdef *sc_regdef;
+};
+
+struct as3722reg_attach_args {
+ const struct as3722regdef *reg_def;
+ int reg_phandle;
+};
+#endif
+
#define AS3722_WATCHDOG_DEFAULT_PERIOD 10
static int as3722_match(device_t, cfdata_t, void *);
@@ -113,6 +146,26 @@
static int as3722_rtc_gettime(todr_chip_handle_t, struct clock_ymdhms *);
static int as3722_rtc_settime(todr_chip_handle_t, struct clock_ymdhms *);
+#ifdef FDT
+static void as3722_regulator_attach(struct as3722_softc *);
+static int as3722reg_match(device_t, cfdata_t, void *);
+static void as3722reg_attach(device_t, device_t, void *);
+
+static int as3722reg_acquire(device_t);
+static void as3722reg_release(device_t);
+static int as3722reg_enable(device_t, bool);
+static int as3722reg_set_voltage(device_t, u_int, u_int);
+static int as3722reg_get_voltage(device_t, u_int *);
+
+static struct fdtbus_regulator_controller_func as3722reg_funcs = {
+ .acquire = as3722reg_acquire,
+ .release = as3722reg_release,
+ .enable = as3722reg_enable,
+ .set_voltage = as3722reg_set_voltage,
+ .get_voltage = as3722reg_get_voltage,
+};
+#endif
+
static int as3722_read(struct as3722_softc *, uint8_t, uint8_t *, int);
static int as3722_write(struct as3722_softc *, uint8_t, uint8_t, int);
static int as3722_set_clear(struct as3722_softc *, uint8_t, uint8_t,
@@ -121,6 +174,11 @@
CFATTACH_DECL_NEW(as3722pmic, sizeof(struct as3722_softc),
as3722_match, as3722_attach, NULL, NULL);
+#ifdef FDT
+CFATTACH_DECL_NEW(as3722reg, sizeof(struct as3722reg_softc),
+ as3722reg_match, as3722reg_attach, NULL, NULL);
+#endif
+
static const char * as3722_compats[] = {
"ams,as3722",
NULL
@@ -165,6 +223,9 @@
as3722_wdt_attach(sc);
as3722_rtc_attach(sc);
+#ifdef FDT
+ as3722_regulator_attach(sc);
+#endif
}
static void
@@ -373,6 +434,165 @@
return error;
}
+#ifdef FDT
+static void
+as3722_regulator_attach(struct as3722_softc *sc)
+{
+ struct as3722reg_attach_args raa;
+ int phandle, child;
+
+ phandle = of_find_firstchild_byname(sc->sc_phandle, "regulators");
+ if (phandle <= 0)
+ return;
+
+ for (int i = 0; i < __arraycount(as3722regdefs); i++) {
+ const struct as3722regdef *regdef = &as3722regdefs[i];
+ child = of_find_firstchild_byname(phandle, regdef->name);
+ if (child <= 0)
+ continue;
+ raa.reg_def = regdef;
+ raa.reg_phandle = child;
+ config_found(sc->sc_dev, &raa, NULL);
+ }
+}
+
+static int
+as3722reg_match(device_t parent, cfdata_t match, void *aux)
+{
+ return 1;
+}
+
+static void
+as3722reg_attach(device_t parent, device_t self, void *aux)
+{
+ struct as3722reg_softc *sc = device_private(self);
+ struct as3722reg_attach_args *raa = aux;
+ char *name = NULL;
+ int len;
+
+ sc->sc_dev = self;
+ sc->sc_phandle = raa->reg_phandle;
+ sc->sc_regdef = raa->reg_def;
+
+ fdtbus_register_regulator_controller(self, sc->sc_phandle,
+ &as3722reg_funcs);
+
+ len = OF_getproplen(sc->sc_phandle, "regulator-name");
+ if (len > 0) {
+ name = kmem_zalloc(len, KM_SLEEP);
+ OF_getprop(sc->sc_phandle, "regulator-name", name, len);
+ }
+
+ aprint_naive("\n");
+ if (name)
+ aprint_normal(": %s\n", name);
+ else
+ aprint_normal("\n");
+
+ if (name)
+ kmem_free(name, len);
+}
+
+static int
+as3722reg_acquire(device_t dev)
+{
+ return 0;
+}
+
+static void
+as3722reg_release(device_t dev)
+{
+}
+
+static int
+as3722reg_enable(device_t dev, bool enable)
+{
+ struct as3722reg_softc *sc = device_private(dev);
+ struct as3722_softc *asc = device_private(device_parent(dev));
+ const struct as3722regdef *regdef = sc->sc_regdef;
+ const int flags = (cold ? I2C_F_POLL : 0);
+ int error;
+
+ iic_acquire_bus(asc->sc_i2c, flags);
+ if (enable)
+ error = as3722_set_clear(asc, regdef->enable_reg,
+ regdef->enable_mask, 0, flags);
+ else
+ error = as3722_set_clear(asc, regdef->enable_reg,
+ 0, regdef->enable_mask, flags);
+ iic_release_bus(asc->sc_i2c, flags);
+
+ return error;
+}
+
+static int
+as3722reg_set_voltage(device_t dev, u_int min_uvol, u_int max_uvol)
+{
+ struct as3722reg_softc *sc = device_private(dev);
+ struct as3722_softc *asc = device_private(device_parent(dev));
+ const struct as3722regdef *regdef = sc->sc_regdef;
+ const int flags = (cold ? I2C_F_POLL : 0);
+ uint8_t set_v = 0x00;
+ u_int uvol;
+ int error;
+
+ for (uint8_t v = 0x01; v <= 0x24; v++) {
+ uvol = 800000 + (v * 25000);
+ if (uvol >= min_uvol && uvol <= max_uvol) {
+ set_v = v;
+ goto done;
+ }
+ }
+ for (uint8_t v = 0x40; v <= 0x7f; v++) {
+ uvol = 1725000 + ((v - 0x40) * 25000);
+ if (uvol >= min_uvol && uvol <= max_uvol) {
+ set_v = v;
+ goto done;
+ }
+ }
+ if (set_v == 0)
+ return ERANGE;
+
+done:
+ iic_acquire_bus(asc->sc_i2c, flags);
+ error = as3722_set_clear(asc, regdef->vsel_reg, set_v,
+ regdef->vsel_mask, flags);
+ iic_release_bus(asc->sc_i2c, flags);
+
+ return error;
+}
+
+static int
+as3722reg_get_voltage(device_t dev, u_int *puvol)
+{
+ struct as3722reg_softc *sc = device_private(dev);
+ struct as3722_softc *asc = device_private(device_parent(dev));
+ const struct as3722regdef *regdef = sc->sc_regdef;
+ const int flags = (cold ? I2C_F_POLL : 0);
+ uint8_t v;
+ int error;
+
+ iic_acquire_bus(asc->sc_i2c, flags);
+ error = as3722_read(asc, regdef->vsel_reg, &v, flags);
+ iic_release_bus(asc->sc_i2c, flags);
+ if (error != 0)
+ return error;
+
+ v &= regdef->vsel_mask;
+
+ if (v == 0)
+ *puvol = 0; /* LDO off */
+ else if (v >= 0x01 && v <= 0x24)
+ *puvol = 800000 + (v * 25000);
+ else if (v >= 0x40 && v <= 0x7f)
+ *puvol = 1725000 + ((v - 0x40) * 25000);
+ else
+ return EINVAL;
+
+ return 0;
+}
+#endif
+
int
as3722_poweroff(device_t dev)
{
diff -r a221b918571f -r 547e4918166a sys/dev/i2c/files.i2c
--- a/sys/dev/i2c/files.i2c Sat Apr 22 21:47:41 2017 +0000
+++ b/sys/dev/i2c/files.i2c Sat Apr 22 21:48:56 2017 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: files.i2c,v 1.72 2016/07/03 11:40:58 kiyohara Exp $
+# $NetBSD: files.i2c,v 1.73 2017/04/22 21:48:56 jmcneill Exp $
obsolete defflag opt_i2cbus.h I2C_SCAN
define i2cbus { }
@@ -257,6 +257,8 @@
file dev/i2c/titemp.c titemp
# AMS AS3722 Power Management IC
Home |
Main Index |
Thread Index |
Old Index