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 additional debugging output.



details:   https://anonhg.NetBSD.org/src/rev/0a3127c24466
branches:  trunk
changeset: 945376:0a3127c24466
user:      jdc <jdc%NetBSD.org@localhost>
date:      Tue Oct 27 20:13:21 2020 +0000

description:
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:

 sys/dev/i2c/pcagpio.c |  86 +++++++++++++++++++++++++++++++++++++++++++-------
 1 files changed, 73 insertions(+), 13 deletions(-)

diffs (156 lines):

diff -r de1aa15d4d22 -r 0a3127c24466 sys/dev/i2c/pcagpio.c
--- a/sys/dev/i2c/pcagpio.c     Tue Oct 27 19:16:46 2020 +0000
+++ b/sys/dev/i2c/pcagpio.c     Tue Oct 27 20:13:21 2020 +0000
@@ -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 @@
 
 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 @@
        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 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 @@
 
 #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 @@
        }
        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 @@
        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 @@
        }
 }
 
+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)
 {



Home | Main Index | Thread Index | Old Index