summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorjdc <jdc@NetBSD.org>2020-10-27 20:13:21 +0000
committerjdc <jdc@NetBSD.org>2020-10-27 20:13:21 +0000
commit29581b701ace75abca5a7f59e5c73e824fd71eeb (patch)
treed443797c5714093103659b61b8fc4ab989c5243d /sys/dev
parent8b2fe5146d8dc02365c1a87778317a779c22df2a (diff)
Add additional debugging output.
Track more chip state in the softc and check the chip state via a timer. This allows us to easily observe changes caused by external events (e.g. disk removal or PSU failure).
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/i2c/pcagpio.c86
1 files changed, 73 insertions, 13 deletions
diff --git a/sys/dev/i2c/pcagpio.c b/sys/dev/i2c/pcagpio.c
index 26f3144264e..cf8529b6ba9 100644
--- a/sys/dev/i2c/pcagpio.c
+++ b/sys/dev/i2c/pcagpio.c
@@ -1,4 +1,4 @@
-/* $NetBSD: pcagpio.c,v 1.3 2020/02/02 06:43:14 macallan Exp $ */
+/* $NetBSD: pcagpio.c,v 1.4 2020/10/27 20:13:21 jdc Exp $ */
/*-
* Copyright (c) 2020 Michael Lorenz
@@ -31,11 +31,14 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pcagpio.c,v 1.3 2020/02/02 06:43:14 macallan Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pcagpio.c,v 1.4 2020/10/27 20:13:21 jdc Exp $");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/device.h>
+#ifdef PCAGPIO_DEBUG
+#include <sys/kernel.h>
+#endif
#include <sys/conf.h>
#include <sys/bus.h>
@@ -56,6 +59,10 @@ __KERNEL_RCSID(0, "$NetBSD: pcagpio.c,v 1.3 2020/02/02 06:43:14 macallan Exp $")
static int pcagpio_match(device_t, cfdata_t, void *);
static void pcagpio_attach(device_t, device_t, void *);
+static int pcagpio_detach(device_t, int);
+#ifdef PCAGPIO_DEBUG
+static void pcagpio_timeout(void *);
+#endif
/* we can only pass one cookie to led_attach() but we need several values... */
struct pcagpio_led {
@@ -72,6 +79,11 @@ struct pcagpio_softc {
uint32_t sc_state;
struct pcagpio_led sc_leds[16];
int sc_nleds;
+
+#ifdef PCAGPIO_DEBUG
+ uint32_t sc_dir, sc_in;
+ callout_t sc_timer;
+#endif
};
@@ -83,7 +95,7 @@ static int pcagpio_get(void *);
static void pcagpio_set(void *, int);
CFATTACH_DECL_NEW(pcagpio, sizeof(struct pcagpio_softc),
- pcagpio_match, pcagpio_attach, NULL, NULL);
+ pcagpio_match, pcagpio_attach, pcagpio_detach, NULL);
static const struct device_compatible_entry compat_data[] = {
{ "i2c-pca9555", 1 },
@@ -107,7 +119,7 @@ pcagpio_match(device_t parent, cfdata_t match, void *aux)
#ifdef PCAGPIO_DEBUG
static void
-printdir(uint32_t val, uint32_t mask, char letter)
+printdir(char* name, uint32_t val, uint32_t mask, char letter)
{
char flags[17], bits[17];
uint32_t bit = 0x8000;
@@ -121,8 +133,8 @@ printdir(uint32_t val, uint32_t mask, char letter)
}
flags[16] = 0;
bits[16] = 0;
- printf("dir: %s\n", flags);
- printf("lvl: %s\n", bits);
+ printf("%s: dir: %s\n", name, flags);
+ printf("%s: lvl: %s\n", name, bits);
}
#endif
@@ -151,16 +163,21 @@ pcagpio_attach(device_t parent, device_t self, void *aux)
sc->sc_state = pcagpio_readreg(sc, PCAGPIO_OUTPUT);
#ifdef PCAGPIO_DEBUG
- uint32_t dir, in, out;
- dir = pcagpio_readreg(sc, PCAGPIO_CONFIG);
- in = pcagpio_readreg(sc, PCAGPIO_INPUT);
+ uint32_t in, out;
+ sc->sc_dir = pcagpio_readreg(sc, PCAGPIO_CONFIG);
+ sc->sc_in = pcagpio_readreg(sc, PCAGPIO_INPUT);
+ in = sc-> sc_in;
out = sc->sc_state;
- out &= ~dir;
- in &= dir;
+ out &= ~sc->sc_dir;
+ in &= sc->sc_dir;
- printdir(in, dir, 'I');
- printdir(out, ~dir, 'O');
+ printdir(sc->sc_dev->dv_xname, in, sc->sc_dir, 'I');
+ printdir(sc->sc_dev->dv_xname, out, ~sc->sc_dir, 'O');
+
+ callout_init(&sc->sc_timer, CALLOUT_MPSAFE);
+ callout_reset(&sc->sc_timer, hz*20, pcagpio_timeout, sc);
+
#endif
pins = prop_dictionary_get(dict, "pins");
@@ -189,6 +206,49 @@ pcagpio_attach(device_t parent, device_t self, void *aux)
}
}
+static int
+pcagpio_detach(device_t self, int flags)
+{
+#ifdef PCAGPIO_DEBUG
+ struct pcagpio_softc *sc = device_private(self);
+
+ callout_halt(&sc->sc_timer, NULL);
+ callout_destroy(&sc->sc_timer);
+#endif
+
+ return 0;
+}
+
+#ifdef PCAGPIO_DEBUG
+static void
+pcagpio_timeout(void *v)
+{
+ struct pcagpio_softc *sc = v;
+ uint32_t out, dir, in, o_out, o_in;
+
+ out = pcagpio_readreg(sc, PCAGPIO_OUTPUT);
+ dir = pcagpio_readreg(sc, PCAGPIO_CONFIG);
+ in = pcagpio_readreg(sc, PCAGPIO_INPUT);
+ if (out != sc->sc_state || dir != sc->sc_dir || in != sc->sc_in) {
+ aprint_normal_dev(sc->sc_dev, "status change\n");
+ o_out = sc->sc_state;
+ o_in = sc->sc_in;
+ o_out &= ~sc->sc_dir;
+ o_in &= sc->sc_dir;
+ printdir(sc->sc_dev->dv_xname, o_in, sc->sc_dir, 'I');
+ printdir(sc->sc_dev->dv_xname, o_out, ~sc->sc_dir, 'O');
+ sc->sc_state = out;
+ sc->sc_dir = dir;
+ sc->sc_in = in;
+ out &= ~sc->sc_dir;
+ in &= sc->sc_dir;
+ printdir(sc->sc_dev->dv_xname, in, sc->sc_dir, 'I');
+ printdir(sc->sc_dev->dv_xname, out, ~sc->sc_dir, 'O');
+ }
+ callout_reset(&sc->sc_timer, hz*60, pcagpio_timeout, sc);
+}
+#endif
+
static void
pcagpio_writereg(struct pcagpio_softc *sc, int reg, uint32_t val)
{