diff options
author | Jeff Hatch <jhatch@multitech.com> | 2020-11-16 15:56:21 -0600 |
---|---|---|
committer | John Klug <john.klug@multitech.com> | 2020-11-23 14:22:34 -0600 |
commit | febfbaa141125c24d3a40e17034261c5354a0973 (patch) | |
tree | d16d84058fb005e0e5262b1a0bd16d63cd6c08f1 /io-module | |
parent | e8af5a62cb51f9bca1900c17b021cf5bc240c029 (diff) | |
download | mts-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.c | 2 | ||||
-rw-r--r-- | io-module/mts-io.c | 6 | ||||
-rw-r--r-- | io-module/mts_supercap.c | 128 | ||||
-rw-r--r-- | io-module/mts_supercap.h | 42 |
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_ */ |