Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/i2c Handle pins that represent alerts.
details: https://anonhg.NetBSD.org/src/rev/152b452c87d2
branches: trunk
changeset: 948259:152b452c87d2
user: jdc <jdc%NetBSD.org@localhost>
date: Wed Dec 23 07:06:26 2020 +0000
description:
Handle pins that represent alerts.
split out common code for alert and indicator pins
change the previously debug-only callout to work for alerts too
split out common code for alerts in refresh and in callout
While here, remove redundant variable used for checking sysmon setup.
diffstat:
sys/dev/i2c/pcf8574.c | 208 ++++++++++++++++++++++++++++++++++++-------------
1 files changed, 151 insertions(+), 57 deletions(-)
diffs (truncated from 358 to 300 lines):
diff -r 9957cae99257 -r 152b452c87d2 sys/dev/i2c/pcf8574.c
--- a/sys/dev/i2c/pcf8574.c Wed Dec 23 07:01:14 2020 +0000
+++ b/sys/dev/i2c/pcf8574.c Wed Dec 23 07:06:26 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: pcf8574.c,v 1.5 2020/12/06 10:09:36 jdc Exp $ */
+/* $NetBSD: pcf8574.c,v 1.6 2020/12/23 07:06:26 jdc Exp $ */
/*-
* Copyright (c) 2020 The NetBSD Foundation, Inc.
@@ -35,7 +35,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pcf8574.c,v 1.5 2020/12/06 10:09:36 jdc Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pcf8574.c,v 1.6 2020/12/23 07:06:26 jdc Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -43,6 +43,7 @@
#include <sys/kernel.h>
#include <dev/sysmon/sysmonvar.h>
+#include <dev/sysmon/sysmon_taskq.h>
#include <dev/i2c/i2cvar.h>
#include <dev/led.h>
@@ -59,6 +60,12 @@
uint8_t mask, v_on, v_off;
};
+struct pcf8574_pin {
+ int pin_sensor;
+ int pin_active;
+ char pin_desc[ENVSYS_DESCLEN];
+};
+
#define PCF8574_NPINS 8
struct pcf8574_softc {
device_t sc_dev;
@@ -67,34 +74,35 @@
uint8_t sc_state;
uint8_t sc_mask;
+ uint8_t sc_alert_mask;
+#define PCF8574_DEFAULT_TIMER 60
+ int sc_callout_time;
+ callout_t sc_timer;
+
int sc_nleds;
struct pcf8574_led sc_leds[PCF8574_NPINS];
+ struct pcf8574_pin sc_pins[PCF8574_NPINS];
struct sysmon_envsys *sc_sme;
envsys_data_t sc_sensor[PCF8574_NPINS];
- int sc_pin_sensor[PCF8574_NPINS];
- int sc_pin_active[PCF8574_NPINS];
-
-#ifdef PCF8574_DEBUG
- callout_t sc_timer;
-#endif
};
static int pcf8574_match(device_t, cfdata_t, void *);
static void pcf8574_attach(device_t, device_t, void *);
static int pcf8574_detach(device_t, int);
-static int pcf8574_read(struct pcf8574_softc *sc, uint8_t *val);
-static int pcf8574_write(struct pcf8574_softc *sc, uint8_t val);
+static int pcf8574_read(struct pcf8574_softc *sc, uint8_t *);
+static int pcf8574_write(struct pcf8574_softc *sc, uint8_t);
static void pcf8574_attach_led(
struct pcf8574_softc *, char *, int, int, int);
+static int pcf8574_attach_sysmon(
+ struct pcf8574_softc *, char *, int, int, int);
void pcf8574_refresh(struct sysmon_envsys *, envsys_data_t *);
int pcf8574_get_led(void *);
void pcf8574_set_led(void *, int);
-
-#ifdef PCF8574_DEBUG
-static void pcf8574_timeout(void *);
-#endif
+static void pcf8574_timeout(void *);
+static void pcf8574_check(void *);
+static void pcf8574_check_alert(struct pcf8574_softc *, uint8_t, uint8_t);
CFATTACH_DECL_NEW(pcf8574io, sizeof(struct pcf8574_softc),
pcf8574_match, pcf8574_attach, pcf8574_detach, NULL);
@@ -128,12 +136,19 @@
int i, num, def, envc = 0;
char name[32];
const char *nptr = NULL, *spptr;
- bool ok = TRUE, act, sysmon = FALSE;
+ bool ok = TRUE, act;
sc->sc_tag = ia->ia_tag;
sc->sc_addr = ia->ia_addr;
sc->sc_dev = self;
+ sc->sc_sme = NULL;
+#ifdef PCF8574_DEBUG
+ sc->sc_callout_time = 60; /* watch for changes when debugging */
+#else
+ sc->sc_callout_time = 0;
+#endif
+
/*
* The PCF8574 requires input pins to be written with the value 1,
* and then read. Assume that all pins are input initially.
@@ -150,9 +165,6 @@
#ifdef PCF8574_DEBUG
aprint_normal(": GPIO: state = 0x%02x\n", sc->sc_state);
-
- callout_init(&sc->sc_timer, CALLOUT_MPSAFE);
- callout_reset(&sc->sc_timer, hz*30, pcf8574_timeout, sc);
#else
aprint_normal(": GPIO\n");
#endif
@@ -177,37 +189,38 @@
continue;
spptr += 1;
strncpy(name, spptr, 31);
- sc->sc_pin_active[i] = act;
+ sc->sc_pins[i].pin_active = act;
if (!strncmp(nptr, "LED ", 4)) {
sc->sc_mask &= ~(1 << num);
pcf8574_attach_led(sc, name, num, act, def);
}
- if (!strncmp(nptr, "INDICATOR ", 4)) {
- if (!sysmon) {
- sc->sc_sme = sysmon_envsys_create();
- sysmon = TRUE;
- }
- /* envsys sensor # to pin # mapping */
- sc->sc_pin_sensor[envc] = num;
- sc->sc_sensor[i].state = ENVSYS_SINVALID;
- sc->sc_sensor[i].units = ENVSYS_INDICATOR;
- strlcpy(sc->sc_sensor[i].desc, name,
- sizeof(sc->sc_sensor[i].desc));
- if (sysmon_envsys_sensor_attach(sc->sc_sme,
- &sc->sc_sensor[i])) {
- sysmon_envsys_destroy(sc->sc_sme);
- sc->sc_sme = NULL;
- aprint_error_dev(self,
- "unable to attach pin %d at sysmon\n", i);
+ if (!strncmp(nptr, "INDICATOR ", 10)) {
+ if (pcf8574_attach_sysmon(sc, name, envc, num, act))
+ return;
+ envc++;
+ }
+ if (!strncmp(nptr, "ALERT ", 6)) {
+ u_int64_t alert_time;
+
+ if (pcf8574_attach_sysmon(sc, name, envc, num, act))
return;
- }
- DPRINTF("%s: added indicator: pin %d sensor %d (%s)\n",
- device_xname(sc->sc_dev), num, envc, name);
+
+ /* Adjust our timeout if the alert times out. */
+ if (def != -1)
+ alert_time = def / 2;
+ else
+ alert_time = PCF8574_DEFAULT_TIMER;
+
+ if (sc->sc_callout_time == 0 ||
+ alert_time < sc->sc_callout_time)
+ sc->sc_callout_time = alert_time;
+
+ sc->sc_alert_mask |= (1 << num);
envc++;
}
}
- if (sysmon) {
+ if (sc->sc_sme != NULL) {
sc->sc_sme->sme_name = device_xname(self);
sc->sc_sme->sme_cookie = sc;
sc->sc_sme->sme_refresh = pcf8574_refresh;
@@ -219,6 +232,12 @@
return;
}
}
+
+ if (sc->sc_callout_time) {
+ callout_init(&sc->sc_timer, CALLOUT_MPSAFE);
+ callout_reset(&sc->sc_timer, hz * sc->sc_callout_time,
+ pcf8574_timeout, sc);
+ }
}
static int
@@ -227,6 +246,12 @@
struct pcf8574_softc *sc = device_private(self);
int i;
+ if (sc->sc_callout_time) {
+ callout_halt(&sc->sc_timer, NULL);
+ callout_destroy(&sc->sc_timer);
+ sc->sc_callout_time = 0;
+ }
+
if (sc->sc_sme != NULL) {
sysmon_envsys_unregister(sc->sc_sme);
sc->sc_sme = NULL;
@@ -235,10 +260,6 @@
for (i = 0; i < sc->sc_nleds; i++)
led_detach(sc->sc_leds[i].led);
-#ifdef PCF8574_DEBUG
- callout_halt(&sc->sc_timer, NULL);
- callout_destroy(&sc->sc_timer);
-#endif
return 0;
}
@@ -269,7 +290,8 @@
}
static void
-pcf8574_attach_led(struct pcf8574_softc *sc, char *n, int pin, int act, int def)
+pcf8574_attach_led(struct pcf8574_softc *sc, char *name, int pin, int act,
+ int def)
{
struct pcf8574_led *l;
@@ -278,7 +300,7 @@
l->mask = 1 << pin;
l->v_on = act ? l->mask : 0;
l->v_off = act ? 0 : l->mask;
- led_attach(n, l, pcf8574_get_led, pcf8574_set_led);
+ led_attach(name, l, pcf8574_get_led, pcf8574_set_led);
if (def != -1)
pcf8574_set_led(l, def);
DPRINTF("%s: attached LED: %02x %02x %02x def %d\n",
@@ -286,12 +308,45 @@
sc->sc_nleds++;
}
+static int
+pcf8574_attach_sysmon(struct pcf8574_softc *sc, char *name, int envc, int pin,
+ int act)
+{
+ int ret;
+
+ if (sc->sc_sme == NULL) {
+ sc->sc_sme = sysmon_envsys_create();
+ sc->sc_sme->sme_events_timeout = 0;
+ }
+
+ strlcpy(sc->sc_pins[pin].pin_desc, name,
+ sizeof(sc->sc_pins[pin].pin_desc));
+ /* envsys sensor # to pin # mapping */
+ sc->sc_pins[envc].pin_sensor = pin;
+ sc->sc_sensor[envc].state = ENVSYS_SINVALID;
+ sc->sc_sensor[envc].units = ENVSYS_INDICATOR;
+ strlcpy(sc->sc_sensor[envc].desc, name,
+ sizeof(sc->sc_sensor[envc].desc));
+ ret = sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor[envc]);
+ if (ret) {
+ sysmon_envsys_destroy(sc->sc_sme);
+ sc->sc_sme = NULL;
+ aprint_error_dev(sc->sc_dev,
+ "unable to attach pin %d at sysmon\n", pin);
+ return ret;
+ }
+ DPRINTF("%s: added sysmon: pin %d sensor %d (%s)\n",
+ device_xname(sc->sc_dev), pin, envc, name);
+ return 0;
+}
+
void
pcf8574_refresh(struct sysmon_envsys *sme, envsys_data_t *edata)
{
struct pcf8574_softc *sc = sme->sme_cookie;
- int pin = sc->sc_pin_sensor[edata->sensor];
- int act = sc->sc_pin_active[pin];
+ int pin = sc->sc_pins[edata->sensor].pin_sensor;
+ int act = sc->sc_pins[pin].pin_active;
+ u_int8_t prev_state = sc->sc_state;
pcf8574_read(sc, &sc->sc_state);
if (act)
@@ -299,6 +354,13 @@
else
edata->value_cur = sc->sc_state & 1 << pin ? FALSE : TRUE;
edata->state = ENVSYS_SVALID;
+
+ /* We read all the pins, so check for alerts on any pin now */
+ if (sc->sc_state != prev_state) {
+ DPRINTF("%s: (refresh) status change: 0x%02x > 0x%02x\n",
+ device_xname(sc->sc_dev), prev_state, sc->sc_state);
+ pcf8574_check_alert(sc, prev_state, sc->sc_state);
+ }
}
int
@@ -327,19 +389,51 @@
}
}
Home |
Main Index |
Thread Index |
Old Index