summaryrefslogtreecommitdiff
path: root/io-module
diff options
context:
space:
mode:
authorJeff Hatch <jhatch@multitech.com>2020-11-16 15:56:21 -0600
committerJohn Klug <john.klug@multitech.com>2020-11-23 14:22:34 -0600
commitfebfbaa141125c24d3a40e17034261c5354a0973 (patch)
treed16d84058fb005e0e5262b1a0bd16d63cd6c08f1 /io-module
parente8af5a62cb51f9bca1900c17b021cf5bc240c029 (diff)
downloadmts-io-febfbaa141125c24d3a40e17034261c5354a0973.tar.gz
mts-io-febfbaa141125c24d3a40e17034261c5354a0973.tar.bz2
mts-io-febfbaa141125c24d3a40e17034261c5354a0973.zip
Add supercap_worker to handle supercap gpio and signal supercap-monitor
Diffstat (limited to 'io-module')
-rw-r--r--io-module/machine/mtcap.c2
-rw-r--r--io-module/mts-io.c6
-rw-r--r--io-module/mts_supercap.c128
-rw-r--r--io-module/mts_supercap.h42
4 files changed, 178 insertions, 0 deletions
diff --git a/io-module/machine/mtcap.c b/io-module/machine/mtcap.c
index 99e1999..c2a4687 100644
--- a/io-module/machine/mtcap.c
+++ b/io-module/machine/mtcap.c
@@ -1,4 +1,5 @@
#include "at91gpio.h"
+#include "mts_supercap.h"
/* Used for both MTCAP 0.0 and 0.1 */
static struct gpio_pin gpio_pins_mtcap_0_0[] = {
{
@@ -670,6 +671,7 @@ static struct attribute *mtcap_0_3_supercap_attributes[] = {
&dev_attr_supercap_allow_reset_mtcap.attr,
&dev_attr_supercap_power_fail_mtcap.attr,
&dev_attr_supercap_supercap_full_mtcap.attr,
+ &dev_attr_supercap_monitor.attr,
};
static struct attribute *mtcap_0_2_enable_radio_attribute[] = {
diff --git a/io-module/mts-io.c b/io-module/mts-io.c
index 069e84b..83c3ddf 100644
--- a/io-module/mts-io.c
+++ b/io-module/mts-io.c
@@ -45,6 +45,7 @@
#include "mts_io_module.h"
#include "mts_io.h"
#include "buttons.h"
+#include "mts_supercap.h"
#define PLATFORM_NAME "mts-io"
@@ -1217,6 +1218,11 @@ static int __init mts_io_init(void)
// start general buttons processing
init_buttons();
+ //start supercap monitor worker if SUPERCAP CAPA is true
+ if(DEVICE_CAPA(id_eeprom.capa, CAPA_SUPERCAP)) {
+ init_supercap_worker();
+ }
+
/* init timers */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,15,0)
timer_setup(&radio_reset_timer, radio_reset_timer_callback, 0);
diff --git a/io-module/mts_supercap.c b/io-module/mts_supercap.c
new file mode 100644
index 0000000..e028408
--- /dev/null
+++ b/io-module/mts_supercap.c
@@ -0,0 +1,128 @@
+
+
+#include "mts_supercap.h"
+
+extern struct gpio_pin *gpio_pin_by_attr_name(const char *name);
+
+static supercap_info_t supercap = {
+ .name = "Super Cap",
+ .label_monitor = "supercap-monitor",
+ .signal = SIGPWR,
+ .pid = 0,
+ .pwf_count = 0,
+ .pin_is_one = 0,
+
+};
+
+ssize_t mts_attr_show_supercap_monitor(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ int ret;
+
+ //button_info_t *button = button_by_monitor_name(attr->attr.name);
+
+ //if (!button) {
+ // return -ENODEV;
+ //}
+
+ mutex_lock(&mts_io_mutex);
+
+ ret = sprintf(buf, "%d %d\n", supercap.pid, supercap.signal);
+
+ mutex_unlock(&mts_io_mutex);
+
+ return ret;
+}
+
+ssize_t mts_attr_store_supercap_monitor(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ pid_t pid;
+ int signal;
+ int result = sscanf(buf, "%i %i", &pid, &signal);
+
+ //button_info_t *button = button_by_monitor_name(attr->attr.name);
+
+ //if (!button) {
+ // return -ENODEV;
+ //}
+
+ if (result != 2) {
+ return -EINVAL;
+ }
+
+ if(result == 2) {
+ mutex_lock(&mts_io_mutex);
+
+ supercap.pid = pid;
+ supercap.signal = signal;
+
+ mutex_unlock(&mts_io_mutex);
+ }
+
+ return count;
+}
+
+static void supercap_worker(struct work_struct *ignored);
+
+static DECLARE_DELAYED_WORK(supercap_work, supercap_worker);
+
+static void supercap_worker(struct work_struct *ignored)
+{
+ struct gpio_pin *pin;
+ struct pid *vpid;
+ int running_on_cap = 0;
+
+ pin = gpio_pin_by_attr_name("power-fail");
+
+ if (pin) {
+ running_on_cap = !gpio_get_value(pin->pin.gpio);
+ }
+
+ if (supercap.pid > 0) {
+ vpid = find_vpid(supercap.pid);
+ }
+ if (vpid) {
+ if (running_on_cap == 0 && supercap.pwf_count == 0) {
+ schedule_delayed_work(&supercap_work, SUPERCAP_CHECK_INTERVAL);
+ }
+ else if ( (supercap.pwf_count >= 0) && (supercap.pwf_count < SUPERCAP_TOTAL_INTERVALS) ) {
+ /* check if 90% of checks were running_on_cap == 1 */
+ supercap.pwf_count++;
+ if (running_on_cap == 1) {
+ supercap.pin_is_one++;
+ }
+ if (supercap.pin_is_one >= 45) {
+ /* send configured signal to reset handler pid */
+ log_debug("Super Cap positives %d long signal", supercap.pin_is_one);
+ kill_pid(vpid, supercap.signal, 1);
+ /* reset and start over since hit the reset condition (maybe we should clean up and go away?) */
+ supercap.pwf_count = 0;
+ supercap.pin_is_one = 0;
+ }
+ }
+ else if (supercap.pwf_count == SUPERCAP_TOTAL_INTERVALS) {
+ /* reset and start over since didn't reach 90% at total intervals */
+ supercap.pwf_count = 0;
+ supercap.pin_is_one = 0;
+ }
+ } /* vpid */
+
+ schedule_delayed_work(&supercap_work, SUPERCAP_CHECK_INTERVAL);
+
+}
+
+void init_supercap_worker(void) {
+ supercap_worker(NULL);
+}
+
+void cleanup_sepercap_worker(void) {
+ cancel_delayed_work_sync(&supercap_work);
+}
+
+
+DEVICE_ATTR_MTS(dev_attr_supercap_monitor,
+ supercap.label_monitor,
+ mts_attr_show_supercap_monitor,
+ mts_attr_store_supercap_monitor);
diff --git a/io-module/mts_supercap.h b/io-module/mts_supercap.h
new file mode 100644
index 0000000..79ea7df
--- /dev/null
+++ b/io-module/mts_supercap.h
@@ -0,0 +1,42 @@
+#ifndef IO_MODULE_SUPERCAP_H_
+#define IO_MODULE_SUPERCAP_H_
+
+#include <linux/workqueue.h>
+#include <linux/pid.h>
+
+#include "mts_io.h"
+#include "mts_io_module.h"
+
+#define SUPERCAP_CHECKS_PER_SEC 10
+#define SUPERCAP_CHECK_INTERVAL (HZ / SUPERCAP_CHECKS_PER_SEC)
+#define SUPERCAP_TOTAL_INTERVALS 50 /* 5s */
+
+typedef struct supercap_info {
+ char name[32];
+ char label_monitor[32];
+
+ /* PID to notify */
+ pid_t pid;
+
+ /* signal to send */
+ int signal;
+
+ /* internal fields used in worker*/
+ int pwf_count; /* count of intervals in worker */
+ int pin_is_one; /* count of number of times pin has been set to one */
+
+} supercap_info_t, *supercap_info_pt;
+
+extern void init_supercap_worker(void);
+extern void cleanup_sepercap_worker(void);
+
+extern ssize_t mts_attr_show_supercap_monitor(struct device *dev,
+ struct device_attribute *attr,
+ char *buf);
+
+extern ssize_t mts_attr_store_supercap_monitor(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count);
+
+extern struct device_attribute dev_attr_supercap_monitor;
+
+#endif /* IO_MODULE_SUPERCAP_H_ */