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 watchdog support
details: https://anonhg.NetBSD.org/src/rev/5b13e505492a
branches: trunk
changeset: 341755:5b13e505492a
user: jmcneill <jmcneill%NetBSD.org@localhost>
date: Sat Nov 21 10:56:40 2015 +0000
description:
add watchdog support
diffstat:
sys/dev/i2c/as3722.c | 135 ++++++++++++++++++++++++++++++++++++++++++++++++--
1 files changed, 129 insertions(+), 6 deletions(-)
diffs (206 lines):
diff -r 235e62dd2652 -r 5b13e505492a sys/dev/i2c/as3722.c
--- a/sys/dev/i2c/as3722.c Sat Nov 21 09:06:03 2015 +0000
+++ b/sys/dev/i2c/as3722.c Sat Nov 21 10:56:40 2015 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: as3722.c,v 1.1 2015/11/11 12:35:22 jmcneill Exp $ */
+/* $NetBSD: as3722.c,v 1.2 2015/11/21 10:56:40 jmcneill Exp $ */
/*-
* Copyright (c) 2015 Jared D. McNeill <jmcneill%invisible.ca@localhost>
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: as3722.c,v 1.1 2015/11/11 12:35:22 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: as3722.c,v 1.2 2015/11/21 10:56:40 jmcneill Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -36,13 +36,35 @@
#include <sys/conf.h>
#include <sys/bus.h>
#include <sys/kmem.h>
+#include <sys/wdog.h>
+
+#include <dev/sysmon/sysmonvar.h>
#include <dev/i2c/i2cvar.h>
#include <dev/i2c/as3722.h>
+#define AS3722_GPIO0_CTRL_REG 0x08
+#define AS3722_GPIO0_CTRL_INVERT __BIT(7)
+#define AS3722_GPIO0_CTRL_IOSF __BITS(6,3)
+#define AS3722_GPIO0_CTRL_IOSF_GPIO 0
+#define AS3722_GPIO0_CTRL_IOSF_WATCHDOG 9
+#define AS3722_GPIO0_CTRL_MODE __BITS(2,0)
+#define AS3722_GPIO0_CTRL_MODE_PULLDOWN 5
+
#define AS3722_RESET_CTRL_REG 0x36
#define AS3722_RESET_CTRL_POWER_OFF __BIT(1)
+#define AS3722_WATCHDOG_CTRL_REG 0x38
+#define AS3722_WATCHDOG_CTRL_MODE __BITS(2,1)
+#define AS3722_WATCHDOG_CTRL_ON __BIT(0)
+
+#define AS3722_WATCHDOG_TIMER_REG 0x46
+#define AS3722_WATCHDOG_TIMER_TIMER __BITS(6,0)
+
+#define AS3722_WATCHDOG_SIGNAL_REG 0x48
+#define AS3722_WATCHDOG_SIGNAL_PWM_DIV __BITS(7,6)
+#define AS3722_WATCHDOG_SIGNAL_SW_SIG __BIT(0)
+
#define AS3722_ASIC_ID1_REG 0x90
#define AS3722_ASIC_ID2_REG 0x91
@@ -50,15 +72,22 @@
device_t sc_dev;
i2c_tag_t sc_i2c;
i2c_addr_t sc_addr;
+
+ struct sysmon_wdog sc_smw;
};
+#define AS3722_WATCHDOG_DEFAULT_PERIOD 10
+
static int as3722_match(device_t, cfdata_t, void *);
static void as3722_attach(device_t, device_t, void *);
-#if 0
+static int as3722_wdt_setmode(struct sysmon_wdog *);
+static int as3722_wdt_tickle(struct sysmon_wdog *);
+
static int as3722_read(struct as3722_softc *, uint8_t, uint8_t *, int);
-#endif
static int as3722_write(struct as3722_softc *, uint8_t, uint8_t, int);
+static int as3722_set_clear(struct as3722_softc *, uint8_t, uint8_t,
+ uint8_t, int);
CFATTACH_DECL_NEW(as3722pmic, sizeof(struct as3722_softc),
as3722_match, as3722_attach, NULL, NULL);
@@ -87,6 +116,7 @@
{
struct as3722_softc * const sc = device_private(self);
struct i2c_attach_args *ia = aux;
+ int error;
sc->sc_dev = self;
sc->sc_i2c = ia->ia_tag;
@@ -94,16 +124,40 @@
aprint_naive("\n");
aprint_normal(": AMS AS3822\n");
+
+ iic_acquire_bus(sc->sc_i2c, I2C_F_POLL);
+ error = as3722_write(sc, AS3722_GPIO0_CTRL_REG,
+ __SHIFTIN(AS3722_GPIO0_CTRL_IOSF_GPIO,
+ AS3722_GPIO0_CTRL_IOSF) |
+ __SHIFTIN(AS3722_GPIO0_CTRL_MODE_PULLDOWN,
+ AS3722_GPIO0_CTRL_MODE),
+ I2C_F_POLL);
+ error += as3722_set_clear(sc, AS3722_WATCHDOG_CTRL_REG,
+ __SHIFTIN(1, AS3722_WATCHDOG_CTRL_MODE), 0, I2C_F_POLL);
+ iic_release_bus(sc->sc_i2c, I2C_F_POLL);
+
+ if (error)
+ aprint_error_dev(self, "couldn't setup watchdog\n");
+
+ sc->sc_smw.smw_name = device_xname(self);
+ sc->sc_smw.smw_cookie = sc;
+ sc->sc_smw.smw_setmode = as3722_wdt_setmode;
+ sc->sc_smw.smw_tickle = as3722_wdt_tickle;
+ sc->sc_smw.smw_period = AS3722_WATCHDOG_DEFAULT_PERIOD;
+
+ aprint_normal_dev(self, "default watchdog period is %u seconds\n",
+ sc->sc_smw.smw_period);
+
+ if (sysmon_wdog_register(&sc->sc_smw) != 0)
+ aprint_error_dev(self, "couldn't register with sysmon\n");
}
-#if 0
static int
as3722_read(struct as3722_softc *sc, uint8_t reg, uint8_t *val, int flags)
{
return iic_exec(sc->sc_i2c, I2C_OP_READ_WITH_STOP, sc->sc_addr,
®, 1, val, 1, flags);
}
-#endif
static int
as3722_write(struct as3722_softc *sc, uint8_t reg, uint8_t val, int flags)
@@ -113,6 +167,75 @@
NULL, 0, buf, 2, flags);
}
+static int
+as3722_set_clear(struct as3722_softc *sc, uint8_t reg, uint8_t set,
+ uint8_t clr, int flags)
+{
+ uint8_t old, new;
+ int error;
+
+ error = as3722_read(sc, reg, &old, flags);
+ if (error) {
+ return error;
+ }
+ new = set | (old & ~clr);
+
+ return as3722_write(sc, reg, new, flags);
+}
+
+static int
+as3722_wdt_setmode(struct sysmon_wdog *smw)
+{
+ struct as3722_softc * const sc = smw->smw_cookie;
+ int error;
+
+ const int flags = (cold ? I2C_F_POLL : 0);
+
+ if ((smw->smw_mode & WDOG_MODE_MASK) == WDOG_MODE_DISARMED) {
+ iic_acquire_bus(sc->sc_i2c, flags);
+ error = as3722_set_clear(sc, AS3722_WATCHDOG_CTRL_REG,
+ 0, AS3722_WATCHDOG_CTRL_ON, flags);
+ iic_release_bus(sc->sc_i2c, flags);
+ return error;
+ }
+
+ if (smw->smw_period == WDOG_PERIOD_DEFAULT) {
+ smw->smw_period = AS3722_WATCHDOG_DEFAULT_PERIOD;
+ }
+ if (smw->smw_period < 1 || smw->smw_period > 128) {
+ return EINVAL;
+ }
+ sc->sc_smw.smw_period = smw->smw_period;
+
+ iic_acquire_bus(sc->sc_i2c, flags);
+ error = as3722_set_clear(sc, AS3722_WATCHDOG_TIMER_REG,
+ __SHIFTIN(sc->sc_smw.smw_period - 1, AS3722_WATCHDOG_TIMER_TIMER),
+ AS3722_WATCHDOG_TIMER_TIMER, flags);
+ if (error == 0) {
+ error = as3722_set_clear(sc, AS3722_WATCHDOG_CTRL_REG,
+ AS3722_WATCHDOG_CTRL_ON, 0, flags);
+ }
+ iic_release_bus(sc->sc_i2c, flags);
+
+ return error;
+}
+
+static int
+as3722_wdt_tickle(struct sysmon_wdog *smw)
+{
+ struct as3722_softc * const sc = smw->smw_cookie;
+ int error;
+
+ const int flags = (cold ? I2C_F_POLL : 0);
+
+ iic_acquire_bus(sc->sc_i2c, flags);
+ error = as3722_set_clear(sc, AS3722_WATCHDOG_SIGNAL_REG,
+ AS3722_WATCHDOG_SIGNAL_SW_SIG, 0, flags);
+ iic_release_bus(sc->sc_i2c, flags);
+
+ return error;
+}
+
int
as3722_poweroff(device_t dev)
{
Home |
Main Index |
Thread Index |
Old Index