diff options
| -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_ */ | 
