diff --git a/arch/arm/configs/seco_imx6_linux_defconfig b/arch/arm/configs/seco_imx6_linux_defconfig
index 6ca0833e437e7eda12134c3d4daf77d5db6d3e74..caa41561bc9decd7898485895f5692df0667cc4b 100644
--- a/arch/arm/configs/seco_imx6_linux_defconfig
+++ b/arch/arm/configs/seco_imx6_linux_defconfig
@@ -486,6 +486,7 @@ CONFIG_MXC_MLB150=y
 CONFIG_MXC_IPU_V3_PRE=y
 CONFIG_MXC_HDMI_CEC=y
 CONFIG_MXC_MIPI_CSI2=y
+CONFIG_ECTRL_MSP430=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT2_FS_POSIX_ACL=y
diff --git a/drivers/seco/Kconfig b/drivers/seco/Kconfig
index 583f216184c724e869c096ee216fe9b5b3e001c9..3894a67aa9e43bf3f2af1d7e48c2ca0fa70fd1e1 100644
--- a/drivers/seco/Kconfig
+++ b/drivers/seco/Kconfig
@@ -4,5 +4,12 @@
 
 menu "SECO mxc support"
 
+config ECTRL_MSP430
+	bool "Communication system with the Embedded Controller based on MSP430 MCU"
+	depends on I2C && ARCH_MXC
+	help
+		Say Y here if you want to use the Seco Communication System with the Embedded Controller.
+
+		if usure, say Y.
 
 endmenu
diff --git a/drivers/seco/Makefile b/drivers/seco/Makefile
index 9afb499c40371f838695cd057649347ce4a7c5e8..c442932e80a34d01ddc629d74d96b8d538ceb1d7 100644
--- a/drivers/seco/Makefile
+++ b/drivers/seco/Makefile
@@ -1,3 +1,6 @@
 #
 #  SECO system driver
 #
+
+obj-$(CONFIG_ECTRL_MSP430)        += ectrl_msp430.o
+
diff --git a/drivers/seco/ectrl_msp430.c b/drivers/seco/ectrl_msp430.c
new file mode 100644
index 0000000000000000000000000000000000000000..d7c468d77c170006651848f4bd5c4b07a5c143c6
--- /dev/null
+++ b/drivers/seco/ectrl_msp430.c
@@ -0,0 +1,5018 @@
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/input.h>
+#include <linux/i2c.h>
+#include <linux/proc_fs.h>
+#include <linux/platform_device.h>
+#include <linux/seq_file.h>
+#include <linux/delay.h>
+#include <linux/list.h>
+#include <linux/proc_fs.h>
+#include <linux/uaccess.h>
+#include <linux/workqueue.h>
+#include <linux/reboot.h>
+
+
+#include <linux/ectrl_msp430.h>
+#include <linux/ectrl_msp430_io.h>
+#include <dt-bindings/seco/ectrl_msp430.h>
+
+
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_irq.h>
+
+
+#define WDT_CTRL_REG                   0x00
+#define GINO_TASK_REG                  0x01
+#define DVI2LVDS_FLAGS_REG             0x02
+#define DATA_REG                       0x03
+#define INDEX_REG                      0x04
+#define WDT_DELAY_REG                  0x05
+#define WDT_TIMEOUT_REG                0x06
+#define WDT_TIMER1_REG                 0x07
+#define WDT_TIMER2_REG                 0x08
+#define WDT_CONFIG_REG                 0x09
+#define ADC_READING_0_REG              0x0A
+#define ADC_READING_1_REG              0x0B
+#define BUILDREV_REG                   0x0C
+#define FW_ID_REV_REG                  0x0E
+#define FLAG_REG                       0x0F 
+#define ENABLE_REG                     0x10
+#define STATUS_REG                     0x11
+
+/* Flash registers */
+#define ALWAYS_STATE_REG               0x01
+#define WDT_F_DELAY_REG_LSB            0x0A
+#define WDT_F_DELAY_REG_MSB            0x0B
+#define WDT_F_TIMEOUT_REG_LSB          0x0C
+#define WDT_F_TIMEOUT_REG_MSB          0x0D
+#define WDT_F_CONFIG_REG_LSB           0x0E
+#define WDT_F_CONFIG_REG_MSB           0x0F
+#define BOOT0_REG                      0x10
+#define BOOT1_REG                      0x11
+#define BOOT2_REG                      0x12
+#define BOOT3_REG                      0x13
+#define EN_FLASH_REG_LSB               0x14
+#define EN_FLASH_REG_MSB               0x15
+
+#define SBLOCK_CMD                     0x55AA
+#define HALT_CMD                       0x6101
+#define REBOOT_CMD                     0x6505
+
+#define ECTRL_POLL_PERIOD                   2  // (ms)
+#define ECTRL_POLL_PERIOD_SNOOPER_PWR_BTN   50 // (ms)
+
+#define MAX_LEN_NAME                   64
+#define MAX_LEN_LABEL                  32
+
+
+#define PWR_BUTTON                     0
+#define RST_BUTTON                     1
+#define SLEEP_SIGNAL                   2
+#define BATLOW_HL_SIGNAL               3	// when BATLOW becomes HIGH - battery charge low
+#define BATLOW_LH_SIGNAL               4 	// when BATLOW becomes LOW - battery full
+#define LID_HL_SIGNAL                  5	// when LID becomes HIGH
+#define LID_LH_SIGNAL                  6	// when LID becomes LOW
+#define WAKE_SIGNAL                    7
+#define PWR_BTN_4SEC                   8
+
+
+#define PWR_BUTTON_MASK_REG            0x0001
+#define RST_BUTTON_MASK_REG            0x0002
+#define SLEEP_SIGNAL_MASK_REG          0x0004
+#define BATLOW_HL_SIGNAL_MASK_REG      0x0008
+#define BATLOW_LH_SIGNAL_MASK_REG      0x0010
+#define LID_HL_SIGNAL_MASK_REG         0x0020
+#define LID_LH_SIGNAL_MASK_REG         0x0040
+#define WAKE_SIGNAL_MASK_REG           0x0080
+#define PWR_BTN_4SEC_MASK_REG          0x0100
+
+
+#define PWR_BUTTON_SHIFT_REG           0
+#define RST_BUTTON_SHIFT_REG           1
+#define SLEEP_SIGNAL_SHIFT_REG         2
+#define BATLOW_HL_SIGNAL_SHIFT_REG     3
+#define BATLOW_LH_SIGNAL_SHIFT_REG     4
+#define LID_HL_SIGNAL_SHIFT_REG        5
+#define LID_LH_SIGNAL_SHIFT_REG        6
+#define WAKE_SIGNAL_SHIFT_REG          7
+#define PWR_BTN_4SEC_SHIFT_REG         8
+
+
+#define PWR_BUTTON_NAME                "PowerButton"
+#define RST_BUTTON_NAME                "ResetButton"
+#define SLEEP_SIGNAL_NAME              "Sleep"
+#define BATLOW_HL_SIGNAL_NAME          "BatteryLow_H2L"
+#define BATLOW_LH_SIGNAL_NAME          "BatteryLow_L2H"
+#define LID_HL_SIGNAL_NAME             "Lid_H2L"
+#define LID_LH_SIGNAL_NAME             "Lid_L2H"
+#define WAKE_SIGNAL_NAME               "Wake"
+#define PWR_BTN_4SEC_NAME              "PoworButton4Sec"
+
+
+#define PWR_BUTTON_LABEL               "power_button"
+#define RST_BUTTON_LABEL               "reset_button"
+#define SLEEP_SIGNAL_LABEL             "sleep"
+#define BATLOW_HL_SIGNAL_LABEL         "battery_low_h2l"
+#define BATLOW_LH_SIGNAL_LABEL         "battery_low_l2h"
+#define LID_HL_SIGNAL_LABEL            "lid_h2l"
+#define LID_LH_SIGNAL_LABEL            "lid_l2h"
+#define WAKE_SIGNAL_LABEL              "wake"
+#define PWR_BTN_4SEC_LABEL             "pwr_btn_4sec"
+
+
+#define EVNT_PWR_BTN_STATE_LABEL       "power_button"
+#define EVNT_RST_BTN_STATE_LABEL       "reset_button"
+#define EVNT_SLEEP_STATE_LABEL         "sleep"
+#define EVNT_BATTERY_STATE_LABEL       "battery_low"
+#define EVNT_LID_STATE_LABEL           "lid"
+#define EVNT_WAKE_STATE_LABEL          "wake"
+
+
+#define PM_STATE_ALWAYS_ON             "always_on"
+#define PM_STATE_ALWAYS_OFF            "always_off"
+
+#define ALWAYS_ON                      0x0055
+#define ALWAYS_OFF                     0x0000 
+
+
+#define WDT_SHIFT_ENABLE               0
+#define WDT_SHIFT_EVENT                1
+
+#define WDT_MASK_ENABLE                (0x0001 << WDT_SHIFT_ENABLE)
+#define WDT_MASK_EVENT                 (0x0007 << WDT_SHIFT_EVENT)
+
+#define WDT_CTRL_WDTOUT_RESET          (0x0001 << 8) // Auto Resettable Byte
+#define WDT_CTRL_WDTOUT_TRIGGER        (0x0002 << 8) // Auto Resettable Byte
+
+#define INPUT_DEV_NAME                 "Embedded Controller"
+
+#define ECTRL_USE_OWN_STATE            0
+
+/*  ID used to code the board  (read from Embedded Controller)  */
+#define BOARD_928_ID                   0x28
+#define BOARD_962_ID                   0x62
+#define BOARD_984_ID                   0x84
+#define BOARD_B38_ID                   0x38
+
+
+#define DRV_VERSION                    "1.0"
+
+#define ECTRL_INFO(fmt, arg...)        printk(KERN_INFO "Embedded Controller: " fmt "\n" , ## arg)
+#define ECTRL_ERR(fmt, arg...)         printk(KERN_ERR "%s: " fmt "\n" , __func__ , ## arg)
+#define ECTRL_DBG(fmt, arg...)         pr_debug("%s: " fmt "\n" , __func__ , ## arg)
+
+
+/*  ############ LOGGING ############  */
+#define ECTRL_LOGGING                  0
+
+
+/*  element index of the structures relative to the boards  */
+#define BOARD_928                      0
+#define BOARD_962                      1
+#define BOARD_984                      2
+#define BOARD_B38                      3
+
+static int board_nr_states [] = {
+	[BOARD_928] = 6,
+	[BOARD_962] = 5,
+	[BOARD_984] = 5,
+	[BOARD_B38] = 5,
+};
+
+
+static char board_name [][30] = {
+	[BOARD_928] = "Quadmo747 (Q7) - 928",
+	[BOARD_962] = "uQ7 - 962",
+	[BOARD_984] = "uSBC - 984",
+	[BOARD_B38] = "SBC B38",
+};
+
+
+/*  Maps the event to the relative index into the register 
+ *  (-1 if the event is not available for the board)  
+ */
+static int board_reg_state_idx [][8] = {
+	[BOARD_928] = {
+		[EVNT_PWR_BTN] =  1,
+		[EVNT_RST_BTN] =  2,
+		[EVNT_SLEEP]   =  4,
+		[EVNT_BATTERY] =  5,
+		[EVNT_LID]     =  6,
+		[EVNT_WAKE]    =  3,
+	},
+	[BOARD_962] = {
+		[EVNT_PWR_BTN] =  1,
+		[EVNT_RST_BTN] =  2,
+		[EVNT_SLEEP]   =  4,
+		[EVNT_BATTERY] =  5,
+		[EVNT_LID]     = -1,
+		[EVNT_WAKE]    =  3,
+	},
+	[BOARD_984] = {
+		[EVNT_PWR_BTN] =  1,
+		[EVNT_RST_BTN] =  2,
+		[EVNT_SLEEP]   =  4,
+		[EVNT_BATTERY] =  5,
+		[EVNT_LID]     = -1,
+		[EVNT_WAKE]    =  3,
+	},
+	[BOARD_B38] = {
+		[EVNT_PWR_BTN] =  1,
+		[EVNT_RST_BTN] =  2,
+		[EVNT_SLEEP]   =  4,
+		[EVNT_BATTERY] =  5,
+		[EVNT_LID]     = -1,
+		[EVNT_WAKE]    =  3,
+	},
+
+};
+
+
+
+struct event_dev {
+	unsigned short int      id;
+	char                    name[MAX_LEN_NAME];
+	char                    label[MAX_LEN_LABEL];
+	unsigned int            index_reg;
+	unsigned int            shift;
+	struct proc_dir_entry   *proc_dir; 
+	struct input_dev        *input;
+	char                    input_name[MAX_LEN_NAME];
+};
+
+
+#define EVENT_DEFINE(_event)						\
+	[_event] = {							\
+		.id          = _event,					\
+		.name        = _event ## _NAME,				\
+		.label       = _event ## _LABEL,			\
+		.index_reg   = _event ## _MASK_REG,			\
+		.shift       = _event ## _SHIFT_REG,			\
+		.proc_dir    = NULL,					\
+		.input       = NULL,					\
+		.input_name  = INPUT_DEV_NAME " - " _event ## _LABEL	\
+	}	
+
+
+#define EVENT_NO_SIGNAL_DEFINE(_event)					\
+	[_event] = {							\
+		.id          = _event,					\
+		.name        = _event ## _NAME,				\
+		.label       = "",	   				\
+		.index_reg   = _event ## _MASK_REG,			\
+		.shift       = _event ## _SHIFT_REG,			\
+		.proc_dir    = NULL,					\
+		.input       = NULL,					\
+		.input_name  = ""					\
+	}	
+
+
+/*  Main sructure list of all fasible events  */
+static struct event_dev global_event_list [] = {
+	EVENT_DEFINE(PWR_BUTTON),
+	EVENT_DEFINE(RST_BUTTON),
+	EVENT_DEFINE(SLEEP_SIGNAL),
+	EVENT_DEFINE(BATLOW_HL_SIGNAL),
+	EVENT_DEFINE(BATLOW_LH_SIGNAL),
+	EVENT_DEFINE(LID_HL_SIGNAL),
+	EVENT_DEFINE(LID_LH_SIGNAL),
+	EVENT_DEFINE(WAKE_SIGNAL),
+	EVENT_NO_SIGNAL_DEFINE(PWR_BTN_4SEC),
+};
+
+
+struct event_state {
+	enum ECTRL_EVENTS    evn;
+	int                  reg_idx;
+	char                 *label;
+};
+
+
+#define EVENT_STATE_DEFINE(_event)			\
+	[_event] = {					\
+		.evn      = _event,			\
+		.reg_idx  = -1,				\
+		.label    = _event ## _STATE_LABEL	\
+	}
+
+
+static struct event_state event_state_list [] = {
+	EVENT_STATE_DEFINE(EVNT_PWR_BTN),  
+	EVENT_STATE_DEFINE(EVNT_RST_BTN),  
+	EVENT_STATE_DEFINE(EVNT_SLEEP), 
+	EVENT_STATE_DEFINE(EVNT_BATTERY),
+	EVENT_STATE_DEFINE(EVNT_LID),   
+	EVENT_STATE_DEFINE(EVNT_WAKE),
+};  
+
+
+
+static char *PM_PWR_STATE[] = {
+	PM_STATE_ALWAYS_OFF,
+	PM_STATE_ALWAYS_ON,
+};
+
+
+enum BOOTDEV_ID {
+	BOOTDEV_ID0  =  (u8)0,
+	BOOTDEV_ID1  =  (u8)1,
+	BOOTDEV_ID2  =  (u8)2,
+	BOOTDEV_ID3  =  (u8)3,
+};
+
+
+struct bootdev {
+        enum BOOTDEV_ID   id;
+        const char        *label;
+};
+
+
+#define BOOT_IDX0   0
+#define BOOT_IDX1   1
+#define BOOT_IDX2   2
+#define BOOT_IDX3   3
+
+
+struct wdt_event_element {
+	enum wdt_event id;
+	char           *label;
+
+};
+
+
+#define WDT_EVENT_DEFINE(wdt_evnt, name)	\
+	[wdt_evnt] = {				\
+		.id = wdt_evnt,			\
+		.label = name,			\
+	}
+
+
+static struct wdt_event_element wdt_evnt_list [] = {
+	WDT_EVENT_DEFINE(WDT_EVNT_WDOUT, "wdout"),
+	WDT_EVENT_DEFINE(WDT_EVNT_RESET, "reset"),
+	WDT_EVENT_DEFINE(WDT_EVNT_PWRBTN1SEC, "power_button_1sec"),
+	WDT_EVENT_DEFINE(WDT_EVNT_PWRBTN4SEC, "power_button_4sec"),
+	WDT_EVENT_DEFINE(WDT_EVNT_BOOT_RECOVERY, "boot_recovery"),
+};
+
+
+/*  Main structure, used by whole driver  */
+struct econtroller {
+	/*  I2C client  */
+	struct i2c_client             *client;
+	/*  board identificator  */
+	int                           board_id;
+	/*  list of all feasible events for the current board  */
+	struct event_dev              **events;
+	int                           nr_evnt;
+
+	struct event_state            **evn_state;
+	int                           nr_evn;
+	struct bootdev                *bootdev_list;
+	int                           nr_bootdev;
+	struct wdt_event_element      *wdt_event_list;
+	int                           nr_wdt_event;
+	void 		              (*task_pre_halt_signal) (void);
+	void                          (*task_post_halt_signal) (void);
+	int		              irq;
+	unsigned int                  irq_flags;
+	char                          *phys;
+	struct delayed_work           work;
+	struct delayed_work           work_snooper_pwr_btn;
+	unsigned long                 poll_period;
+	unsigned long                 poll_period_snooper_pwr_btn;
+	unsigned long                 orig_jiffies; //used only for the power button snooping
+	struct mutex                  fs_lock;
+	struct mutex                  ioctl_lock;
+};
+
+
+struct ectrl_proc_event {
+	struct econtroller  *ectrl;
+	int                 event;
+	int                 is_true_event : 1;
+};
+
+
+struct ectrl_proc_event_state {
+	struct econtroller  *ectrl;
+	int                 state_id;
+};
+
+
+struct ectrl_proc_boot {
+	struct econtroller   *ectrl;
+	int                  idx;
+};
+
+
+struct snooper_work {
+	struct econtroller   *ectrl;
+	unsigned long        orig_jiffies;
+};
+
+
+static struct econtroller *ectrl;
+
+static unsigned long  last_jiffies_communication;
+static struct mutex   comm_lock;
+
+static struct ectrl_reg_rw reg_halt[] = {
+	{
+		.op   = WVE_OP,
+		.reg  = {
+				.addr = SBLOCK_CMD,
+				.data = 0x0001,
+
+			},
+	},
+	{
+		.op   = WVE_OP,
+		.reg  = { 
+				.addr = HALT_CMD,
+				.data = 0x0001,
+			},
+	},
+	{
+		.op   = STOP_OP,
+		.reg  = {
+				.addr = 0,
+				.data = 0,
+			},
+	},
+};
+
+static struct ectrl_reg_rw reg_reboot[] = {
+	{
+		.op   = WVE_OP,
+		.reg  = {
+				.addr = SBLOCK_CMD,
+				.data = 0x0001,
+			},
+	},
+	{
+		.op   = WVE_OP,
+		.reg  = {
+				.addr = REBOOT_CMD,
+				.data = 0x0001,
+			},
+	},
+	{
+		.op   = STOP_OP,
+		.reg  = {
+				.addr = 0,
+				.data = 0,
+			},
+	},
+};
+
+static struct ectrl_reg_rw reg_en_flash[] = {
+	{
+		.op   = WVE_OP,
+		.reg  = {
+				.addr = SBLOCK_CMD,
+				.data = 0x0001,
+			},
+	},
+	{
+		.op   = WVE_OP,
+		.reg  = {
+				.addr = EN_FLASH_REG_LSB,
+				.data = 0x0,
+			},
+	},
+	{
+		.op   = WVE_OP,
+		.reg  = {
+				.addr = SBLOCK_CMD,
+				.data = 0x0001,
+			},
+	},
+	{
+		.op   = WVE_OP,
+		.reg  = {
+				.addr = EN_FLASH_REG_MSB,
+				.data = 0x0,
+			},
+	},
+
+	{
+		.op   = STOP_OP,
+		.reg  = {
+				.addr = 0,
+				.data = 0,
+			},
+	},
+};
+
+static struct ectrl_reg_rw reg_boot_idx0[] = {
+	{
+		.op   = WVE_OP,
+		.reg  = {
+				.addr = SBLOCK_CMD,
+				.data = 0x0001,
+			},
+	},
+	{
+		.op   = WVE_OP,
+		.reg  = {
+				.addr = BOOT0_REG,
+				.data = 0x0,
+			},
+	},
+	{
+		.op   = STOP_OP,
+		.reg  = {
+				.addr = 0,
+				.data = 0,
+			},
+	},
+};
+
+static struct ectrl_reg_rw reg_boot_idx1[] = {
+	{
+		.op   = WVE_OP,
+		.reg  = {
+				.addr = SBLOCK_CMD,
+				.data = 0x0001,
+			},
+	},
+	{
+		.op   = WVE_OP,
+		.reg  = {
+				.addr = BOOT1_REG,
+				.data = 0x0,
+			},
+	},
+	{
+		.op   = STOP_OP,
+		.reg  = {
+				.addr = 0,
+				.data = 0,
+			},
+	},
+};
+
+static struct ectrl_reg_rw reg_boot_idx2[] = {
+	{
+		.op   = WVE_OP,
+		.reg  = {
+				.addr = SBLOCK_CMD,
+				.data = 0x0001,
+			},
+	},
+	{
+		.op   = WVE_OP,
+		.reg  = {
+				.addr = BOOT2_REG,
+				.data = 0x0,
+			},
+	},
+	{
+		.op   = STOP_OP,
+		.reg  = {
+				.addr = 0,
+				.data = 0,
+			},
+	},
+};
+
+static struct ectrl_reg_rw reg_boot_idx3[] = {
+	{
+		.op   = WVE_OP,
+		.reg  = {
+				.addr = SBLOCK_CMD,
+				.data = 0x0001,
+			},
+	},
+	{
+		.op   = WVE_OP,
+		.reg  = {
+				.addr = BOOT3_REG,
+				.data = 0x0,
+			},
+	},
+	{
+		.op   = STOP_OP,
+		.reg  = {
+				.addr = 0,
+				.data = 0,
+			},
+	},
+};
+
+static struct ectrl_reg_rw reg_wdt_delay[] = {
+	{
+		.op   = WVE_OP,
+		.reg  = {
+				.addr = SBLOCK_CMD,
+				.data = 0x0001,
+			},
+	},
+	{
+		.op   = WVE_OP,
+		.reg  = {
+				.addr = WDT_F_DELAY_REG_LSB,
+				.data = 0x0,
+			},
+	},
+	{
+		.op   = WVE_OP,
+		.reg  = {
+				.addr = SBLOCK_CMD,
+				.data = 0x0001,
+			},
+	},
+	{
+		.op   = WVE_OP,
+		.reg  = {
+				.addr = WDT_F_DELAY_REG_MSB,
+				.data = 0x0,
+			},
+	},
+
+	{
+		.op   = STOP_OP,
+		.reg  = {
+				.addr = 0,
+				.data = 0,
+			},
+	},
+};
+
+static struct ectrl_reg_rw reg_wdt_timeout[] = {
+	{
+		.op   = WVE_OP,
+		.reg  = {
+				.addr = SBLOCK_CMD,
+				.data = 0x0001,
+			},
+	},
+	{
+		.op   = WVE_OP,
+		.reg  = {
+				.addr = WDT_F_TIMEOUT_REG_LSB,
+				.data = 0x0,
+			},
+	},
+	{
+		.op   = WVE_OP,
+		.reg  = {
+				.addr = SBLOCK_CMD,
+				.data = 0x0001,
+			},
+	},
+	{
+		.op   = WVE_OP,
+		.reg  = {
+				.addr = WDT_F_TIMEOUT_REG_MSB,
+				.data = 0x0,
+			},
+	},
+
+	{
+		.op   = STOP_OP,
+		.reg  = {
+				.addr = 0,
+				.data = 0,
+			},
+	},
+};
+
+static struct ectrl_reg_rw reg_wdt_config[] = {
+	{
+		.op   = WVE_OP,
+		.reg  = {
+				.addr = SBLOCK_CMD,
+				.data = 0x0001,
+			},
+	},
+	{
+		.op   = WVE_OP,
+		.reg  = {
+				.addr = WDT_F_CONFIG_REG_LSB,
+				.data = 0x0,
+			},
+	},
+	{
+		.op   = WVE_OP,
+		.reg  = {
+				.addr = SBLOCK_CMD,
+				.data = 0x0001,
+			},
+	},
+	{
+		.op   = WVE_OP,
+		.reg  = {
+				.addr = WDT_F_CONFIG_REG_MSB,
+				.data = 0x0,
+			},
+	},
+
+	{
+		.op   = STOP_OP,
+		.reg  = {
+				.addr = 0,
+				.data = 0,
+			},
+	},
+};
+
+static struct ectrl_reg_rw reg_pm_always_state[] = {
+	{
+		.op   = WVE_OP,
+		.reg  = {
+				.addr = SBLOCK_CMD,
+				.data = 0x0001,
+			},
+	},
+	{
+		.op   = WVE_OP,
+		.reg  = {
+				.addr = ALWAYS_STATE_REG,
+				.data = 0x0,
+			},
+	},
+	{
+		.op   = STOP_OP,
+		.reg  = {
+				.addr = 0,
+				.data = 0,
+			},
+	},
+};
+
+
+/* --------------------------------------------------------------------------
+                                 LOGGING FUNCTIONS
+   -------------------------------------------------------------------------- */
+#if ECTRL_LOGGING
+
+#define LOG_OP_WRITE   'w'
+#define LOG_OP_READ    'r'
+
+struct logger_entry {
+	unsigned int      time;
+	char              op;
+	u16               address;
+	u16               data;
+	struct list_head  list;
+};
+
+static struct mutex         logger_lock;
+static struct logger_entry  *logger_list;
+
+#define log_list_add(item, head, uop, addr, udata)       item = kzalloc (sizeof (struct logger_entry), GFP_KERNEL); \
+							item->address = addr; \
+							item->data = udata; \
+							item->op = op; \
+							item->time = jiffies_to_msecs (jiffies); \
+							list_add_tail (&item->list, &head->list)
+
+
+static inline void logger_insert (char op, u16 addr, u16 data) {
+	struct logger_entry *tmp;
+	if ( !logger_list )
+		return;
+	mutex_lock (&logger_lock);
+	log_list_add (tmp, logger_list, op, addr, data);
+	mutex_unlock (&logger_lock);
+}
+
+
+static inline void logger_del_all (void) {
+	struct list_head *pos, *q;
+	struct logger_entry *tmp;
+
+	if ( !logger_list )
+		return;
+
+	mutex_lock (&logger_lock);
+	list_for_each_safe (pos, q, &logger_list->list) {
+		tmp = list_entry (pos, struct logger_entry, list);
+		list_del (pos);
+		kfree (tmp);
+	}
+	mutex_unlock (&logger_lock);
+}
+
+#endif /* ECTRL_LOGGING */
+
+/* --------------------------------------------------------------------------
+                                 BASIC FUNCTIONS
+   -------------------------------------------------------------------------- */
+
+static inline void ectrl_com_timing (unsigned int time_delay) {
+	while ( !time_after(jiffies, last_jiffies_communication + msecs_to_jiffies(time_delay)) ) {
+		schedule();
+	}
+}
+
+
+static inline u16 ectrl_read_data_no_blocking (struct i2c_client *client, u16 addr) {
+	s32 data;
+	u16 val;
+	data = i2c_smbus_read_word_data(client, (u8)addr);
+	/*  update time last communication */
+	last_jiffies_communication = jiffies;
+	if (data < 0) {
+		dev_err(&client->dev, "i2c io (read) error: %d\n", data);
+		return data;
+	}
+	val = (u16)data;
+#if ECTRL_LOGGING
+	logger_insert (LOG_OP_READ, addr, val);
+#endif /* ECTRL_LOGGING */
+	dev_dbg(&client->dev, "data: 0x%x, val: 0x%x\n", data, val);
+	return val;
+}
+
+
+static inline u16 ectrl_read_data (struct i2c_client *client, u16 addr) {
+	u16 val;
+	mutex_lock (&comm_lock);
+	val = ectrl_read_data_no_blocking (client, addr);
+	mutex_unlock (&comm_lock);
+	return val;
+}
+
+
+static inline u16 ectrl_write_data_no_blocking (struct i2c_client *client, u16 addr, u16 data) {
+	u16 ret = i2c_smbus_write_word_data(client, (u8)addr, data);
+	/*  update time last communication */
+	last_jiffies_communication = jiffies;
+#if ECTRL_LOGGING
+	logger_insert (LOG_OP_WRITE, addr, data);
+#endif /* ECTRL_LOGGING */
+	return ret;
+}
+
+
+static inline u16 ectrl_write_data (struct i2c_client *client, u16 addr, u16 data) {
+	u16 val;
+	mutex_lock (&comm_lock);
+	val = ectrl_write_data_no_blocking (client, addr, data);
+	mutex_unlock (&comm_lock);
+	return val;
+}
+
+
+static inline u16 ectrl_read_vector_element_no_blocking (struct i2c_client *client, u16 addr) {
+	int retval;
+	ectrl_com_timing (110); // needed to access to the flash of the embedded controller
+	retval = ectrl_write_data_no_blocking (client, INDEX_REG, addr);
+	if (!(retval < 0)) {
+		ectrl_com_timing (90); // needed to access to the flash of the embedded controller
+		retval = ectrl_read_data_no_blocking (client, DATA_REG);
+	}
+	return (u16)retval;
+}
+
+
+static inline u16 ectrl_read_vector_element (struct i2c_client *client, u16 addr) {
+	u16 val;
+	mutex_lock (&comm_lock);
+	val = ectrl_read_vector_element_no_blocking (client, addr);
+	mutex_unlock (&comm_lock);
+	return val;
+}
+
+
+static inline u16 ectrl_write_vector_element_no_blocking (struct i2c_client *client, u16 addr, u16 data) {
+	int retval;
+	ectrl_com_timing (110); // needed to access to the flash of the embedded controller
+	retval = ectrl_write_data_no_blocking (client, DATA_REG, data);
+	/*  update time last communication */
+	last_jiffies_communication = jiffies;
+	if (!(retval < 0)) {
+		ectrl_com_timing (90); // needed to access to the flash of the embedded controller
+		retval = ectrl_write_data_no_blocking (client, INDEX_REG, addr);
+	}
+	return (u16)retval;
+}
+
+
+static inline u16 ectrl_write_vector_element (struct i2c_client *client, u16 addr, u16 data) {
+	u16 val;
+	mutex_lock (&comm_lock);
+	val = ectrl_write_vector_element_no_blocking (client, addr, data);
+	mutex_unlock (&comm_lock);
+	return val;
+}
+
+
+static int ectrl_mem_single_op (struct i2c_client *client, struct ectrl_reg_rw *reg_rw) {
+	int retval = 0;
+
+	u16 val;
+	switch (reg_rw->op) {
+		case R_OP:
+			val = ectrl_read_data_no_blocking (client, reg_rw->reg.addr);
+			if (val >= 0) {
+				dev_dbg(&client->dev, "read data done: 0x%x\n", val);
+				reg_rw->reg.data = val;	
+				retval = 1;
+			} else {
+				dev_err(&client->dev, "read data failed: 0x%x\n", val);
+				retval = -1;
+			}
+			break;
+		case W_OP:
+			val = ectrl_write_data_no_blocking (client, reg_rw->reg.addr, reg_rw->reg.data);
+			if (val >= 0) {
+				dev_dbg(&client->dev, "write data done: addr 0x%x  data 0x%x\n", reg_rw->reg.addr, reg_rw->reg.data);
+				retval = 0;
+			} else {
+				dev_err(&client->dev, "write data failed: addr 0x%x  data 0x%x\n", reg_rw->reg.addr, reg_rw->reg.data);
+				retval = -1;
+			}
+			break;
+		case RVE_OP:
+			val = ectrl_read_vector_element_no_blocking (client, reg_rw->reg.addr);
+			if (val >= 0) {
+				dev_dbg(&client->dev, "read vector element done: 0x%x", val);
+				reg_rw->reg.data = val;
+				retval = 1;
+			} else {
+				dev_err(&client->dev, "read vector's element failed: 0x%x\n", val);
+				retval = -1;
+			}
+			break;
+		case WVE_OP:
+			val = ectrl_write_vector_element_no_blocking (client, reg_rw->reg.addr, reg_rw->reg.data);
+			if (val >= 0) {
+				dev_dbg(&client->dev, "write vector's element done: addr 0x%x  data 0x%x\n", reg_rw->reg.addr, reg_rw->reg.data);
+				retval = 1;		
+			} else {
+				dev_err(&client->dev, "write vector's element failed: addr 0x%x  data 0x%x\n", reg_rw->reg.addr, reg_rw->reg.data);
+				retval = -1;
+			}
+			break;
+		default:
+			dev_dbg(&client->dev, "invalid operation!\n");
+	 		retval = -1;
+	}
+	return retval;
+}
+
+
+static int ectrl_mem_op (struct i2c_client *client, struct ectrl_reg_rw regs[], struct data_list *data_l) {
+	struct ectrl_reg_rw *next = regs;
+	struct data_list *tmp;
+	int retval = 0;
+	int val;
+	mutex_lock (&comm_lock);
+	for (; next->op != STOP_OP ; next++) {
+		val = ectrl_mem_single_op (client, next);
+		if (val < 0) {
+			mutex_unlock (&comm_lock);
+			return val;
+		}
+		if (val > 0) {
+			if (data_l != NULL) {
+				tmp = kzalloc (sizeof (struct data_list), GFP_KERNEL);
+				tmp->data = next->reg.data;
+				list_add (&(tmp->list), &(data_l->list));
+			}
+		}
+		retval += val;
+	}
+	mutex_unlock (&comm_lock);
+	return retval;
+}
+
+
+static int get_reg_rw (struct ectrl_reg_rw *reg_rw, struct ectrl_reg reg, int op) {
+	reg_rw->op = op;
+	reg_rw->reg.data = reg.data;
+	reg_rw->reg.addr = reg.addr;
+	return 0;
+}
+
+
+
+/* --------------------------------------------------------------------------
+                              ADVANCED FUNCTIONS
+   -------------------------------------------------------------------------- */
+
+			/* DATA FUNCTIONS */
+
+#define getBoardID(client)    (ectrl_read_data ((client), FW_ID_REV_REG) & 0xFF00) >> 8
+
+
+
+			/* EVENT FUNCTIONS */
+
+#define getStatusReg(client)    ectrl_read_data ((client), STATUS_REG)
+#define getFlagReg(client)      ectrl_read_data ((client), FLAG_REG)
+#define getEnableReg(client)    ectrl_read_data ((client), ENABLE_REG)
+#define getEnFlashReg(client)   (ectrl_read_vector_element ((client), EN_FLASH_REG_MSB) << 8) | \
+				ectrl_read_vector_element ((client), EN_FLASH_REG_LSB)  
+
+#define setFlagReg(client, regv)      ectrl_write_data ((client), FLAG_REG, (regv))
+#define setEnableReg(client, regv)    ectrl_write_data ((client), ENABLE_REG, (regv))
+#define setEnFlashReg(client, regv)   reg_en_flash[1].reg.data = (regv) & 0x00FF;  \
+		   		      reg_en_flash[3].reg.data = ((regv) >> 8) & 0x00FF;  \
+                                      ectrl_mem_op ((client), reg_en_flash, NULL) 
+
+
+static inline int getStatus (struct i2c_client *client, int reg_idx) {
+	int reg = (int)getStatusReg(client);
+	return ((reg >> (reg_idx)) & 0x1);
+}
+
+	
+static inline int getFlag (struct i2c_client *client, int event) {
+	int reg = (int)getFlagReg(client);
+	return (reg & global_event_list[event].index_reg) >> global_event_list[event].shift;
+}
+
+
+static inline int getEnable (struct i2c_client *client, int event) {
+	int reg = (int)getEnableReg(client);
+	return (reg & global_event_list[event].index_reg) >> global_event_list[event].shift;
+}
+
+
+static inline int getEnFlash (struct i2c_client *client, int event) {
+	int reg = (int)getEnFlashReg(client);
+	return (reg & global_event_list[event].index_reg) >> global_event_list[event].shift;
+}
+
+
+static inline void setFlag (struct i2c_client *client, int event, int set) {
+	int reg = (int)getFlagReg(client);
+	reg = (set) ? reg | (1u << global_event_list[event].shift) : reg & ~(1u << global_event_list[event].shift);
+	setFlagReg(client, reg);	
+}
+
+
+static inline void setEnable (struct i2c_client *client, int event, int set) {
+	int reg = (int)getEnableReg(client);
+	reg = (set) ? reg | (1u << global_event_list[event].shift) : reg & ~(1u << global_event_list[event].shift);
+	setEnableReg(client, reg);	
+}
+
+
+static inline void setEnFlash (struct i2c_client *client, int event, int set) {
+	int reg = (int)getEnFlashReg(client);
+	reg = (set) ? reg | (1u << global_event_list[event].shift) : reg & ~(1u << global_event_list[event].shift);
+	setEnFlashReg(client, reg);	
+}
+
+
+static int is_feasibleEvent (struct econtroller *ectrl, unsigned short int id) {
+	int i;
+	int find = 0;
+
+	for (i = 0 ; i < ectrl->nr_evnt ; i++) {
+		if ( ectrl->events[i]->id == id ) {
+			find = 1;
+			break;
+		}
+	}
+
+	return find;
+}
+
+			/* POWER MANAGEMENT FUNCTIONS */
+
+#define PMgetAlwaysState(client)             ectrl_read_vector_element ((client), ALWAYS_STATE_REG)
+#define PMsetAlwaysState(client, state)      reg_pm_always_state[1].reg.data = (state); \
+                                             ectrl_mem_op ((client), reg_pm_always_state, NULL)
+
+
+			/* BOOT FUNCTIONS */
+
+#define BOOT_SEQUENCE_LENGTH         4
+#define IS_VALID_BOOT_SEQ_IDX(idx)   ((idx) >= 0 && (idx) < BOOT_SEQUENCE_LENGTH) ? 1 : 0
+
+#define getBoot0Reg(client)        ectrl_read_vector_element ((client), BOOT0_REG)
+#define getBoot1Reg(client)        ectrl_read_vector_element ((client), BOOT1_REG)
+#define getBoot2Reg(client)        ectrl_read_vector_element ((client), BOOT2_REG)
+#define getBoot3Reg(client)        ectrl_read_vector_element ((client), BOOT3_REG)
+
+#define setBoot0Reg(client, regv)   reg_boot_idx0[1].reg.data = (regv); \
+ 				    ectrl_mem_op ((client), reg_boot_idx0, NULL)
+#define setBoot1Reg(client, regv)   reg_boot_idx1[1].reg.data = (regv); \
+ 				    ectrl_mem_op ((client), reg_boot_idx1, NULL)
+#define setBoot2Reg(client, regv)   reg_boot_idx2[1].reg.data = (regv); \
+ 				    ectrl_mem_op ((client), reg_boot_idx2, NULL)
+#define setBoot3Reg(client, regv)   reg_boot_idx3[1].reg.data = (regv); \
+ 				    ectrl_mem_op ((client), reg_boot_idx3, NULL)
+
+
+
+static int isAvaildableBootdev (struct econtroller *ectrl, enum BOOTDEV_ID id) {
+	int i, isValid = -1;
+	for (i = 0 ; i < ectrl->nr_bootdev ; i++) {
+		if (ectrl->bootdev_list[i].id == id) {
+			isValid = i;
+			break;
+		}
+	}
+	return isValid;
+}
+
+
+static int getBootDev (struct econtroller *ectrl, int boot_idx) {
+	int reg_val;
+	switch (boot_idx) {
+		case BOOT_IDX0:
+			reg_val = getBoot0Reg(ectrl->client);
+			break;
+		case BOOT_IDX1:
+			reg_val = getBoot1Reg(ectrl->client);
+			break;
+		case BOOT_IDX2:
+			reg_val = getBoot2Reg(ectrl->client);
+			break;
+		case BOOT_IDX3:
+			reg_val = getBoot3Reg(ectrl->client);
+			break;
+		default:
+			reg_val = -1;
+	}
+	return reg_val;
+}
+
+
+static int setBootDev (struct econtroller *ectrl, int boot_idx, enum BOOTDEV_ID bootdev_id) {
+	if (isAvaildableBootdev (ectrl, bootdev_id) < 0)
+		return -1;
+	else {
+		switch (boot_idx) {
+			case BOOT_IDX0:
+				setBoot0Reg(ectrl->client, (int)bootdev_id);
+				break;
+			case BOOT_IDX1:
+				setBoot1Reg(ectrl->client, (int)bootdev_id);
+				break;
+			case BOOT_IDX2:
+				setBoot2Reg(ectrl->client, (int)bootdev_id);
+				break;
+			case BOOT_IDX3:
+				setBoot3Reg(ectrl->client, (int)bootdev_id);
+				break;
+			default:
+				return -1;
+		}
+	}
+	return boot_idx;	
+}
+
+
+
+			/* WATCHDOG FUNCTIONS */
+
+
+#define WDTgetEnableReg(client)    (ectrl_read_data ((client), WDT_CONFIG_REG) & \
+					WDT_MASK_ENABLE) >> WDT_SHIFT_ENABLE
+#define WDTgetEventReg(client)     (ectrl_read_data ((client), WDT_CONFIG_REG) & \
+					WDT_MASK_EVENT) >> WDT_SHIFT_EVENT
+#define WDTgetDelayReg(client)     (ectrl_read_data ((client), WDT_DELAY_REG))
+#define WDTgetTimeoutReg(client)   (ectrl_read_data ((client), WDT_TIMEOUT_REG))
+#define WDTgetTimer1Reg(client)    (ectrl_read_data ((client), WDT_TIMER1_REG))
+#define WDTgetTimer2Reg(client)    (ectrl_read_data ((client), WDT_TIMER2_REG))
+
+
+#define WDT_F_getDelayReg(client)    (ectrl_read_vector_element ((client), WDT_F_DELAY_REG_MSB) << 8) |  \
+				     ectrl_read_vector_element ((client), WDT_F_DELAY_REG_LSB)
+#define WDT_F_getTimeoutReg(client)  (ectrl_read_vector_element ((client), WDT_F_TIMEOUT_REG_MSB) << 8) |  \
+				     ectrl_read_vector_element ((client), WDT_F_TIMEOUT_REG_LSB)
+#define WDT_F_getEnableReg(client)   (ectrl_read_vector_element ((client), WDT_F_CONFIG_REG_LSB) & \
+					WDT_MASK_ENABLE) >> WDT_SHIFT_ENABLE
+#define WDT_F_getEventReg(client)    (ectrl_read_vector_element ((client), WDT_F_CONFIG_REG_LSB) & \
+					WDT_MASK_EVENT) >> WDT_SHIFT_EVENT
+
+
+#define WDTsetEnableReg(client, en)         ectrl_write_data ((client), WDT_CONFIG_REG, !(en) ? \
+				ectrl_read_data ((client), WDT_CONFIG_REG) & ~WDT_MASK_ENABLE : \
+				ectrl_read_data ((client), WDT_CONFIG_REG) | WDT_MASK_ENABLE)
+#define WDTsetEventReg(client, evn)         ectrl_write_data ((client), WDT_CONFIG_REG, \
+				(ectrl_read_data ((client), WDT_CONFIG_REG) \
+				& ~WDT_MASK_EVENT) | (((evn) << WDT_SHIFT_EVENT) & WDT_MASK_EVENT))
+#define WDTsetDelayReg(client, regval)      ectrl_write_data ((client), WDT_DELAY_REG, (u16)(regval))
+#define WDTsetTimeoutReg(client, regval)    ectrl_write_data ((client), WDT_TIMEOUT_REG, (u16)(regval))
+
+#define WDTrefresh(client)         ectrl_write_data ((client), WDT_CTRL_REG, WDT_CTRL_WDTOUT_TRIGGER)
+#define WDTwdtout_reset(client)    ectrl_write_data ((client), WDT_CTRL_REG, WDT_CTRL_WDTOUT_RESET)
+
+#define WDT_F_setDelayReg(client, regval)     { reg_wdt_delay[1].reg.data = (regval) & 0x00FF; \
+					      reg_wdt_delay[3].reg.data = ((regval) >> 8) & 0x00FF; \
+                                              ectrl_mem_op ((client), reg_wdt_delay, NULL); }          
+#define WDT_F_setTimeoutReg(client, regval)   { reg_wdt_timeout[1].reg.data = (regval) & 0x00FF; \
+					      reg_wdt_timeout[3].reg.data = ((regval) >> 8) & 0x00FF; \
+                                              ectrl_mem_op ((client), reg_wdt_timeout, NULL); }
+#define WDT_F_setEnableReg(client, regval)   { reg_wdt_config[1].reg.data = (regval);  \
+                                              ectrl_mem_op ((client), reg_wdt_config, NULL); }
+#define WDT_F_setEventReg(client, regval)    { reg_wdt_config[1].reg.data = (regval) & 0x00FF;  \
+					      reg_wdt_config[3].reg.data = ((regval) >> 8) & 0x00FF; \
+                                              ectrl_mem_op ((client), reg_wdt_config, NULL); }
+
+
+static inline enum wdt_event WDTgetEvent (struct i2c_client *client) {
+	return (enum wdt_event)WDTgetEventReg(client);
+}
+
+
+static inline int WDTsetEvent (struct i2c_client *client, enum wdt_event event) {
+	u16 retval;
+	switch (event) {
+		case WDT_EVNT_WDOUT:
+		case WDT_EVNT_RESET:
+		case WDT_EVNT_PWRBTN1SEC:
+		case WDT_EVNT_PWRBTN4SEC:
+		case WDT_EVNT_BOOT_RECOVERY:
+			WDTsetEventReg(client, (u16)event);
+			retval = (u16)event;
+			break;
+		default:
+			retval = -1;
+	}
+	return (int)retval;
+}
+
+
+static inline void WDT_F_setEnable (struct i2c_client *client, int en) {
+	int reg = (int)(ectrl_read_vector_element ((client), WDT_F_CONFIG_REG_LSB) |
+			ectrl_read_vector_element ((client), WDT_F_CONFIG_REG_MSB) << 8);
+	reg = (en) ? reg | WDT_MASK_ENABLE : reg & ~WDT_MASK_ENABLE;
+	if (en == 0 || en == 1)
+		WDT_F_setEnableReg (client, reg);
+}
+
+
+static inline int WDT_F_setEvent (struct i2c_client *client,  enum wdt_event event) {
+	int reg = (int)(ectrl_read_vector_element ((client), WDT_F_CONFIG_REG_LSB) |
+			ectrl_read_vector_element ((client), WDT_F_CONFIG_REG_MSB) << 8);
+	u16 retval;
+	switch (event) {
+		case WDT_EVNT_WDOUT:
+		case WDT_EVNT_RESET:
+		case WDT_EVNT_PWRBTN1SEC:
+		case WDT_EVNT_PWRBTN4SEC:
+		case WDT_EVNT_BOOT_RECOVERY:
+			retval = (u16)event;
+			reg = (reg & ~WDT_MASK_EVENT) | ((retval << WDT_SHIFT_EVENT) & WDT_MASK_EVENT);
+			WDT_F_setEnableReg(client, reg);
+			break;
+		default:
+			retval = -1;
+	}
+	return (int)retval;
+
+}
+
+
+
+			/* POWER FUNCTIONS */
+
+static int ectrl_SystemHalt (struct i2c_client *client) {
+	int retval;
+	retval = ectrl_mem_op (client, reg_halt, NULL);
+	if (!(retval < 0)) {
+		printk (KERN_INFO "Seco halt performed!\n");
+	} else {
+		printk (KERN_ERR "Seco halt not performed!\n");
+	}
+	return retval;
+}
+
+
+static int ectrl_SystemReboot (struct i2c_client *client) {
+	int retval;
+	retval = ectrl_mem_op (client, reg_reboot, NULL);
+	if (!(retval < 0)) {
+		printk (KERN_INFO "Seco reboot performed!\n");
+	} else {
+		printk (KERN_ERR "Seco reboot not performed!\n");
+	}
+	return retval;
+}
+
+
+/* --------------------------------------------------------------------------
+                              FS Interface (/proc)
+   -------------------------------------------------------------------------- */
+
+static struct proc_dir_entry *ectrl_root_dir;
+static struct proc_dir_entry *ectrl_events_dir;
+static struct proc_dir_entry *ectrl_events_state_dir;
+static struct proc_dir_entry *ectrl_pm_dir;
+static struct proc_dir_entry *ectrl_pm_pwr_btn_4sec_dir;
+static struct proc_dir_entry *ectrl_boot_dir;
+static struct proc_dir_entry *ectrl_watchdog_dir;
+static struct proc_dir_entry *ectrl_watchdog_permanent_dir;
+
+
+#define ECTRL_PROC_ROOT                          "ectrl"
+
+#define ECTRL_PROC_EVENTS                        "events"
+#define ECTRL_PROC_EVENTS_STATE                  "event_state"
+#define ECTRL_PROC_PM                            "power_management"
+#define ECTRL_PROC_BOOT                          "boot"
+#define ECTRL_PROC_WATCHDOG                      "watchdog"
+#define ECTRL_PROC_WDT_PERMANENT                 "permanent"
+
+#define ECTRL_PROC_LID                           "lid"
+#define ECTRL_PROC_BATTERY                       "battery"
+#define ECTRL_PROC_PWR_BTN                       "power_button"
+#define ECTRL_PROC_RST_BTN                       "reset_button"
+#define ECTRL_PROC_SLEEP                         "sleep"
+
+#define ECTRL_ENTRY_STATUS                       "status"
+#define ECTRL_ENTRY_ENABLE                       "enable"
+#define ECTRL_ENTRY_ENFLASH                      "en_flash"
+
+#define ECTRL_ENTRY_PM_PWR_STATE                 "power_state"
+#define ECTRL_ENTRY_PM_STATE                     "available_states"
+#define ECTRL_ENTRY_PM_PWR_BTN_4SEC              "pwr_btn_4sec"
+#define ECTRL_ENTRY_PM_PWR_BTN_4SEC_EN           "enable"
+#define ECTRL_ENTRY_PM_PWR_BTN_4SEC_ENFLASH      "en_flash"
+
+#define ECTRL_ENTRY_DEVBOOT0                     "devboot_1th"
+#define ECTRL_ENTRY_DEVBOOT1                     "devboot_2th"
+#define ECTRL_ENTRY_DEVBOOT2                     "devboot_3th"
+#define ECTRL_ENTRY_RECOVERY_BOOT                "recovery_boot"
+#define ECTRL_ENTRY_BOOTDEV_LIST                 "available_bootdevices"
+#define ECTRL_ENTRY_BOOT_SEQUENCE                "boot_sequence"
+
+#define ECTRL_ENTRY_WDT_ENABLE                   "enable"
+#define ECTRL_ENTRY_WDT_DELAY                    "delay_sec"
+#define ECTRL_ENTRY_WDT_TIMEOUT                  "timeout_sec"
+#define ECTRL_ENTRY_WDT_TIMER1                   "timer_delay"
+#define ECTRL_ENTRY_WDT_TIMER2                   "timer_wd"
+#define ECTRL_ENTRY_WDT_EVENT                    "event"
+#define ECTRL_ENTRY_WDT_AVAL_EVN                 "available_events"
+#define ECTRL_ENTRY_WDT_STATE                    "state"
+#define ECTRL_ENTRY_WDT_REFRESH                  "refresh"
+#define ECTRL_ENTRY_WDT_RESTORE                  "restore"
+#define ECTRL_ENTRY_WDT_WDTOUT_RESET             "wdtout_reset"
+
+#define INPUT_BUF_SIZE   256
+
+
+/* -------------------------- PROC STATE FILEs OPT (r only) -------------------------- */
+
+static int ectrl_proc_state_show (struct seq_file *seq, void *offset) {
+	struct ectrl_proc_event *proc = (struct ectrl_proc_event *)seq->private;
+	int status;
+	if (!proc) 
+		return -EINVAL;
+	mutex_lock (&proc->ectrl->fs_lock);
+	status = getStatus (proc->ectrl->client, proc->event);
+	mutex_unlock (&proc->ectrl->fs_lock);
+        seq_printf(seq, "%s\n", !status ? "active" : "inactive");
+        return 0;
+}
+
+
+static int ectrl_proc_state_open_fs (struct inode *inode, struct file *file) {
+        return single_open(file, ectrl_proc_state_show,  PDE_DATA(inode));
+}
+
+
+static const struct proc_ops ectrl_proc_state_fops = { 
+	.proc_open = ectrl_proc_state_open_fs,
+	.proc_read = seq_read,
+	.proc_write = NULL,
+	.proc_lseek = seq_lseek,
+	.proc_release = single_release,
+};
+
+
+/* -------------------------- PROC STATUS FILEs OPT (r only) -------------------------- */
+
+static int ectrl_proc_status_show (struct seq_file *seq, void *offset) {
+	struct ectrl_proc_event_state *proc = (struct ectrl_proc_event_state *)seq->private;
+	int status;
+	if (!proc) 
+		return -EINVAL;
+	mutex_lock (&proc->ectrl->fs_lock);
+	status = getStatus (proc->ectrl->client, 
+		proc->ectrl->evn_state[proc->state_id]->reg_idx);
+	mutex_unlock (&proc->ectrl->fs_lock);
+        seq_printf(seq, "%s\n", !status ? "active" : "inactive");
+        return 0;
+}
+
+
+static int ectrl_proc_status_open_fs (struct inode *inode, struct file *file) {
+        return single_open(file, ectrl_proc_status_show,  PDE_DATA(inode));
+}
+
+
+static const struct proc_ops ectrl_proc_status_fops = { 
+	.proc_open = ectrl_proc_status_open_fs,
+	.proc_read = seq_read,
+	.proc_write = NULL,
+	.proc_lseek = seq_lseek,
+	.proc_release = single_release,
+};
+
+
+/* -------------------------- PROC ENABLE FILEs OPT (r/w) -------------------------- */
+
+static int ectrl_proc_enable_show (struct seq_file *seq, void *offset) {
+	struct ectrl_proc_event *proc = (struct ectrl_proc_event *)seq->private;
+	int enable;
+	if (!proc) 
+		return -EINVAL;
+
+	mutex_lock (&proc->ectrl->fs_lock);
+	enable = getEnable (proc->ectrl->client, proc->event);
+	mutex_unlock (&proc->ectrl->fs_lock);
+        seq_printf(seq, "%s\n", enable ? "enable" : "disable");
+        return 0;
+}
+
+
+static int ectrl_proc_enable_write (struct file *file, const char __user *buf,
+			size_t count, loff_t *pos) {
+	
+	char input[INPUT_BUF_SIZE];
+	int err_conv;
+	long en;
+	struct ectrl_proc_event *proc = (struct ectrl_proc_event *)
+		((struct seq_file *)file->private_data)->private;
+	if (!proc)
+		return -EINVAL;
+
+	if (!capable(CAP_SYS_ADMIN))
+                return -EACCES;
+
+        if (count >= INPUT_BUF_SIZE)
+                count = INPUT_BUF_SIZE - 1;
+
+	memset(input, 0, INPUT_BUF_SIZE);
+	if (copy_from_user (input, buf, count))
+		return -EFAULT;	
+
+	err_conv = kstrtoul (input, 0, &en);
+	
+	if (err_conv == 0) {
+		if (en == 0 || en == 1) {
+			mutex_lock (&proc->ectrl->fs_lock);
+			setEnable (proc->ectrl->client, proc->event, en);
+			mutex_unlock (&proc->ectrl->fs_lock);
+		} else 
+			return -EINVAL;
+	}
+	return count;
+}
+
+
+static int ectrl_proc_enable_open_fs (struct inode *inode, struct file *file) {
+        return single_open(file, ectrl_proc_enable_show,  PDE_DATA(inode));
+}
+
+
+static const struct proc_ops ectrl_proc_enable_fops = { 
+	.proc_open = ectrl_proc_enable_open_fs,
+	.proc_read = seq_read,
+	.proc_write = ectrl_proc_enable_write,
+	.proc_lseek = seq_lseek,
+	.proc_release = single_release,
+};
+
+
+/* -------------------------- PROC ENFLASH FILEs OPT (r/w) -------------------------- */
+
+static int ectrl_proc_enflash_show (struct seq_file *seq, void *offset) {
+	struct ectrl_proc_event *proc = (struct ectrl_proc_event *)seq->private;
+	int enflash;
+	if (!proc) 
+		return -EINVAL;
+
+	mutex_lock (&proc->ectrl->fs_lock);
+	enflash = getEnFlash (proc->ectrl->client, proc->event);
+	mutex_unlock (&proc->ectrl->fs_lock);
+        seq_printf(seq, "%s\n", enflash ? "enable" : "disable");
+        return 0;
+}
+
+
+static int ectrl_proc_enflash_write (struct file *file, const char __user *buf,
+			size_t count, loff_t *pos) {
+	char input[INPUT_BUF_SIZE];
+	int err_conv;
+	long en;
+	struct ectrl_proc_event *proc = (struct ectrl_proc_event *)
+		((struct seq_file *)file->private_data)->private;
+		
+	if (!proc)
+		return -EINVAL;
+
+	if (!capable(CAP_SYS_ADMIN))
+                return -EACCES;
+
+        if (count >= INPUT_BUF_SIZE)
+                count = INPUT_BUF_SIZE - 1;
+
+	memset(input, 0, INPUT_BUF_SIZE);
+	if (copy_from_user (input, buf, count))
+		return -EFAULT;	
+
+	err_conv = kstrtoul (input, 0, &en);
+	
+	if (err_conv == 0) {
+		if (en == 0 || en == 1) {
+			mutex_lock (&proc->ectrl->fs_lock);
+			setEnFlash (proc->ectrl->client, proc->event, en);
+			mutex_unlock (&proc->ectrl->fs_lock);
+		} else 
+			return -EINVAL;
+	}
+	return count;
+
+}
+
+
+static int ectrl_proc_enflash_open_fs (struct inode *inode, struct file *file) {
+        return single_open(file, ectrl_proc_enflash_show,  PDE_DATA(inode));
+}
+
+
+static const struct proc_ops ectrl_proc_enflash_fops = {
+	.proc_open = ectrl_proc_enflash_open_fs,
+	.proc_read = seq_read,
+	.proc_write = ectrl_proc_enflash_write,
+	.proc_lseek = seq_lseek,
+	.proc_release = single_release,
+};
+
+
+/* -------------------------- PROC PM PWM_STATE FILEs OPT (r/w) -------------------------- */
+
+static int ectrl_proc_pm_pwr_state_show (struct seq_file *seq, void *offset) {
+	struct econtroller *ectrl = (struct econtroller *)seq->private;
+	u16 always;
+	if (!ectrl) 
+		return -EINVAL;
+
+	mutex_lock (&ectrl->fs_lock);
+	always = PMgetAlwaysState (ectrl->client);
+	mutex_unlock (&ectrl->fs_lock);
+        seq_printf(seq, "%s\n", always == (u16)ALWAYS_ON ? "always_on" : "always_off");
+        return 0;
+}
+
+
+static int ectrl_proc_pm_pwr_state_write (struct file *file, const char __user *buf,
+			size_t count, loff_t *pos) {
+	char input[INPUT_BUF_SIZE];
+	int err_conv;
+	long en;
+	struct econtroller *ectrl = (struct econtroller *)
+		((struct seq_file *)file->private_data)->private;
+	if (!ectrl)
+		return -EINVAL;
+
+	if (!capable(CAP_SYS_ADMIN))
+                return -EACCES;
+
+        if (count >= INPUT_BUF_SIZE)
+                count = INPUT_BUF_SIZE - 1;
+
+	memset(input, 0, INPUT_BUF_SIZE);
+	if (copy_from_user (input, buf, count))
+		return -EFAULT;	
+
+	err_conv = kstrtoul (input, 0, &en);
+	
+	if (err_conv == 0) {
+		if (en == 1) {
+			mutex_lock (&ectrl->fs_lock);
+			PMsetAlwaysState (ectrl->client, ALWAYS_ON);
+			mutex_unlock (&ectrl->fs_lock);
+		} else if (en == 0) {
+			mutex_lock (&ectrl->fs_lock);
+			PMsetAlwaysState (ectrl->client, ALWAYS_OFF);
+			mutex_unlock (&ectrl->fs_lock);
+		} else 
+			return -EINVAL;
+	}
+	return count;
+
+}
+
+
+static int ectrl_proc_pm_pwr_state_open_fs (struct inode *inode, struct file *file) {
+        return single_open(file, ectrl_proc_pm_pwr_state_show,  PDE_DATA(inode));
+}
+
+
+static const struct proc_ops ectrl_proc_pm_pwr_state_fops = {
+	.proc_open = ectrl_proc_pm_pwr_state_open_fs,
+	.proc_read = seq_read,
+	.proc_write = ectrl_proc_pm_pwr_state_write,
+	.proc_lseek = seq_lseek,
+	.proc_release = single_release,
+};
+
+
+/* -------------------------- PROC AVAILABLE PM STATE FILE OPT (r only) -------------------------- */
+
+static int ectrl_proc_available_pm_state_show (struct seq_file *seq, void *offset) {
+	struct econtroller *ectrl = (struct econtroller *)seq->private;
+	int i;
+
+	if (!ectrl) 
+		return -EINVAL;
+
+	mutex_lock (&ectrl->fs_lock);
+	for (i = 0 ; i < ARRAY_SIZE (PM_PWR_STATE) ; i++) {
+		seq_printf (seq, "%d: %s\n", i, PM_PWR_STATE[i]);
+	}
+	mutex_unlock (&ectrl->fs_lock);
+        return 0;
+}
+
+
+static int ectrl_proc_available_pm_state_open_fs (struct inode *inode, struct file *file) {
+        return single_open(file, ectrl_proc_available_pm_state_show,  PDE_DATA(inode));
+}
+
+
+static const struct proc_ops ectrl_proc_available_pm_state_fops = {
+	.proc_open = ectrl_proc_available_pm_state_open_fs,
+	.proc_read = seq_read,
+	.proc_write = NULL,
+	.proc_lseek = seq_lseek,
+	.proc_release = single_release,
+};
+
+
+/* -------------------------- PROC BOOT FILEs OPT (r/w) -------------------------- */
+
+static int ectrl_proc_bootdev_show (struct seq_file *seq, void *offset) {
+	struct ectrl_proc_boot *proc = (struct ectrl_proc_boot *)seq->private;
+	enum BOOTDEV_ID bootdev;
+	int index;
+	if (!proc) 
+		return -EINVAL;
+
+	if (!IS_VALID_BOOT_SEQ_IDX(proc->idx))
+		return -EINVAL;
+
+	mutex_lock (&proc->ectrl->fs_lock);
+	bootdev = (enum BOOTDEV_ID)getBootDev (proc->ectrl, proc->idx);
+	index = isAvaildableBootdev (proc->ectrl, bootdev);
+	mutex_unlock (&proc->ectrl->fs_lock);
+        seq_printf (seq, "%d %s\n", (int)bootdev, index < 0 ? "<no label>" : ectrl->bootdev_list[index].label);
+        return 0;
+}
+
+
+static int ectrl_proc_bootdev_write (struct file *file, const char __user *buf,
+			size_t count, loff_t *pos) {
+	
+	char input[INPUT_BUF_SIZE];
+	int err_conv;
+	long  id;
+	
+	struct ectrl_proc_boot *proc = (struct ectrl_proc_boot *)
+		((struct seq_file *)file->private_data)->private;
+	
+	if (!proc)
+		return -EINVAL;
+
+	if (!capable(CAP_SYS_ADMIN))
+                return -EACCES;
+
+        if (count >= INPUT_BUF_SIZE)
+                count = INPUT_BUF_SIZE - 1;
+
+	memset(input, 0, INPUT_BUF_SIZE);
+	if (copy_from_user (input, buf, count))
+		return -EFAULT;	
+
+	err_conv = kstrtoul(input, 0, &id);
+
+	if (err_conv == 0) {
+		mutex_lock (&proc->ectrl->fs_lock);
+		if (setBootDev (proc->ectrl, proc->idx, (enum BOOTDEV_ID)id) < 0) {
+			mutex_unlock (&proc->ectrl->fs_lock);
+			return -EINVAL;
+		}
+		mutex_unlock (&proc->ectrl->fs_lock);
+	} else
+		return err_conv;
+
+	return count;
+}
+
+
+static int ectrl_proc_bootdev_open_fs (struct inode *inode, struct file *file) {
+        return single_open(file, ectrl_proc_bootdev_show,  PDE_DATA(inode));
+}
+
+
+static const struct proc_ops ectrl_proc_bootdev_fops = { 
+	.proc_open = ectrl_proc_bootdev_open_fs,
+	.proc_read = seq_read,
+	.proc_write = ectrl_proc_bootdev_write,
+	.proc_lseek = seq_lseek,
+	.proc_release = single_release,
+};
+
+
+/* -------------------------- PROC BOOT_DEV_LIST FILEs OPT (r only) -------------------------- */
+
+static int ectrl_proc_bootdev_list_show (struct seq_file *seq, void *offset) {
+	struct econtroller *ectrl = (struct econtroller *)seq->private;
+	int i;
+	if (!ectrl) 
+		return -EINVAL;
+
+	mutex_lock (&ectrl->fs_lock);
+	for (i = 0 ; i < ectrl->nr_bootdev ; i++) {
+		seq_printf (seq, "%d %s\n",  
+				ectrl->bootdev_list[i].id, ectrl->bootdev_list[i].label);
+	}
+	mutex_unlock (&ectrl->fs_lock);
+        return 0;
+}
+
+static int ectrl_proc_bootdev_list_open_fs (struct inode *inode, struct file *file) {
+        return single_open(file, ectrl_proc_bootdev_list_show, PDE_DATA(inode));
+	// PDE_DATA(inode));
+}
+
+
+static const struct proc_ops ectrl_proc_bootdev_list_fops = {
+	.proc_open = ectrl_proc_bootdev_list_open_fs,
+	.proc_read = seq_read,
+	.proc_write = NULL,
+	.proc_lseek = seq_lseek,
+	.proc_release = single_release,
+};
+
+
+/* -------------------------- PROC BOOT_SEQUENCE FILE OPT (r only) -------------------------- */
+
+static int ectrl_proc_bootseq_show (struct seq_file *seq, void *offset) {
+	struct econtroller *ectrl = (struct econtroller *)seq->private;
+	int i;
+	enum BOOTDEV_ID bootdev;
+	int index;
+	if (!ectrl) 
+		return -EINVAL;
+
+	mutex_lock (&ectrl->fs_lock);
+	for (i = 0 ; i < BOOT_SEQUENCE_LENGTH ; i++) {
+		bootdev = (enum BOOTDEV_ID)getBootDev (ectrl, i);
+		index = isAvaildableBootdev (ectrl, bootdev);
+		if (index >= 0) {
+			if ( i != (BOOT_SEQUENCE_LENGTH -1)) {
+				seq_printf (seq, "BootDev%d: %d %s\n", i,  
+			   	   ectrl->bootdev_list[index].id, ectrl->bootdev_list[index].label);
+			} else {
+				seq_printf (seq, "Recovery: %d %s\n", 
+				   ectrl->bootdev_list[index].id, ectrl->bootdev_list[index].label);
+			}
+		}
+	}
+	mutex_unlock (&ectrl->fs_lock);
+        return 0;
+}
+
+static int ectrl_proc_bootseq_open_fs (struct inode *inode, struct file *file) {
+        return single_open(file, ectrl_proc_bootseq_show,  PDE_DATA(inode));
+}
+
+
+static const struct proc_ops ectrl_proc_bootseq_fops = {
+	.proc_open = ectrl_proc_bootseq_open_fs,
+	.proc_read = seq_read,
+	.proc_write = NULL,
+	.proc_lseek = seq_lseek,
+	.proc_release = single_release,
+};
+
+
+/* -------------------------- PROC WDT ENABLE FILEs OPT (r/w) -------------------------- */
+
+static int ectrl_proc_wdt_enable_show (struct seq_file *seq, void *offset) {
+	struct econtroller *ectrl = (struct econtroller *)seq->private;
+	int enable;
+	
+	if (!ectrl) 
+		return -EINVAL;
+
+	mutex_lock (&ectrl->fs_lock);
+	enable = WDTgetEnableReg (ectrl->client);
+	mutex_unlock (&ectrl->fs_lock);
+        seq_printf(seq, "%s\n", enable ? "enable" : "disable");
+        return 0;
+}
+
+
+static int ectrl_proc_wdt_enable_write (struct file *file, const char __user *buf,
+			size_t count, loff_t *pos) {
+	
+	char input[INPUT_BUF_SIZE];
+	int err_conv;
+	long en;
+	struct econtroller *ectrl = (struct econtroller *)
+		((struct seq_file *)file->private_data)->private;
+
+	if (!ectrl)
+		return -EINVAL;
+
+	if (!capable(CAP_SYS_ADMIN))
+                return -EACCES;
+
+        if (count >= INPUT_BUF_SIZE)
+                count = INPUT_BUF_SIZE - 1;
+
+	memset(input, 0, INPUT_BUF_SIZE);
+	if (copy_from_user (input, buf, count))
+		return -EFAULT;	
+
+	err_conv = kstrtoul (input, 0, &en);
+	
+	if (err_conv == 0) {
+		if (en == 0 || en == 1) {
+			mutex_lock (&ectrl->fs_lock);
+			WDTsetEnableReg (ectrl->client, en);
+			mutex_unlock (&ectrl->fs_lock);
+		} else 
+			return -EINVAL;
+	}
+	return count;
+}
+
+
+static int ectrl_proc_wdt_enable_open_fs (struct inode *inode, struct file *file) {
+        return single_open(file, ectrl_proc_wdt_enable_show,  PDE_DATA(inode));
+}
+
+
+static const struct proc_ops ectrl_proc_wdt_enable_fops = {
+	.proc_open = ectrl_proc_wdt_enable_open_fs,
+	.proc_read = seq_read,
+	.proc_write = ectrl_proc_wdt_enable_write,
+	.proc_lseek = seq_lseek,
+	.proc_release = single_release,
+};
+
+
+/* -------------------------- PROC WDT EVENT FILE OPT (r/w) -------------------------- */
+
+static int ectrl_proc_wdt_event_show (struct seq_file *seq, void *offset) {
+	struct econtroller *ectrl = (struct econtroller *)seq->private;
+	enum wdt_event event;
+	int index;
+	if (!ectrl) 
+		return -EINVAL;
+
+	mutex_lock (&ectrl->fs_lock);
+	event = WDTgetEvent (ectrl->client);
+	mutex_unlock (&ectrl->fs_lock);
+	index = (int)event;
+        seq_printf(seq, "%d %s\n", ectrl->wdt_event_list[index].id, ectrl->wdt_event_list[index].label);
+        return 0;
+}
+
+
+static int ectrl_proc_wdt_event_write (struct file *file, const char __user *buf,
+			size_t count, loff_t *pos) {
+	
+	char input[INPUT_BUF_SIZE];
+	long id;
+	int  err_conv;
+	struct econtroller *ectrl = (struct econtroller *)
+		((struct seq_file *)file->private_data)->private;
+
+	if (!ectrl)
+		return -EINVAL;
+
+	if (!capable(CAP_SYS_ADMIN))
+                return -EACCES;
+
+        if (count >= INPUT_BUF_SIZE)
+                count = INPUT_BUF_SIZE - 1;
+
+	memset(input, 0, INPUT_BUF_SIZE);
+	if (copy_from_user (input, buf, count))
+		return -EFAULT;	
+
+	err_conv = kstrtoul(input, 0, &id);
+
+	if (err_conv == 0) {
+		mutex_lock (&ectrl->fs_lock);
+		if (WDTsetEvent (ectrl->client, (enum wdt_event)id) < 0) {
+			mutex_unlock (&ectrl->fs_lock);
+			return -EINVAL;
+		}
+		mutex_unlock (&ectrl->fs_lock);
+	} else
+		return err_conv;
+
+	return count;
+}
+
+
+static int ectrl_proc_wdt_event_open_fs (struct inode *inode, struct file *file) {
+        return single_open(file, ectrl_proc_wdt_event_show,  PDE_DATA(inode));
+}
+
+
+static const struct proc_ops ectrl_proc_wdt_event_fops = {
+	.proc_open = ectrl_proc_wdt_event_open_fs,
+	.proc_read = seq_read,
+	.proc_write = ectrl_proc_wdt_event_write,
+	.proc_lseek = seq_lseek,
+	.proc_release = single_release,
+};
+
+
+/* -------------------------- PROC AVAILABLE WDT EVENTS FILE OPT (r only) -------------------------- */
+
+static int ectrl_proc_avalaible_wdt_event_show (struct seq_file *seq, void *offset) {
+	struct econtroller *ectrl = (struct econtroller *)seq->private;
+	int i;
+
+	if (!ectrl) 
+		return -EINVAL;
+
+	mutex_lock (&ectrl->fs_lock);
+	for (i = 0 ; i < ectrl->nr_wdt_event ; i++) {
+		seq_printf (seq, "%d: %s\n",  ectrl->wdt_event_list[i].id, 
+					ectrl->wdt_event_list[i].label);
+	}
+	mutex_unlock (&ectrl->fs_lock);
+        return 0;
+}
+
+
+static int ectrl_proc_available_wdt_event_open_fs (struct inode *inode, struct file *file) {
+        return single_open(file, ectrl_proc_avalaible_wdt_event_show,  PDE_DATA(inode));
+}
+
+
+static const struct proc_ops ectrl_proc_avalaible_wdt_event_fops = {
+	.proc_open = ectrl_proc_available_wdt_event_open_fs,
+	.proc_read = seq_read,
+	.proc_write = NULL,
+	.proc_lseek = seq_lseek,
+	.proc_release = single_release,
+};
+
+
+/* -------------------------- PROC WDT DELAY FILE OPT (r/w) -------------------------- */
+
+static int ectrl_proc_wdt_delay_show (struct seq_file *seq, void *offset) {
+	struct econtroller *ectrl = (struct econtroller *)seq->private;
+	
+	if (!ectrl) 
+		return -EINVAL;
+
+	mutex_lock (&ectrl->fs_lock);
+        seq_printf(seq, "%d\n", WDTgetDelayReg (ectrl->client));
+	mutex_unlock (&ectrl->fs_lock);
+        return 0;
+}
+
+
+static int ectrl_proc_wdt_delay_write (struct file *file, const char __user *buf,
+			size_t count, loff_t *pos) {
+	
+	char input[INPUT_BUF_SIZE];
+	long delay;
+	int  err_conv;
+	struct econtroller *ectrl = (struct econtroller *)
+		((struct seq_file *)file->private_data)->private;
+
+	if (!ectrl)
+		return -EINVAL;
+
+	if (!capable(CAP_SYS_ADMIN))
+                return -EACCES;
+
+        if (count >= INPUT_BUF_SIZE)
+                count = INPUT_BUF_SIZE - 1;
+
+	memset(input, 0, INPUT_BUF_SIZE);
+	if (copy_from_user (input, buf, count))
+		return -EFAULT;	
+
+	err_conv = kstrtoul(input, 0, &delay);
+
+	if (err_conv == 0) {
+		if ((u16)delay < 1)
+			return -EINVAL;
+		mutex_lock (&ectrl->fs_lock);
+		WDTsetDelayReg (ectrl->client, (u16)delay);
+		mutex_unlock (&ectrl->fs_lock);
+	} else
+		return err_conv;
+
+	return count;
+}
+
+
+static int ectrl_proc_wdt_delay_open_fs (struct inode *inode, struct file *file) {
+        return single_open(file, ectrl_proc_wdt_delay_show,  PDE_DATA(inode));
+}
+
+
+static const struct proc_ops ectrl_proc_wdt_delay_fops = {
+	.proc_open = ectrl_proc_wdt_delay_open_fs,
+	.proc_read = seq_read,
+	.proc_write = ectrl_proc_wdt_delay_write,
+	.proc_lseek = seq_lseek,
+	.proc_release = single_release,
+};
+
+
+/* -------------------------- PROC WDT TIMEOUT FILE OPT (r/w) -------------------------- */
+
+static int ectrl_proc_wdt_timeout_show (struct seq_file *seq, void *offset) {
+	struct econtroller *ectrl = (struct econtroller *)seq->private;
+	
+	if (!ectrl) 
+		return -EINVAL;
+
+	mutex_unlock (&ectrl->fs_lock);
+        seq_printf(seq, "%d\n", WDTgetTimeoutReg (ectrl->client));
+	mutex_unlock (&ectrl->fs_lock);
+        return 0;
+}
+
+
+static int ectrl_proc_wdt_timeout_write (struct file *file, const char __user *buf,
+			size_t count, loff_t *pos) {
+	
+	char input[INPUT_BUF_SIZE];
+	long timeout;
+	int  err_conv;
+	struct econtroller *ectrl = (struct econtroller *)
+		((struct seq_file *)file->private_data)->private;
+
+	if (!ectrl)
+		return -EINVAL;
+
+	if (!capable(CAP_SYS_ADMIN))
+                return -EACCES;
+
+        if (count >= INPUT_BUF_SIZE)
+                count = INPUT_BUF_SIZE - 1;
+
+	memset(input, 0, INPUT_BUF_SIZE);
+	if (copy_from_user (input, buf, count))
+		return -EFAULT;	
+
+	err_conv = kstrtoul(input, 0, &timeout);
+
+	if (err_conv == 0) {
+		if ((u16)timeout < 1)
+			return -EINVAL; 
+		mutex_lock (&ectrl->fs_lock);
+		WDTsetTimeoutReg (ectrl->client, (u16)timeout);
+		mutex_unlock (&ectrl->fs_lock);
+	} else
+		return err_conv;
+
+	return count;
+}
+
+
+static int ectrl_proc_wdt_timeout_open_fs (struct inode *inode, struct file *file) {
+        return single_open(file, ectrl_proc_wdt_timeout_show,  PDE_DATA(inode));}
+
+
+static const struct proc_ops ectrl_proc_wdt_timeout_fops = {
+	.proc_open = ectrl_proc_wdt_timeout_open_fs,
+	.proc_read = seq_read,
+	.proc_write = ectrl_proc_wdt_timeout_write,
+	.proc_lseek = seq_lseek,
+	.proc_release = single_release,
+};
+
+
+/* -------------------------- PROC WDT REFRESH FILE OPT (r/w) -------------------------- */
+
+static int ectrl_proc_wdt_refresh_show (struct seq_file *seq, void *offset) {
+	struct econtroller *ectrl = (struct econtroller *)seq->private;
+	
+	if (!ectrl) 
+		return -EINVAL;
+
+        return 0;
+}
+
+
+static int ectrl_proc_wdt_refresh_write (struct file *file, const char __user *buf,
+			size_t count, loff_t *pos) {
+	
+	char input[INPUT_BUF_SIZE];
+	long in;
+	int  err_conv;
+	struct econtroller *ectrl = (struct econtroller *)
+		((struct seq_file *)file->private_data)->private;
+
+	if (!ectrl)
+		return -EINVAL;
+
+	if (!capable(CAP_SYS_ADMIN))
+                return -EACCES;
+
+        if (count >= INPUT_BUF_SIZE)
+                count = INPUT_BUF_SIZE - 1;
+
+	memset(input, 0, INPUT_BUF_SIZE);
+	if (copy_from_user (input, buf, count))
+		return -EFAULT;	
+
+	err_conv = kstrtoul(input, 0, &in);
+
+	if (err_conv == 0) {
+		if ((u16)in != 1)
+			return -EINVAL; 
+		mutex_lock (&ectrl->fs_lock);
+		WDTrefresh (ectrl->client);
+		mutex_unlock (&ectrl->fs_lock);
+	} else
+		return err_conv;
+
+	return count;
+}
+
+
+static int ectrl_proc_wdt_refresh_open_fs (struct inode *inode, struct file *file) {
+        return single_open(file, ectrl_proc_wdt_refresh_show,  PDE_DATA(inode));
+}
+
+
+static const struct proc_ops ectrl_proc_wdt_refresh_fops = {
+	.proc_open = ectrl_proc_wdt_refresh_open_fs,
+	.proc_read = seq_read,
+	.proc_write = ectrl_proc_wdt_refresh_write,
+	.proc_lseek = seq_lseek,
+	.proc_release = single_release,
+};
+
+
+/* -------------------------- PROC WDT RESTORE FILE OPT (r/w) -------------------------- */
+
+static int ectrl_proc_wdt_restore_show (struct seq_file *seq, void *offset) {
+	struct econtroller *ectrl = (struct econtroller *)seq->private;
+	
+	if (!ectrl) 
+		return -EINVAL;
+
+        return 0;
+}
+
+
+static int ectrl_proc_wdt_restore_write (struct file *file, const char __user *buf,
+			size_t count, loff_t *pos) {
+	
+	char input[INPUT_BUF_SIZE];
+	long in;
+	int  err_conv;
+	u16 f_delay, f_timeout;
+	struct econtroller *ectrl = (struct econtroller *)
+		((struct seq_file *)file->private_data)->private;
+
+	if (!ectrl)
+		return -EINVAL;
+
+	if (!capable(CAP_SYS_ADMIN))
+                return -EACCES;
+
+        if (count >= INPUT_BUF_SIZE)
+                count = INPUT_BUF_SIZE - 1;
+
+	memset(input, 0, INPUT_BUF_SIZE);
+	if (copy_from_user (input, buf, count))
+		return -EFAULT;	
+
+	err_conv = kstrtoul(input, 0, &in);
+
+	if (err_conv == 0) {
+		if ((u16)in != 1)
+			return -EINVAL; 
+		mutex_lock (&ectrl->fs_lock);
+		f_delay   = (u16)WDT_F_getDelayReg (ectrl->client);
+		f_timeout = (u16)WDT_F_getTimeoutReg (ectrl->client);
+
+		WDTsetDelayReg (ectrl->client, f_delay);
+		WDTsetTimeoutReg (ectrl->client, f_timeout);	
+		mutex_unlock (&ectrl->fs_lock);
+	} else
+		return err_conv;
+
+	return count;
+}
+
+
+static int ectrl_proc_wdt_restore_open_fs (struct inode *inode, struct file *file) {
+        return single_open(file, ectrl_proc_wdt_restore_show,  PDE_DATA(inode));
+}
+
+
+static const struct proc_ops ectrl_proc_wdt_restore_fops = { 
+	.proc_open = ectrl_proc_wdt_restore_open_fs,
+	.proc_read = seq_read,
+	.proc_write = ectrl_proc_wdt_restore_write,
+	.proc_lseek = seq_lseek,
+	.proc_release = single_release,
+};
+
+
+/* -------------------------- PROC WDTOUT RESET FILE OPT (r/w) -------------------------- */
+
+static int ectrl_proc_wdt_wdtout_reset_show (struct seq_file *seq, void *offset) {
+	struct econtroller *ectrl = (struct econtroller *)seq->private;
+	
+	if (!ectrl) 
+		return -EINVAL;
+
+        return 0;
+}
+
+
+static int ectrl_proc_wdt_wdtout_reset_write (struct file *file, const char __user *buf,
+			size_t count, loff_t *pos) {
+	
+	char input[INPUT_BUF_SIZE];
+	long in;
+	int  err_conv;
+	struct econtroller *ectrl = (struct econtroller *)
+		((struct seq_file *)file->private_data)->private;
+
+	if (!ectrl)
+		return -EINVAL;
+
+	if (!capable(CAP_SYS_ADMIN))
+                return -EACCES;
+
+        if (count >= INPUT_BUF_SIZE)
+                count = INPUT_BUF_SIZE - 1;
+
+	memset(input, 0, INPUT_BUF_SIZE);
+	if (copy_from_user (input, buf, count))
+		return -EFAULT;	
+
+	err_conv = kstrtoul(input, 0, &in);
+
+	if (err_conv == 0) {
+		if ((u16)in != 1)
+			return -EINVAL;
+		mutex_lock (&ectrl->fs_lock);
+		WDTwdtout_reset (ectrl->client); 
+		mutex_unlock (&ectrl->fs_lock);
+	} else
+		return err_conv;
+
+	return count;
+}
+
+
+static int ectrl_proc_wdt_wdtout_reset_open_fs (struct inode *inode, struct file *file) {
+        return single_open(file, ectrl_proc_wdt_wdtout_reset_show,  PDE_DATA(inode));
+}
+
+
+static const struct proc_ops ectrl_proc_wdt_wdtout_reset_fops = {
+	.proc_open = ectrl_proc_wdt_wdtout_reset_open_fs,
+	.proc_read = seq_read,
+	.proc_write = ectrl_proc_wdt_wdtout_reset_write,
+	.proc_lseek = seq_lseek,
+	.proc_release = single_release,
+};
+
+
+/* -------------------------- PROC WDT TIMER1 FILE OPT (r only) -------------------------- */
+
+static int ectrl_proc_wdt_timer1_show (struct seq_file *seq, void *offset) {
+	struct econtroller *ectrl = (struct econtroller *)seq->private;
+
+	if (!ectrl) 
+		return -EINVAL;
+
+	mutex_lock (&ectrl->fs_lock);
+        seq_printf(seq, "%d\n", WDTgetTimer1Reg (ectrl->client));
+	mutex_unlock (&ectrl->fs_lock);
+        return 0;
+}
+
+
+static int ectrl_proc_wdt_timer1_open_fs (struct inode *inode, struct file *file) {
+        return single_open(file, ectrl_proc_wdt_timer1_show,  PDE_DATA(inode));
+}
+
+
+static const struct proc_ops ectrl_proc_wdt_timer1_fops = {
+	.proc_open = ectrl_proc_wdt_timer1_open_fs,
+	.proc_read = seq_read,
+	.proc_write = NULL,
+	.proc_lseek = seq_lseek,
+	.proc_release = single_release,
+};
+
+
+/* -------------------------- PROC WDT TIMER2 FILE OPT (r only) -------------------------- */
+
+static int ectrl_proc_wdt_timer2_show (struct seq_file *seq, void *offset) {
+	struct econtroller *ectrl = (struct econtroller *)seq->private;
+
+	if (!ectrl) 
+		return -EINVAL;
+
+	mutex_lock (&ectrl->fs_lock);
+        seq_printf(seq, "%d\n", WDTgetTimer2Reg (ectrl->client));
+	mutex_unlock (&ectrl->fs_lock);
+        return 0;
+}
+
+
+static int ectrl_proc_wdt_timer2_open_fs (struct inode *inode, struct file *file) {
+        return single_open(file, ectrl_proc_wdt_timer2_show,  PDE_DATA(inode));
+}
+
+
+static const struct proc_ops ectrl_proc_wdt_timer2_fops = {
+	.proc_open = ectrl_proc_wdt_timer2_open_fs,
+	.proc_read = seq_read,
+	.proc_write = NULL,
+	.proc_lseek = seq_lseek,
+	.proc_release = single_release,
+};
+
+
+/* -------------------------- PROC WDT STATE FILE OPT (r only) -------------------------- */
+
+static int ectrl_proc_wdt_state_show (struct seq_file *seq, void *offset) {
+	struct econtroller *ectrl = (struct econtroller *)seq->private;
+	enum wdt_event event;
+	int enable, index;
+
+	if (!ectrl) 
+		return -EINVAL;
+	
+	mutex_lock (&ectrl->fs_lock);
+	enable = WDTgetEnableReg (ectrl->client);
+
+	event = WDTgetEvent (ectrl->client);
+	index = (int)event;
+
+        seq_printf(seq, "  %20s : %s\n  %20s : %d - %s\n  %20s : %d\n  %20s : %d\n  %20s : %d\n  %20s : %d\n",
+				ECTRL_ENTRY_WDT_ENABLE,   enable ? "enable" : "disable",
+				ECTRL_ENTRY_WDT_EVENT,    ectrl->wdt_event_list[index].id, 
+							  ectrl->wdt_event_list[index].label,
+				ECTRL_ENTRY_WDT_DELAY,    WDTgetDelayReg (ectrl->client),
+				ECTRL_ENTRY_WDT_TIMEOUT,  WDTgetTimeoutReg (ectrl->client),
+				ECTRL_ENTRY_WDT_TIMER1,   WDTgetTimer1Reg (ectrl->client),
+				ECTRL_ENTRY_WDT_TIMER2,   WDTgetTimer2Reg (ectrl->client));
+	mutex_unlock (&ectrl->fs_lock);
+        return 0;
+}
+
+
+static int ectrl_proc_wdt_state_open_fs (struct inode *inode, struct file *file) {
+        return single_open(file, ectrl_proc_wdt_state_show,  PDE_DATA(inode));
+}
+
+
+static const struct proc_ops ectrl_proc_wdt_state_fops = {
+	.proc_open = ectrl_proc_wdt_state_open_fs,
+	.proc_read = seq_read,
+	.proc_write = NULL,
+	.proc_lseek = seq_lseek,
+	.proc_release = single_release,
+};
+
+
+/* -------------------------- PROC WDT FLASH ENABLE FILEs OPT (r/w) -------------------------- */
+
+static int ectrl_proc_wdt_f_enable_show (struct seq_file *seq, void *offset) {
+	struct econtroller *ectrl = (struct econtroller *)seq->private;
+	int enable;
+	
+	if (!ectrl) 
+		return -EINVAL;
+
+	mutex_lock (&ectrl->fs_lock);
+	enable = WDT_F_getEnableReg (ectrl->client);
+	mutex_unlock (&ectrl->fs_lock);
+        seq_printf(seq, "%s\n", enable ? "enable" : "disable");
+        return 0;
+}
+
+
+static int ectrl_proc_wdt_f_enable_write (struct file *file, const char __user *buf,
+			size_t count, loff_t *pos) {
+	
+	char input[INPUT_BUF_SIZE];
+	int err_conv;
+	long en;
+	struct econtroller *ectrl = (struct econtroller *)
+		((struct seq_file *)file->private_data)->private;
+
+	if (!ectrl)
+		return -EINVAL;
+
+	if (!capable(CAP_SYS_ADMIN))
+                return -EACCES;
+
+        if (count >= INPUT_BUF_SIZE)
+                count = INPUT_BUF_SIZE - 1;
+
+	memset(input, 0, INPUT_BUF_SIZE);
+	if (copy_from_user (input, buf, count))
+		return -EFAULT;	
+
+	err_conv = kstrtoul (input, 0, &en);
+	
+	if (err_conv == 0) {
+		if (en == 0 || en == 1) {
+			mutex_lock (&ectrl->fs_lock);
+			WDT_F_setEnable (ectrl->client, en);
+			mutex_unlock (&ectrl->fs_lock);
+		} else 
+			return -EINVAL;
+	}
+	return count;
+}
+
+
+static int ectrl_proc_wdt_f_enable_open_fs (struct inode *inode, struct file *file) {
+        return single_open(file, ectrl_proc_wdt_f_enable_show,  PDE_DATA(inode));
+}
+
+
+static const struct proc_ops ectrl_proc_wdt_f_enable_fops = {
+	.proc_open = ectrl_proc_wdt_f_enable_open_fs,
+	.proc_read = seq_read,
+	.proc_write = ectrl_proc_wdt_f_enable_write,
+	.proc_lseek = seq_lseek,
+	.proc_release = single_release,
+};
+
+
+
+
+/* -------------------------- PROC WDT FLASH EVENT FILE OPT (r/w) -------------------------- */
+
+static int ectrl_proc_wdt_f_event_show (struct seq_file *seq, void *offset) {
+	struct econtroller *ectrl = (struct econtroller *)seq->private;
+	enum wdt_event event;
+	int index;
+	if (!ectrl) 
+		return -EINVAL;
+
+	mutex_lock (&ectrl->fs_lock);
+	event = WDT_F_getEventReg (ectrl->client);
+	mutex_unlock (&ectrl->fs_lock);
+	index = (int)event;
+        seq_printf(seq, "%d %s\n", ectrl->wdt_event_list[index].id, ectrl->wdt_event_list[index].label);
+        return 0;
+}
+
+
+static int ectrl_proc_wdt_f_event_write (struct file *file, const char __user *buf,
+			size_t count, loff_t *pos) {
+	
+	char input[INPUT_BUF_SIZE];
+	long id;
+	int  err_conv;
+	struct econtroller *ectrl = (struct econtroller *)
+		((struct seq_file *)file->private_data)->private;
+
+	if (!ectrl)
+		return -EINVAL;
+
+	if (!capable(CAP_SYS_ADMIN))
+                return -EACCES;
+
+        if (count >= INPUT_BUF_SIZE)
+                count = INPUT_BUF_SIZE - 1;
+
+	memset(input, 0, INPUT_BUF_SIZE);
+	if (copy_from_user (input, buf, count))
+		return -EFAULT;	
+
+	err_conv = kstrtoul(input, 0, &id);
+
+	if (err_conv == 0) {
+		mutex_lock (&ectrl->fs_lock);
+		if (WDT_F_setEvent (ectrl->client, (enum wdt_event)id) < 0) {
+			mutex_unlock (&ectrl->fs_lock);
+			return -EINVAL;
+		}
+		mutex_unlock (&ectrl->fs_lock);
+	} else
+		return err_conv;
+
+	return count;
+}
+
+
+static int ectrl_proc_wdt_f_event_open_fs (struct inode *inode, struct file *file) {
+        return single_open(file, ectrl_proc_wdt_f_event_show,  PDE_DATA(inode));
+}
+
+
+static const struct proc_ops ectrl_proc_wdt_f_event_fops = {
+	.proc_open = ectrl_proc_wdt_f_event_open_fs,
+	.proc_read = seq_read,
+	.proc_write = ectrl_proc_wdt_f_event_write,
+	.proc_lseek = seq_lseek,
+	.proc_release = single_release,
+};
+
+
+/* -------------------------- PROC WDT FLASH DELAY FILE OPT (r/w) -------------------------- */
+
+static int ectrl_proc_wdt_f_delay_show (struct seq_file *seq, void *offset) {
+	struct econtroller *ectrl = (struct econtroller *)seq->private;
+	
+	if (!ectrl) 
+		return -EINVAL;
+
+	mutex_unlock (&ectrl->fs_lock);
+        seq_printf(seq, "%d\n", WDT_F_getDelayReg (ectrl->client));
+	mutex_unlock (&ectrl->fs_lock);
+        return 0;
+}
+
+
+static int ectrl_proc_wdt_f_delay_write (struct file *file, const char __user *buf,
+			size_t count, loff_t *pos) {
+	
+	char input[INPUT_BUF_SIZE];
+	long delay;
+	int  err_conv;
+	struct econtroller *ectrl = (struct econtroller *)
+		((struct seq_file *)file->private_data)->private;
+
+	if (!ectrl)
+		return -EINVAL;
+
+	if (!capable(CAP_SYS_ADMIN))
+                return -EACCES;
+
+        if (count >= INPUT_BUF_SIZE)
+                count = INPUT_BUF_SIZE - 1;
+
+	memset(input, 0, INPUT_BUF_SIZE);
+	if (copy_from_user (input, buf, count))
+		return -EFAULT;	
+
+	err_conv = kstrtoul(input, 0, &delay);
+
+	if (err_conv == 0) {
+		if ((u16)delay < 1)
+			return -EINVAL;
+		mutex_lock (&ectrl->fs_lock);
+		WDT_F_setDelayReg (ectrl->client, (u16)delay);
+		mutex_unlock (&ectrl->fs_lock);
+	} else
+		return err_conv;
+
+	return count;
+}
+
+
+static int ectrl_proc_wdt_f_delay_open_fs (struct inode *inode, struct file *file) {
+        return single_open(file, ectrl_proc_wdt_f_delay_show,  PDE_DATA(inode));
+}
+
+
+static const struct proc_ops ectrl_proc_wdt_f_delay_fops = {
+	.proc_open = ectrl_proc_wdt_f_delay_open_fs,
+	.proc_read = seq_read,
+	.proc_write = ectrl_proc_wdt_f_delay_write,
+	.proc_lseek = seq_lseek,
+	.proc_release = single_release,
+};
+
+
+/* -------------------------- PROC WDT FLASH TIMEOUT FILE OPT (r/w) -------------------------- */
+
+static int ectrl_proc_wdt_f_timeout_show (struct seq_file *seq, void *offset) {
+	struct econtroller *ectrl = (struct econtroller *)seq->private;
+	
+	if (!ectrl) 
+		return -EINVAL;
+
+	mutex_lock (&ectrl->fs_lock);
+        seq_printf(seq, "%d\n", WDT_F_getTimeoutReg (ectrl->client));
+	mutex_unlock (&ectrl->fs_lock);
+        return 0;
+}
+
+
+static int ectrl_proc_wdt_f_timeout_write (struct file *file, const char __user *buf,
+			size_t count, loff_t *pos) {
+	
+	char input[INPUT_BUF_SIZE];
+	long timeout;
+	int  err_conv;
+	struct econtroller *ectrl = (struct econtroller *)
+		((struct seq_file *)file->private_data)->private;
+
+	if (!ectrl)
+		return -EINVAL;
+
+	if (!capable(CAP_SYS_ADMIN))
+                return -EACCES;
+
+        if (count >= INPUT_BUF_SIZE)
+                count = INPUT_BUF_SIZE - 1;
+
+	memset(input, 0, INPUT_BUF_SIZE);
+	if (copy_from_user (input, buf, count))
+		return -EFAULT;	
+
+	err_conv = kstrtoul(input, 0, &timeout);
+
+	if (err_conv == 0) {
+		if ((u16)timeout < 1)
+			return -EINVAL; 
+		mutex_lock (&ectrl->fs_lock);
+		WDT_F_setTimeoutReg (ectrl->client, (u16)timeout);
+		mutex_unlock (&ectrl->fs_lock);
+	} else
+		return err_conv;
+
+	return count;
+}
+
+
+static int ectrl_proc_wdt_f_timeout_open_fs (struct inode *inode, struct file *file) {
+        return single_open(file, ectrl_proc_wdt_f_timeout_show,  PDE_DATA(inode));
+}
+
+
+static const struct proc_ops ectrl_proc_wdt_f_timeout_fops = {
+	.proc_open = ectrl_proc_wdt_f_timeout_open_fs,
+	.proc_read = seq_read,
+	.proc_write = ectrl_proc_wdt_f_timeout_write,
+	.proc_lseek = seq_lseek,
+	.proc_release = single_release,
+};
+
+
+
+/* -------------------------- PROC ECTRL REVISION FILE OPT (r) -------------------------- */
+
+
+
+static int ectrl_proc_build_revision_show (struct seq_file *seq, void *offset) {
+	struct econtroller *ectrl = (struct econtroller *)seq->private;
+
+	if (!ectrl)
+		return -EINVAL;
+
+	mutex_lock (&ectrl->fs_lock);
+        seq_printf(seq, "0x%04X\n", ectrl_read_data (ectrl->client, BUILDREV_REG));
+	mutex_unlock (&ectrl->fs_lock);
+        return 0;
+}
+
+
+static int ectrl_proc_build_revision_open_fs (struct inode *inode, struct file *file) {
+        return single_open(file, ectrl_proc_build_revision_show,  PDE_DATA(inode));
+}
+
+
+static const struct proc_ops ectrl_proc_build_revisione_fops = {
+	.proc_open = ectrl_proc_build_revision_open_fs,
+	.proc_read = seq_read,
+	.proc_write = NULL,
+	.proc_lseek = seq_lseek,
+	.proc_release = single_release,
+};
+
+
+static int ectrl_proc_board_revision_show (struct seq_file *seq, void *offset) {
+	struct econtroller *ectrl = (struct econtroller *)seq->private;
+
+	if (!ectrl)
+		return -EINVAL;
+
+	mutex_lock (&ectrl->fs_lock);
+        seq_printf(seq, "0x%04X\n", ectrl_read_data (ectrl->client, FW_ID_REV_REG));
+	mutex_unlock (&ectrl->fs_lock);
+        return 0;
+}
+
+
+static int ectrl_proc_board_revision_open_fs (struct inode *inode, struct file *file) {
+        return single_open(file, ectrl_proc_board_revision_show,  PDE_DATA(inode));
+}
+
+
+static const struct proc_ops ectrl_proc_board_revisione_fops = {
+	.proc_open = ectrl_proc_board_revision_open_fs,
+	.proc_read = seq_read,
+	.proc_write = NULL,
+	.proc_lseek = seq_lseek,
+	.proc_release = single_release,
+};
+
+
+#if ECTRL_LOGGING
+static int ectrl_proc_logger_show (struct seq_file *seq, void *offset) {
+	struct logger_entry *tmp;
+	struct list_head *pos, *q;
+	struct econtroller *ectrl = (struct econtroller *)seq->private;
+	int tot = 0;
+	unsigned char str[50];
+	unsigned char *msg;
+
+	if (!ectrl)
+		return -EINVAL;
+
+	mutex_lock (&logger_lock);
+	list_for_each_safe (pos, q, &logger_list->list) {
+		tot++;
+	}
+
+	msg = kzalloc (sizeof (str) * (tot+1), GFP_KERNEL);
+	if ( !msg ) {
+		mutex_unlock (&logger_lock);
+		return -ENOMEM;
+	}
+
+	list_for_each_safe (pos, q, &logger_list->list) {
+		tmp = list_entry (pos, struct logger_entry, list);
+		sprintf (str, "\n[%10u] op: %c, addr: 0x%02X, data:0x%02X",
+				tmp->time, tmp->op, tmp->address, tmp->data);
+		strcat (msg, str);
+	}
+	mutex_unlock (&logger_lock);
+
+	sprintf (str, "\n total operation: %d", tot);
+	strcat (msg, str);
+
+	mutex_lock (&ectrl->fs_lock);
+	seq_printf (seq, "%s\n", msg);
+	mutex_unlock (&ectrl->fs_lock);
+    return 0;
+}
+
+
+static int ectrl_proc_logger_write (struct file *file, const char __user *buf,
+			size_t count, loff_t *pos) {
+
+	char input[INPUT_BUF_SIZE];
+	long operation;
+	int  err_conv;
+	struct econtroller *ectrl = (struct econtroller *)
+		((struct seq_file *)file->private_data)->private;
+
+	if (!ectrl)
+		return -EINVAL;
+
+	if (!capable(CAP_SYS_ADMIN))
+                return -EACCES;
+
+        if (count >= INPUT_BUF_SIZE)
+                count = INPUT_BUF_SIZE - 1;
+
+	memset(input, 0, INPUT_BUF_SIZE);
+	if (copy_from_user (input, buf, count))
+		return -EFAULT;	
+
+	err_conv = kstrtoul(input, 0, &operation);
+
+	if (err_conv == 0) {
+		if ((u16)operation < 0)
+			return -EINVAL; 
+
+		switch (operation) {
+			case 0: // clear list
+				logger_del_all ();
+				break;
+			default:
+				break;
+		}
+	} else
+		return err_conv;
+
+	return count;
+}
+
+static int ectrl_proc_logger_open_fs (struct inode *inode, struct file *file) {
+        return single_open(file, ectrl_proc_logger_show,  PDE_DATA(inode));
+}
+
+
+static const struct proc_ops ectrl_proc_logger_fops = {
+	.proc_open = ectrl_proc_logger_open_fs,
+	.proc_read = seq_read,
+	.proc_write = ectrl_proc_logger_write,
+	.proc_lseek = seq_lseek,
+	.proc_release = single_release,
+};
+#endif /* ECTRL_LOGGING */
+
+			/* --------------------------- */
+
+struct proc_entry {
+	char                   label[30];
+	struct proc_dir_entry  *entry;
+	struct list_head       list; 
+};
+
+static struct proc_entry *entry_list;
+
+#define add_to_list(item, head, name, entry_dir)       item = kzalloc (sizeof (struct proc_entry), GFP_KERNEL); \
+							strcpy (item->label, name); \
+							item->entry = entry_dir; \
+							list_add (&item->list, &head->list)
+
+
+
+static int ectrl_add_proc_fs (struct econtroller *ectrl) {
+	struct proc_dir_entry *entry = NULL;
+        int i;
+
+	struct ectrl_proc_event *pwr_btn_eproc;
+	struct ectrl_proc_event *rst_btn_eproc;
+	struct ectrl_proc_event *lid_hl_eproc;
+	struct ectrl_proc_event *lid_lh_eproc;
+	struct ectrl_proc_event *batlow_hl_eproc;
+	struct ectrl_proc_event *batlow_lh_eproc;
+	struct ectrl_proc_event *sleep_eproc;
+	struct ectrl_proc_event *wake_eproc;
+	
+	struct ectrl_proc_event *pwr_btn_4sec_eproc; // no event and status for it
+
+	struct ectrl_proc_event_state *pwr_btn_state_eproc;
+	struct ectrl_proc_event_state *rst_btn_state_eproc;
+	struct ectrl_proc_event_state *lid_state_eproc;
+	struct ectrl_proc_event_state *batlow_state_eproc;
+	struct ectrl_proc_event_state *sleep_state_eproc;
+	struct ectrl_proc_event_state *wake_state_eproc;
+
+	struct ectrl_proc_boot  *boot0_bproc;
+	struct ectrl_proc_boot  *boot1_bproc;
+	struct ectrl_proc_boot  *boot2_bproc;
+	struct ectrl_proc_boot  *boot3_bproc;
+
+	struct proc_entry *tmp;
+	struct list_head *pos, *q;
+
+	entry_list = kzalloc (sizeof (struct proc_entry), GFP_KERNEL);
+	INIT_LIST_HEAD (&entry_list->list);
+
+	/* create /proc/ectrl */
+        ectrl_root_dir = proc_mkdir (ECTRL_PROC_ROOT, NULL);
+        if (!ectrl_root_dir)
+                return -ENODEV;
+	else {
+		add_to_list (tmp, entry_list, ECTRL_PROC_ROOT, NULL);
+	}		
+
+	/* EVENTS TREE */
+
+	/* create /proc/ectrl/events */
+	ectrl_events_dir = proc_mkdir (ECTRL_PROC_EVENTS, ectrl_root_dir);
+	if (!ectrl_events_dir) {
+		//TODO: error
+	} else {
+		add_to_list (tmp, entry_list, ECTRL_PROC_EVENTS, ectrl_root_dir);
+	}
+
+	for (i = 0 ; i < ectrl->nr_evnt ; i++) {
+		ectrl->events[i]->proc_dir = proc_mkdir (ectrl->events[i]->label, ectrl_events_dir);
+		if (!ectrl->events[i]->proc_dir) {
+	                goto remove_dir;
+		} else {
+			add_to_list (tmp, entry_list, ectrl->events[i]->label, ectrl_events_dir);
+		}
+		switch (ectrl->events[i]->id) {
+			case PWR_BUTTON:
+				// --- power button --- //
+				pwr_btn_eproc = kzalloc (sizeof (struct ectrl_proc_event), GFP_KERNEL);
+				if (!pwr_btn_eproc) {
+			                goto remove_dir;
+				}
+				pwr_btn_eproc->ectrl = ectrl;
+				pwr_btn_eproc->event = PWR_BUTTON;
+			
+				entry = proc_create_data(ECTRL_ENTRY_ENABLE,  S_IRUGO | S_IWUGO,
+				 		global_event_list[ectrl->events[i]->id].proc_dir, &ectrl_proc_enable_fops, 
+						pwr_btn_eproc);
+				if (!entry) {
+                                        goto remove_dir;		
+			        } else {
+					add_to_list (tmp, entry_list, ECTRL_ENTRY_ENABLE, global_event_list[ectrl->events[i]->id].proc_dir);
+				}
+			
+				entry = proc_create_data(ECTRL_ENTRY_ENFLASH,  S_IRUGO | S_IWUGO,
+				 		global_event_list[ectrl->events[i]->id].proc_dir, &ectrl_proc_enflash_fops, 
+						pwr_btn_eproc);
+				if (!entry) {
+                                        goto remove_dir;
+			        } else {
+					 add_to_list (tmp, entry_list, ECTRL_ENTRY_ENFLASH, global_event_list[ectrl->events[i]->id].proc_dir);
+				}
+
+#if ECTRL_USE_OWN_STATE
+				entry = proc_create_data(ECTRL_ENTRY_STATUS,  S_IRUGO,
+				 		global_event_list[ectrl->events[i]->id].proc_dir, &ectrl_proc_state_fops, 
+						pwr_btn_eproc);
+				if (!entry) {
+                                        goto remove_dir;
+			        } else {
+					add_to_list (tmp, entry_list, ECTRL_ENTRY_STATUS, global_event_list[ectrl->events[i]->id].proc_dir);
+				}
+#endif
+				break;
+
+			case RST_BUTTON:
+				// --- reset button --- //
+				rst_btn_eproc = kzalloc (sizeof (struct ectrl_proc_event), GFP_KERNEL);
+				if (!rst_btn_eproc) {
+                                        goto remove_dir;
+				}
+				rst_btn_eproc->ectrl = ectrl;
+				rst_btn_eproc->event = RST_BUTTON;
+			
+				entry = proc_create_data(ECTRL_ENTRY_ENABLE,  S_IRUGO | S_IWUGO,
+				 		global_event_list[ectrl->events[i]->id].proc_dir, &ectrl_proc_enable_fops, 
+						rst_btn_eproc);
+				if (!entry) {
+                                        goto remove_dir;
+			        } else  {
+					add_to_list (tmp, entry_list, ECTRL_ENTRY_ENABLE, global_event_list[ectrl->events[i]->id].proc_dir);
+				}
+			
+				entry = proc_create_data(ECTRL_ENTRY_ENFLASH,  S_IRUGO | S_IWUGO,
+				 		global_event_list[ectrl->events[i]->id].proc_dir, &ectrl_proc_enflash_fops, 
+						rst_btn_eproc);
+				if (!entry) {
+                                        goto remove_dir;
+			        } else {
+					add_to_list (tmp, entry_list, ECTRL_ENTRY_ENFLASH, global_event_list[ectrl->events[i]->id].proc_dir);
+				}
+
+#if ECTRL_USE_OWN_STATE
+				entry = proc_create_data(ECTRL_ENTRY_STATUS,  S_IRUGO,
+				 		global_event_list[ectrl->events[i]->id].proc_dir, &ectrl_proc_state_fops, 
+						rst_btn_eproc);
+				if (!entry) {
+                                        goto remove_dir;
+			        } else {
+					add_to_list (tmp, entry_list, ECTRL_ENTRY_STATUS, global_event_list[ectrl->events[i]->id].proc_dir);
+				}
+#endif		
+		
+				break;
+
+			case LID_HL_SIGNAL:
+				// --- Lid high to low --- //
+				lid_hl_eproc = kzalloc (sizeof (struct ectrl_proc_event), GFP_KERNEL);
+				if (!lid_hl_eproc) {
+                                        goto remove_dir;
+				}
+				lid_hl_eproc->ectrl = ectrl;
+				lid_hl_eproc->event = LID_HL_SIGNAL;
+			
+				entry = proc_create_data(ECTRL_ENTRY_ENABLE,  S_IRUGO | S_IWUGO,
+				 		global_event_list[ectrl->events[i]->id].proc_dir, &ectrl_proc_enable_fops, 
+						lid_hl_eproc);
+				if (!entry) {
+                                        goto remove_dir;
+			        } else {
+					add_to_list (tmp, entry_list, ECTRL_ENTRY_ENABLE, global_event_list[ectrl->events[i]->id].proc_dir);
+				}
+			
+				entry = proc_create_data(ECTRL_ENTRY_ENFLASH,  S_IRUGO | S_IWUGO,
+				 		global_event_list[ectrl->events[i]->id].proc_dir, &ectrl_proc_enflash_fops, 
+						lid_hl_eproc);
+				if (!entry) {
+                                        goto remove_dir;
+			        } else {
+					add_to_list (tmp, entry_list, ECTRL_ENTRY_ENFLASH, global_event_list[ectrl->events[i]->id].proc_dir);
+				}
+
+#if ECTRL_USE_OWN_STATE
+				entry = proc_create_data(ECTRL_ENTRY_STATUS,  S_IRUGO,
+				 		global_event_list[ectrl->events[i]->id].proc_dir, &ectrl_proc_state_fops, 
+						lid_hl_eproc);
+				if (!entry) {
+                                        goto remove_dir;
+			        } else {
+					add_to_list (tmp, entry_list, ECTRL_ENTRY_STATUS, global_event_list[ectrl->events[i]->id].proc_dir);
+				}
+#endif
+			
+				break;
+			
+			case LID_LH_SIGNAL:
+				// --- Lid low to high --- //
+				lid_lh_eproc = kzalloc (sizeof (struct ectrl_proc_event), GFP_KERNEL);
+				if (!lid_lh_eproc) {
+                                        goto remove_dir;
+				}
+				lid_lh_eproc->ectrl = ectrl;
+				lid_lh_eproc->event = LID_LH_SIGNAL;
+			
+				entry = proc_create_data(ECTRL_ENTRY_ENABLE,  S_IRUGO | S_IWUGO,
+				 		global_event_list[ectrl->events[i]->id].proc_dir, &ectrl_proc_enable_fops, 
+						lid_lh_eproc);
+				if (!entry) {
+                                        goto remove_dir;
+			        } else {
+					 add_to_list (tmp, entry_list, ECTRL_ENTRY_ENABLE, global_event_list[ectrl->events[i]->id].proc_dir);
+				}
+			
+				entry = proc_create_data(ECTRL_ENTRY_ENFLASH,  S_IRUGO | S_IWUGO,
+				 		global_event_list[ectrl->events[i]->id].proc_dir, &ectrl_proc_enflash_fops, 
+						lid_lh_eproc);
+				if (!entry) {
+                                        goto remove_dir;
+			        } else {
+					add_to_list (tmp, entry_list, ECTRL_ENTRY_ENFLASH, global_event_list[ectrl->events[i]->id].proc_dir);
+				}
+
+#if ECTRL_USE_OWN_STATE
+				entry = proc_create_data(ECTRL_ENTRY_STATUS,  S_IRUGO,
+				 		global_event_list[ectrl->events[i]->id].proc_dir, &ectrl_proc_state_fops, 
+						lid_lh_eproc);
+				if (!entry) {
+                                        goto remove_dir;
+			        } else {
+					add_to_list (tmp, entry_list, ECTRL_ENTRY_STATUS, global_event_list[ectrl->events[i]->id].proc_dir);
+				}
+#endif
+
+				break;
+
+			case BATLOW_HL_SIGNAL:
+				// --- battery high to low --- //
+				batlow_hl_eproc = kzalloc (sizeof (struct ectrl_proc_event), GFP_KERNEL);
+				if (!batlow_hl_eproc) {
+                                        goto remove_dir;
+				}
+				batlow_hl_eproc->ectrl = ectrl;
+				batlow_hl_eproc->event = BATLOW_HL_SIGNAL;
+			
+				entry = proc_create_data(ECTRL_ENTRY_ENABLE,  S_IRUGO | S_IWUGO,
+				 		global_event_list[ectrl->events[i]->id].proc_dir, &ectrl_proc_enable_fops, 
+						batlow_hl_eproc);
+				if (!entry) {
+                                        goto remove_dir;
+			        } else {
+					add_to_list (tmp, entry_list, ECTRL_ENTRY_ENABLE, global_event_list[ectrl->events[i]->id].proc_dir);
+				}
+			
+				entry = proc_create_data(ECTRL_ENTRY_ENFLASH,  S_IRUGO | S_IWUGO,
+				 		global_event_list[ectrl->events[i]->id].proc_dir, &ectrl_proc_enflash_fops, 
+						batlow_hl_eproc);
+				if (!entry) {
+                                        goto remove_dir;
+			        } else {
+					add_to_list (tmp, entry_list, ECTRL_ENTRY_ENFLASH, global_event_list[ectrl->events[i]->id].proc_dir);
+				}
+
+#if ECTRL_USE_OWN_STATE
+				entry = proc_create_data(ECTRL_ENTRY_STATUS,  S_IRUGO,
+				 		global_event_list[ectrl->events[i]->id].proc_dir, &ectrl_proc_state_fops, 
+						batlow_hl_eproc);
+				if (!entry) {
+                                        goto remove_dir;
+			        } else {
+					add_to_list (tmp, entry_list, ECTRL_ENTRY_STATUS, global_event_list[ectrl->events[i]->id].proc_dir);
+				}
+#endif
+
+				break;
+
+			case BATLOW_LH_SIGNAL:
+				// --- battery low to high --- //
+				batlow_lh_eproc = kzalloc (sizeof (struct ectrl_proc_event), GFP_KERNEL);
+				if (!batlow_lh_eproc) {
+                                        goto remove_dir;
+				}
+				batlow_lh_eproc->ectrl = ectrl;
+				batlow_lh_eproc->event = BATLOW_LH_SIGNAL;
+			
+				entry = proc_create_data(ECTRL_ENTRY_ENABLE,  S_IRUGO | S_IWUGO,
+				 		global_event_list[ectrl->events[i]->id].proc_dir, &ectrl_proc_enable_fops, 
+						batlow_lh_eproc);
+				if (!entry) {
+                                        goto remove_dir;
+			        } else {
+					add_to_list (tmp, entry_list, ECTRL_ENTRY_ENABLE, global_event_list[ectrl->events[i]->id].proc_dir);
+				}
+			
+				entry = proc_create_data(ECTRL_ENTRY_ENFLASH,  S_IRUGO | S_IWUGO,
+				 		global_event_list[ectrl->events[i]->id].proc_dir, &ectrl_proc_enflash_fops, 
+						batlow_lh_eproc);
+				if (!entry) {
+                                        goto remove_dir;
+			        } else {
+					add_to_list (tmp, entry_list, ECTRL_ENTRY_ENFLASH, global_event_list[ectrl->events[i]->id].proc_dir);
+				}
+
+#if ECTRL_USE_OWN_STATE
+				entry = proc_create_data(ECTRL_ENTRY_STATUS,  S_IRUGO,
+				 		global_event_list[ectrl->events[i]->id].proc_dir, &ectrl_proc_state_fops, 
+						batlow_lh_eproc);
+				if (!entry) {
+                                        goto remove_dir;
+			        } else  {
+					add_to_list (tmp, entry_list, ECTRL_ENTRY_STATUS, global_event_list[ectrl->events[i]->id].proc_dir);
+				}
+#endif
+
+				break;
+
+
+			case SLEEP_SIGNAL:
+				// --- sleep --- //
+				sleep_eproc = kzalloc (sizeof (struct ectrl_proc_event), GFP_KERNEL);
+				if (!sleep_eproc) {
+                                        goto remove_dir;
+				}
+				sleep_eproc->ectrl = ectrl;
+				sleep_eproc->event = SLEEP_SIGNAL;
+			
+				entry = proc_create_data(ECTRL_ENTRY_ENABLE,  S_IRUGO | S_IWUGO,
+				 		global_event_list[ectrl->events[i]->id].proc_dir, &ectrl_proc_enable_fops, 
+						sleep_eproc);
+				if (!entry) {
+                                        goto remove_dir;
+			        } else {
+					add_to_list (tmp, entry_list, ECTRL_ENTRY_ENABLE, global_event_list[ectrl->events[i]->id].proc_dir);
+				}
+
+				entry = proc_create_data(ECTRL_ENTRY_ENFLASH,  S_IRUGO | S_IWUGO,
+				 		global_event_list[ectrl->events[i]->id].proc_dir, &ectrl_proc_enflash_fops, 
+						sleep_eproc);
+				if (!entry) {
+                                        goto remove_dir;
+			        } else {
+					add_to_list (tmp, entry_list, ECTRL_ENTRY_ENFLASH, global_event_list[ectrl->events[i]->id].proc_dir);
+				}
+
+#if ECTRL_USE_OWN_STATE
+				entry = proc_create_data(ECTRL_ENTRY_STATUS,  S_IRUGO,
+				 		global_event_list[ectrl->events[i]->id].proc_dir, &ectrl_proc_state_fops, 
+						sleep_eproc);
+				if (!entry) {
+                                        goto remove_dir;
+			        } else {
+					add_to_list (tmp, entry_list, ECTRL_ENTRY_STATUS, global_event_list[ectrl->events[i]->id].proc_dir);
+				}
+#endif
+				
+				break;
+
+			case WAKE_SIGNAL:
+				// --- wake signal --- //
+				wake_eproc = kzalloc (sizeof (struct ectrl_proc_event), GFP_KERNEL);
+				if (!wake_eproc) {
+			                goto remove_dir;
+				}
+				wake_eproc->ectrl = ectrl;
+				wake_eproc->event = WAKE_SIGNAL;
+			
+				entry = proc_create_data(ECTRL_ENTRY_ENABLE,  S_IRUGO | S_IWUGO,
+				 		global_event_list[ectrl->events[i]->id].proc_dir, &ectrl_proc_enable_fops, 
+						wake_eproc);
+				if (!entry) {
+                                        goto remove_dir;		
+			        } else {
+					add_to_list (tmp, entry_list, ECTRL_ENTRY_ENABLE, global_event_list[ectrl->events[i]->id].proc_dir);
+				}
+
+				entry = proc_create_data(ECTRL_ENTRY_ENFLASH,  S_IRUGO | S_IWUGO,
+				 		global_event_list[ectrl->events[i]->id].proc_dir, &ectrl_proc_enflash_fops, 
+						wake_eproc);
+				if (!entry) {
+                                        goto remove_dir;
+			        } else {
+					add_to_list (tmp, entry_list, ECTRL_ENTRY_ENFLASH, global_event_list[ectrl->events[i]->id].proc_dir);
+				}
+
+#if ECTRL_USE_OWN_STATE
+				entry = proc_create_data(ECTRL_ENTRY_STATUS,  S_IRUGO,
+				 		global_event_list[ectrl->events[i]->id].proc_dir, &ectrl_proc_state_fops, 
+						wake_eproc);
+				if (!entry) {
+                                        goto remove_dir;
+			        } else {
+					add_to_list (tmp, entry_list, ECTRL_ENTRY_STATUS, global_event_list[ectrl->events[i]->id].proc_dir);
+				}
+#endif
+				break;
+
+			default:
+				continue;
+
+		}
+	}
+
+	/* create /proc/ectrl/events/event_state */
+	ectrl_events_state_dir = proc_mkdir (ECTRL_PROC_EVENTS_STATE, ectrl_events_dir);
+	if (!ectrl_events_state_dir) {
+		goto remove_dir;		
+	} else {
+		add_to_list (tmp, entry_list, ECTRL_PROC_EVENTS_STATE, ectrl_events_dir);
+	}
+
+	for (i = 0 ; i < ectrl->nr_evn ; i++) {
+		struct ectrl_proc_event_state *state_proc;
+		switch (ectrl->evn_state[i]->evn) {
+			case EVNT_PWR_BTN:
+				pwr_btn_state_eproc = kzalloc (sizeof (struct ectrl_proc_event_state),
+						 GFP_KERNEL);
+				pwr_btn_state_eproc->ectrl = ectrl;
+				state_proc = pwr_btn_state_eproc;
+				break;
+			case EVNT_RST_BTN:
+				rst_btn_state_eproc = kzalloc (sizeof (struct ectrl_proc_event_state),
+						 GFP_KERNEL);
+				rst_btn_state_eproc->ectrl = ectrl;
+				state_proc = rst_btn_state_eproc;
+				break;
+			case EVNT_SLEEP:
+				sleep_state_eproc = kzalloc (sizeof (struct ectrl_proc_event_state),
+						 GFP_KERNEL);
+				sleep_state_eproc->ectrl = ectrl;
+				state_proc = sleep_state_eproc;
+				break;
+			case EVNT_BATTERY:
+				batlow_state_eproc = kzalloc (sizeof (struct ectrl_proc_event_state),
+						 GFP_KERNEL);
+				batlow_state_eproc->ectrl = ectrl;
+				state_proc = batlow_state_eproc;
+				break;
+			case EVNT_LID:
+				lid_state_eproc = kzalloc (sizeof (struct ectrl_proc_event_state),
+						 GFP_KERNEL);
+				lid_state_eproc->ectrl = ectrl;
+				state_proc = lid_state_eproc;
+				break;
+			case EVNT_WAKE:
+				wake_state_eproc = kzalloc (sizeof (struct ectrl_proc_event_state),
+						 GFP_KERNEL);
+				wake_state_eproc->ectrl = ectrl;
+				state_proc = wake_state_eproc;
+				break;
+			default:
+				state_proc = NULL;
+				break;
+		}	
+
+		if (state_proc != NULL) {
+			state_proc->state_id = i;
+			entry = proc_create_data(ectrl->evn_state[i]->label, 
+				S_IRUGO, ectrl_events_state_dir, &ectrl_proc_status_fops, state_proc);
+			if (!entry) {
+                        	goto remove_dir;
+			} else {
+				add_to_list (tmp, entry_list, ectrl->evn_state[i]->label, ectrl_events_state_dir);
+			}
+		}
+		
+	}
+
+
+	/* POWER MANAGEMENT TREE */
+
+	/* create /proc/ectrl/power_management */
+	ectrl_pm_dir = proc_mkdir (ECTRL_PROC_PM, ectrl_root_dir);
+	if (!ectrl_pm_dir) {
+		goto remove_dir;
+	} else {
+		add_to_list (tmp, entry_list, ECTRL_PROC_PM, ectrl_root_dir);
+	}
+
+	entry = proc_create_data(ECTRL_ENTRY_PM_STATE, S_IRUGO,
+				ectrl_pm_dir, &ectrl_proc_available_pm_state_fops, ectrl);
+	if (!entry) {
+                goto remove_dir;		
+	} else {
+		add_to_list (tmp, entry_list, ECTRL_ENTRY_PM_STATE, ectrl_pm_dir);
+	}
+
+	entry = proc_create_data(ECTRL_ENTRY_PM_PWR_STATE, S_IRUGO | S_IWUGO,
+				ectrl_pm_dir, &ectrl_proc_pm_pwr_state_fops, ectrl);
+	if (!entry) {
+                goto remove_dir;		
+	} else {
+		 add_to_list (tmp, entry_list, ECTRL_ENTRY_PM_PWR_STATE, ectrl_pm_dir);
+	}
+	
+	ectrl_pm_pwr_btn_4sec_dir = proc_mkdir (ECTRL_ENTRY_PM_PWR_BTN_4SEC, ectrl_pm_dir);
+	if (!ectrl_pm_dir) {
+		goto remove_dir;
+	} else {
+		add_to_list (tmp, entry_list, ECTRL_ENTRY_PM_PWR_BTN_4SEC, ectrl_pm_dir);
+	}
+	
+	pwr_btn_4sec_eproc = kzalloc (sizeof (struct ectrl_proc_event), GFP_KERNEL);
+	if (!pwr_btn_4sec_eproc) {
+		goto remove_dir;
+	}
+	pwr_btn_4sec_eproc->ectrl = ectrl;
+	pwr_btn_4sec_eproc->event = PWR_BTN_4SEC;
+	pwr_btn_4sec_eproc->is_true_event = 0;
+
+	entry = proc_create_data(ECTRL_ENTRY_PM_PWR_BTN_4SEC_EN,  S_IRUGO | S_IWUGO,
+			ectrl_pm_pwr_btn_4sec_dir, &ectrl_proc_enable_fops, 
+			pwr_btn_4sec_eproc);
+	if (!entry) {
+		goto remove_dir;		
+	} else {
+		add_to_list (tmp, entry_list, ECTRL_ENTRY_PM_PWR_BTN_4SEC_EN, ectrl_pm_pwr_btn_4sec_dir);
+	}
+
+	entry = proc_create_data(ECTRL_ENTRY_PM_PWR_BTN_4SEC_ENFLASH,  S_IRUGO | S_IWUGO,
+			ectrl_pm_pwr_btn_4sec_dir, &ectrl_proc_enflash_fops, 
+			pwr_btn_4sec_eproc);
+	if (!entry) {
+		goto remove_dir;
+	} else {
+		add_to_list (tmp, entry_list, ECTRL_ENTRY_PM_PWR_BTN_4SEC_ENFLASH, ectrl_pm_pwr_btn_4sec_dir);
+	}
+
+	/* BOOT TREE */
+
+	/* create /proc/ectrl/boot */
+	ectrl_boot_dir = proc_mkdir (ECTRL_PROC_BOOT, ectrl_root_dir);
+	if (!ectrl_boot_dir) {
+		goto remove_dir;
+	} else {
+		add_to_list (tmp, entry_list, ECTRL_PROC_BOOT, ectrl_root_dir);
+	}
+
+	boot0_bproc = kzalloc (sizeof (struct ectrl_proc_boot), GFP_KERNEL);
+	boot1_bproc = kzalloc (sizeof (struct ectrl_proc_boot), GFP_KERNEL);
+	boot2_bproc = kzalloc (sizeof (struct ectrl_proc_boot), GFP_KERNEL);
+	boot3_bproc = kzalloc (sizeof (struct ectrl_proc_boot), GFP_KERNEL);
+
+	if (!boot0_bproc || !boot1_bproc || !boot2_bproc || !boot3_bproc) {
+		goto remove_dir;
+	}
+
+	i = 0;
+	boot0_bproc->ectrl = ectrl;
+	boot0_bproc->idx = BOOT_IDX0;
+	entry = proc_create_data(ECTRL_ENTRY_DEVBOOT0,  S_IRUGO | S_IWUGO,
+				ectrl_boot_dir, &ectrl_proc_bootdev_fops, boot0_bproc);
+	if (!entry) {
+                goto remove_dir;		
+	} else {
+		add_to_list (tmp, entry_list, ECTRL_ENTRY_DEVBOOT0, ectrl_boot_dir);
+	}
+
+	i++;
+	boot1_bproc->ectrl = ectrl;
+	boot1_bproc->idx = BOOT_IDX1;
+	entry = proc_create_data(ECTRL_ENTRY_DEVBOOT1,  S_IRUGO | S_IWUGO,
+				ectrl_boot_dir, &ectrl_proc_bootdev_fops, boot1_bproc);
+	if (!entry) {
+                goto remove_dir;		
+	} else {
+		add_to_list (tmp, entry_list, ECTRL_ENTRY_DEVBOOT1, ectrl_boot_dir);
+	}
+
+	i++;
+	boot2_bproc->ectrl = ectrl;
+	boot2_bproc->idx = BOOT_IDX2;
+	entry = proc_create_data(ECTRL_ENTRY_DEVBOOT2,  S_IRUGO | S_IWUGO,
+				ectrl_boot_dir, &ectrl_proc_bootdev_fops, boot2_bproc);
+	if (!entry) {
+                goto remove_dir;		
+	} else {
+		add_to_list (tmp, entry_list, ECTRL_ENTRY_DEVBOOT2, ectrl_boot_dir);
+	}
+
+	i++;
+	boot3_bproc->ectrl = ectrl;
+	boot3_bproc->idx = BOOT_IDX3;
+	entry = proc_create_data(ECTRL_ENTRY_RECOVERY_BOOT, S_IRUGO | S_IWUGO,
+				ectrl_boot_dir, &ectrl_proc_bootdev_fops, boot3_bproc);
+	if (!entry) {
+                goto remove_dir;		
+	} else {
+		add_to_list (tmp, entry_list, ECTRL_ENTRY_RECOVERY_BOOT, ectrl_boot_dir);
+	}
+
+	entry = proc_create_data(ECTRL_ENTRY_BOOTDEV_LIST, S_IRUGO,
+				ectrl_boot_dir, &ectrl_proc_bootdev_list_fops, ectrl);
+	if (!entry) {
+                goto remove_dir;		
+	} else {
+		add_to_list (tmp, entry_list, ECTRL_ENTRY_BOOTDEV_LIST, ectrl_boot_dir);
+	}
+
+	entry = proc_create_data(ECTRL_ENTRY_BOOT_SEQUENCE, S_IRUGO,
+				ectrl_boot_dir, &ectrl_proc_bootseq_fops, ectrl);
+	if (!entry) {
+                goto remove_dir;		
+	} else {
+		add_to_list (tmp, entry_list, ECTRL_ENTRY_BOOT_SEQUENCE, ectrl_boot_dir);
+	}
+
+	/* WATCHDOG TREE */
+
+	/* create /proc/ectrl/watchdog */
+	ectrl_watchdog_dir = proc_mkdir (ECTRL_PROC_WATCHDOG, ectrl_root_dir);
+	if (!ectrl_watchdog_dir) {
+		goto remove_dir;
+	} else {
+		add_to_list (tmp, entry_list, ECTRL_PROC_WATCHDOG, ectrl_root_dir);
+	}
+
+	entry = proc_create_data(ECTRL_ENTRY_WDT_AVAL_EVN, S_IRUGO,
+				ectrl_watchdog_dir, &ectrl_proc_avalaible_wdt_event_fops, ectrl);
+	if (!entry) {
+                goto remove_dir;		
+	} else {
+		add_to_list (tmp, entry_list, ECTRL_ENTRY_WDT_AVAL_EVN, ectrl_watchdog_dir);
+	}
+
+	entry = proc_create_data(ECTRL_ENTRY_WDT_ENABLE, S_IRUGO | S_IWUGO,   
+				ectrl_watchdog_dir, &ectrl_proc_wdt_enable_fops, ectrl);
+	if (!entry) {
+                goto remove_dir;		
+	} else {
+		add_to_list (tmp, entry_list, ECTRL_ENTRY_WDT_ENABLE, ectrl_watchdog_dir);
+	}
+
+	entry = proc_create_data(ECTRL_ENTRY_WDT_EVENT, S_IRUGO | S_IWUGO,   
+				ectrl_watchdog_dir, &ectrl_proc_wdt_event_fops, ectrl);
+	if (!entry) {
+                goto remove_dir;		
+	} else {
+		add_to_list (tmp, entry_list, ECTRL_ENTRY_WDT_EVENT, ectrl_watchdog_dir);
+	}
+
+	entry = proc_create_data(ECTRL_ENTRY_WDT_DELAY, S_IRUGO | S_IWUGO,
+				ectrl_watchdog_dir, &ectrl_proc_wdt_delay_fops, ectrl);
+	if (!entry) {
+                goto remove_dir;		
+	} else {
+		add_to_list (tmp, entry_list, ECTRL_ENTRY_WDT_DELAY, ectrl_watchdog_dir);
+	}
+
+	entry = proc_create_data(ECTRL_ENTRY_WDT_TIMEOUT, S_IRUGO | S_IWUGO,
+				ectrl_watchdog_dir, &ectrl_proc_wdt_timeout_fops, ectrl);
+	if (!entry) {
+                goto remove_dir;		
+	} else {
+		add_to_list (tmp, entry_list, ECTRL_ENTRY_WDT_TIMEOUT, ectrl_watchdog_dir);
+	}
+
+	entry = proc_create_data(ECTRL_ENTRY_WDT_TIMER1, S_IRUGO,
+				ectrl_watchdog_dir, &ectrl_proc_wdt_timer1_fops, ectrl);
+	if (!entry) {
+                goto remove_dir;		
+	} else {
+		add_to_list (tmp, entry_list, ECTRL_ENTRY_WDT_TIMER1, ectrl_watchdog_dir);
+	}
+
+	entry = proc_create_data(ECTRL_ENTRY_WDT_TIMER2, S_IRUGO,
+			ectrl_watchdog_dir, &ectrl_proc_wdt_timer2_fops, ectrl);
+	if (!entry) {
+		goto remove_dir;		
+	} else {
+		add_to_list (tmp, entry_list, ECTRL_ENTRY_WDT_TIMER2, ectrl_watchdog_dir);
+	}
+
+	entry = proc_create_data(ECTRL_ENTRY_WDT_STATE, S_IRUGO,   
+				ectrl_watchdog_dir, &ectrl_proc_wdt_state_fops, ectrl);
+	if (!entry) {
+                goto remove_dir;		
+	} else {
+		 add_to_list (tmp, entry_list, ECTRL_ENTRY_WDT_STATE, ectrl_watchdog_dir);
+	}
+
+	entry = proc_create_data(ECTRL_ENTRY_WDT_REFRESH, S_IWUGO,   
+				ectrl_watchdog_dir, &ectrl_proc_wdt_refresh_fops, ectrl);
+	if (!entry) {
+                goto remove_dir;		
+	} else {
+		add_to_list (tmp, entry_list, ECTRL_ENTRY_WDT_REFRESH, ectrl_watchdog_dir);
+	}
+
+	entry = proc_create_data(ECTRL_ENTRY_WDT_RESTORE, S_IWUGO,   
+				ectrl_watchdog_dir, &ectrl_proc_wdt_restore_fops, ectrl);
+	if (!entry) {
+                goto remove_dir;		
+	} else {
+		add_to_list (tmp, entry_list, ECTRL_ENTRY_WDT_RESTORE, ectrl_watchdog_dir);
+	}
+
+	entry = proc_create_data(ECTRL_ENTRY_WDT_WDTOUT_RESET, S_IWUGO,   
+				ectrl_watchdog_dir, &ectrl_proc_wdt_wdtout_reset_fops, ectrl);
+	if (!entry) {
+                goto remove_dir;		
+	} else {
+		add_to_list (tmp, entry_list, ECTRL_ENTRY_WDT_WDTOUT_RESET, ectrl_watchdog_dir);
+	}
+
+	ectrl_watchdog_permanent_dir = proc_mkdir (ECTRL_PROC_WDT_PERMANENT, ectrl_watchdog_dir);
+	if (!ectrl_watchdog_permanent_dir) {
+		goto remove_dir;
+	} else {
+		add_to_list (tmp, entry_list, ECTRL_PROC_WDT_PERMANENT, ectrl_watchdog_dir);
+	}
+
+
+	entry = proc_create_data(ECTRL_ENTRY_WDT_EVENT, S_IRUGO | S_IWUGO,   
+				ectrl_watchdog_permanent_dir, &ectrl_proc_wdt_f_event_fops, ectrl);
+	if (!entry) {
+                goto remove_dir;		
+	} else {
+		add_to_list (tmp, entry_list, ECTRL_ENTRY_WDT_EVENT, ectrl_watchdog_permanent_dir);
+	}
+
+	entry = proc_create_data(ECTRL_ENTRY_WDT_DELAY, S_IRUGO | S_IWUGO,
+				ectrl_watchdog_permanent_dir, &ectrl_proc_wdt_f_delay_fops, ectrl);
+	if (!entry) {
+                goto remove_dir;		
+	} else {
+		add_to_list (tmp, entry_list, ECTRL_ENTRY_WDT_DELAY, ectrl_watchdog_permanent_dir);
+	}
+
+	entry = proc_create_data(ECTRL_ENTRY_WDT_TIMEOUT, S_IRUGO | S_IWUGO,
+				ectrl_watchdog_permanent_dir, &ectrl_proc_wdt_f_timeout_fops, ectrl);
+	if (!entry) {
+                goto remove_dir;		
+	} else {
+		add_to_list (tmp, entry_list, ECTRL_ENTRY_WDT_TIMEOUT, ectrl_watchdog_permanent_dir);
+	}
+
+	entry = proc_create_data(ECTRL_ENTRY_WDT_ENABLE, S_IRUGO | S_IWUGO,   
+				ectrl_watchdog_permanent_dir, &ectrl_proc_wdt_f_enable_fops, ectrl);
+	if (!entry) {
+                goto remove_dir;		
+	} else {
+		add_to_list (tmp, entry_list, ECTRL_ENTRY_WDT_ENABLE, ectrl_watchdog_permanent_dir);
+	}
+
+
+	/* revision identification */
+	entry = proc_create_data("build_rev", S_IRUGO, 0, &ectrl_proc_build_revisione_fops, ectrl);
+
+	entry = proc_create_data("board_rev", S_IRUGO, 0, &ectrl_proc_board_revisione_fops, ectrl);
+
+#if ECTRL_LOGGING
+	if ( logger_list != NULL ) {
+		entry = proc_create_data("ectrl_log", S_IWUGO | S_IRUGO, 0, &ectrl_proc_logger_fops, ectrl);
+	}
+#endif /* ECTRL_LOGGING */
+
+	return 0;
+remove_dir:
+	list_for_each_safe (pos, q, &entry_list->list) {
+		tmp = list_entry (pos, struct proc_entry, list);
+		remove_proc_entry (tmp->label, tmp->entry);
+		list_del (pos);
+		kfree (tmp);	
+	}
+	return -EINVAL;
+}
+
+
+static void ectrl_remove_proc_fs (struct econtroller *ectrl) {
+	struct proc_entry *tmp;
+	struct list_head *pos, *q;
+	list_for_each_safe (pos, q, &entry_list->list) {
+		tmp = list_entry (pos, struct proc_entry, list);
+		remove_proc_entry (tmp->label, tmp->entry);
+		list_del (pos);
+		kfree (tmp);	
+	}
+}
+
+
+/* --------------------------------------------------------------------------
+                                     IOCTL
+   -------------------------------------------------------------------------- */
+
+static long ectrl_ioctl (struct file *file, unsigned int cmd, unsigned long arg) {
+
+	struct i2c_client  *client = file->private_data;
+	struct econtroller *ectrl = dev_get_drvdata (&client->dev);
+	int err = 0;
+	int retval = 0;
+	dev_dbg(&client->dev, "ioctl, cmd=0x%02x, arg=0x%02lx\n", cmd, arg);
+
+	switch (cmd) {
+
+		case ECTRL_IOCTL_REG_READ: {
+			struct ectrl_reg reg;
+			struct ectrl_reg_rw reg_rw;
+			mutex_lock (&ectrl->ioctl_lock);
+			if (copy_from_user (&reg, (const void __user *)arg, sizeof (reg))) {
+				mutex_unlock (&ectrl->ioctl_lock);
+				return -EFAULT;
+			}
+			get_reg_rw (&reg_rw, reg, R_OP);
+			err = ectrl_mem_single_op (client, &reg_rw);
+			reg.data = reg_rw.reg.data;
+			if (err < 0)
+				retval = err;
+			if (copy_to_user ((void __user *)arg, &reg, sizeof (reg))) {
+				mutex_unlock (&ectrl->ioctl_lock);
+				retval = -EFAULT;
+			}
+			mutex_unlock (&ectrl->ioctl_lock);
+			break;
+		}
+
+		case ECTRL_IOCTL_REG_WRITE: {
+			struct ectrl_reg reg;
+			struct ectrl_reg_rw reg_rw;
+			mutex_lock (&ectrl->ioctl_lock);
+			if (copy_from_user (&reg, (const void __user *)arg, sizeof (reg))) {
+				mutex_unlock (&ectrl->ioctl_lock);
+				return -EFAULT;
+			}
+			get_reg_rw (&reg_rw, reg, W_OP);
+			err = ectrl_mem_single_op (client, &reg_rw);
+			reg.data = reg_rw.reg.data;
+			if (err < 0)
+				retval = err;
+			if (copy_to_user ((void __user *)arg, &reg, sizeof (reg))) {
+				mutex_unlock (&ectrl->ioctl_lock);
+				retval = -EFAULT;
+			}
+			mutex_unlock (&ectrl->ioctl_lock);
+			break;
+		}
+
+		case ECTRL_EV_STATE_GET: {
+			struct ectrl_ev_state ev_state;
+
+			mutex_lock (&ectrl->ioctl_lock);
+
+			if ( copy_from_user (&ev_state, (const void __user *)arg, sizeof (ev_state)) ) {
+				mutex_unlock (&ectrl->ioctl_lock);
+				return -EFAULT;
+			}
+
+			if ( !is_feasibleEvent (ectrl, ev_state.id) ) {
+				mutex_unlock (&ectrl->ioctl_lock);
+				return -EINVAL;
+			}
+
+			mutex_lock (&ectrl->fs_lock);
+			ev_state.v_enable = getEnable (ectrl->client, ev_state.id);
+			ev_state.f_enable = getEnFlash (ectrl->client, ev_state.id);
+			mutex_unlock (&ectrl->fs_lock);
+
+			if ( copy_to_user ((void __user *)arg, &ev_state, sizeof (ev_state)) ) {
+				mutex_unlock (&ectrl->ioctl_lock);
+				return -EFAULT;
+			}
+
+			mutex_unlock (&ectrl->ioctl_lock);
+			break;
+
+		}
+
+		case ECTRL_EV_STATE_SET: {
+			struct ectrl_ev_state ev_state;
+
+			mutex_lock (&ectrl->ioctl_lock);
+
+			if ( copy_from_user (&ev_state, (const void __user *)arg, sizeof (ev_state)) ) {
+				mutex_unlock (&ectrl->ioctl_lock);
+				return -EFAULT;
+			}
+
+			mutex_lock (&ectrl->fs_lock);
+
+			if ( !is_feasibleEvent (ectrl, ev_state.id) ) {
+				mutex_unlock (&ectrl->fs_lock);
+				mutex_unlock (&ectrl->ioctl_lock);
+				return -EINVAL;
+			}
+
+			setEnable (ectrl->client, ev_state.id, !!ev_state.v_enable);
+			setEnFlash (ectrl->client, ev_state.id, !!ev_state.f_enable);
+			mutex_unlock (&ectrl->fs_lock);
+
+			mutex_unlock (&ectrl->ioctl_lock);
+			break;
+		}
+
+		case ECTRL_PWR_STATE_GET: {
+			enum ECTRL_POWER_STATE pwr_state;
+
+			mutex_lock (&ectrl->ioctl_lock);
+
+			mutex_lock (&ectrl->fs_lock);
+			pwr_state = PMgetAlwaysState (ectrl->client) == (u16)ALWAYS_ON ? PWR_ALWAYS_ON : PWR_ALWAYS_OFF;
+			mutex_unlock (&ectrl->fs_lock);
+
+			if ( copy_to_user ((void __user *)arg, &pwr_state, sizeof (pwr_state)) ) {
+				mutex_unlock (&ectrl->ioctl_lock);
+				return -EFAULT;
+			}
+
+			mutex_unlock (&ectrl->ioctl_lock);
+			break;
+		}
+
+		case ECTRL_PWR_STATE_SET: {
+			enum ECTRL_POWER_STATE pwr_state;
+
+			mutex_lock (&ectrl->ioctl_lock);
+
+			if ( copy_from_user (&pwr_state, (const void __user *)arg, sizeof (pwr_state)) ) {
+				mutex_unlock (&ectrl->ioctl_lock);
+				return -EFAULT;
+			}
+
+			if ( pwr_state != PWR_ALWAYS_OFF && pwr_state != PWR_ALWAYS_ON ) {
+				mutex_unlock (&ectrl->ioctl_lock);
+				return -EINVAL;
+			}
+
+			mutex_lock (&ectrl->fs_lock);
+			if ( pwr_state == PWR_ALWAYS_OFF ) {
+				PMsetAlwaysState (ectrl->client, ALWAYS_OFF);
+			} else {
+				PMsetAlwaysState (ectrl->client, ALWAYS_ON);
+			}
+			mutex_unlock (&ectrl->fs_lock);
+
+			mutex_unlock (&ectrl->ioctl_lock);
+
+			break;
+		}
+
+		case ECTRL_PWR_BTN_4SEC_STATE_GET: {
+			struct ectrl_ev_state ev_state;
+
+			mutex_lock (&ectrl->ioctl_lock);
+
+			mutex_lock (&ectrl->fs_lock);
+			ev_state.id       = PWR_BTN_4SEC;
+			ev_state.v_enable = getEnable (ectrl->client, ev_state.id);
+			ev_state.f_enable = getEnFlash (ectrl->client, ev_state.id);
+			mutex_unlock (&ectrl->fs_lock);
+
+			if ( copy_to_user ((void __user *)arg, &ev_state, sizeof (ev_state)) ) {
+				mutex_lock (&ectrl->fs_lock);
+				mutex_unlock (&ectrl->ioctl_lock);
+				return -EFAULT;
+			}
+			mutex_unlock (&ectrl->ioctl_lock);
+
+			break;
+		}
+
+		case ECTRL_PWR_BTN_4SEC_STATE_SET: {
+			struct ectrl_ev_state ev_state;
+
+			mutex_lock (&ectrl->ioctl_lock);
+			if ( copy_from_user (&ev_state, (const void __user *)arg, sizeof (ev_state)) ) {
+				mutex_unlock (&ectrl->ioctl_lock);
+				return -EFAULT;
+			}
+
+			ev_state.id = PWR_BTN_4SEC;
+			mutex_lock (&ectrl->fs_lock);
+			setEnable (ectrl->client, ev_state.id, !!ev_state.v_enable);
+			setEnFlash (ectrl->client, ev_state.id, !!ev_state.f_enable);
+			mutex_unlock (&ectrl->fs_lock);
+
+			mutex_unlock (&ectrl->ioctl_lock);
+			break;
+		}
+
+		case ECTRL_BOOT_NUM_DEV_GET: {
+			int n_dev = ectrl->nr_bootdev;
+
+			mutex_lock (&ectrl->ioctl_lock);
+			if ( copy_to_user ((void __user *)arg, &n_dev, sizeof (n_dev)) ) {
+				mutex_unlock (&ectrl->ioctl_lock);
+				return -EFAULT;
+			}
+
+			mutex_unlock (&ectrl->ioctl_lock);
+			break;
+		}
+
+		case ECTRL_BOOT_DEV_LIST_GET: {
+			int                      n_dev    = ectrl->nr_bootdev;
+			int                      i, size;
+			struct ectrl_boot_device *bd_list = NULL;
+
+			mutex_lock (&ectrl->ioctl_lock);
+
+			size = sizeof (struct ectrl_boot_device) * n_dev;
+			bd_list = kzalloc (size, GFP_KERNEL);
+			if ( !bd_list ) {
+				mutex_unlock (&ectrl->ioctl_lock);
+				return -ENOMEM;
+			}
+
+			mutex_lock (&ectrl->fs_lock);
+			for (i = 0 ; i < ectrl->nr_bootdev ; i++) {
+				bd_list[i].id = ectrl->bootdev_list[i].id;
+				strcpy (bd_list[i].label, ectrl->bootdev_list[i].label);
+			}
+			mutex_unlock (&ectrl->fs_lock);
+
+			if ( copy_to_user ((void __user *)arg, bd_list, size) ) {
+				mutex_unlock (&ectrl->ioctl_lock);
+				return -EFAULT;
+			}
+
+			kfree (bd_list);
+
+			mutex_unlock (&ectrl->ioctl_lock);
+			break;
+		}
+
+		case ECTRL_BOOT_DEV_1_GET: {
+			struct ectrl_boot_device bd;
+			enum BOOTDEV_ID          bootdev;
+			int                      index;
+
+			mutex_lock (&ectrl->ioctl_lock);
+			mutex_lock (&ectrl->fs_lock);
+			bootdev = (enum BOOTDEV_ID)getBootDev (ectrl, 0);
+			index = isAvaildableBootdev (ectrl, bootdev);
+
+			if ( index >= 0 ) {
+				bd.id = ectrl->bootdev_list[index].id;
+				strcpy (bd.label, ectrl->bootdev_list[index].label);
+			} else {
+				mutex_unlock (&ectrl->fs_lock);
+				mutex_unlock (&ectrl->ioctl_lock);
+				return -EINVAL;
+			}
+			mutex_unlock (&ectrl->fs_lock);
+
+			if ( copy_to_user ((void __user *)arg, &bd, sizeof (bd)) ) {
+				mutex_unlock (&ectrl->ioctl_lock);
+				return -EFAULT;
+			}
+
+			mutex_unlock (&ectrl->ioctl_lock);
+			break;
+		}
+
+		case ECTRL_BOOT_DEV_2_GET: {
+			struct ectrl_boot_device bd;
+			enum BOOTDEV_ID          bootdev;
+			int                      index;
+
+			mutex_lock (&ectrl->ioctl_lock);
+			mutex_lock (&ectrl->fs_lock);
+			bootdev = (enum BOOTDEV_ID)getBootDev (ectrl, 1);
+			index = isAvaildableBootdev (ectrl, bootdev);
+
+			if ( index >= 0 ) {
+				bd.id = ectrl->bootdev_list[index].id;
+				strcpy (bd.label, ectrl->bootdev_list[index].label);
+			} else {
+				mutex_unlock (&ectrl->fs_lock);
+				mutex_unlock (&ectrl->ioctl_lock);
+				return -EINVAL;
+			}
+			mutex_unlock (&ectrl->fs_lock);
+
+			if ( copy_to_user ((void __user *)arg, &bd, sizeof (bd)) ) {
+				mutex_unlock (&ectrl->ioctl_lock);
+				return -EFAULT;
+			}
+
+			mutex_unlock (&ectrl->ioctl_lock);
+			break;
+		}
+
+		case ECTRL_BOOT_DEV_3_GET: {
+			struct ectrl_boot_device bd;
+			enum BOOTDEV_ID          bootdev;
+			int                      index;
+
+			mutex_lock (&ectrl->ioctl_lock);
+			mutex_lock (&ectrl->fs_lock);
+			bootdev = (enum BOOTDEV_ID)getBootDev (ectrl, 2);
+			index = isAvaildableBootdev (ectrl, bootdev);
+
+			if ( index >= 0 ) {
+				bd.id = ectrl->bootdev_list[index].id;
+				strcpy (bd.label, ectrl->bootdev_list[index].label);
+			} else {
+				mutex_unlock (&ectrl->fs_lock);
+				mutex_unlock (&ectrl->ioctl_lock);
+				return -EINVAL;
+			}
+			mutex_unlock (&ectrl->fs_lock);
+
+			if ( copy_to_user ((void __user *)arg, &bd, sizeof (bd)) ) {
+				mutex_unlock (&ectrl->ioctl_lock);
+				return -EFAULT;
+			}
+
+			mutex_unlock (&ectrl->ioctl_lock);
+			break;
+		}
+
+		case ECTRL_BOOT_DEV_RECOVERY_GET: {
+			struct ectrl_boot_device bd;
+			enum BOOTDEV_ID          bootdev;
+			int                      index;
+
+			mutex_lock (&ectrl->ioctl_lock);
+			mutex_lock (&ectrl->fs_lock);
+			bootdev = (enum BOOTDEV_ID)getBootDev (ectrl, 3);
+			index = isAvaildableBootdev (ectrl, bootdev);
+
+			if ( index >= 0 ) {
+				bd.id = ectrl->bootdev_list[index].id;
+				strcpy (bd.label, ectrl->bootdev_list[index].label);
+			} else {
+				mutex_unlock (&ectrl->fs_lock);
+				mutex_unlock (&ectrl->ioctl_lock);
+				return -EINVAL;
+			}
+			mutex_unlock (&ectrl->fs_lock);
+
+			if ( copy_to_user ((void __user *)arg, &bd, sizeof (bd)) ) {
+				mutex_unlock (&ectrl->ioctl_lock);
+				return -EFAULT;
+			}
+
+			mutex_unlock (&ectrl->ioctl_lock);
+			break;
+		}
+
+		case ECTRL_BOOT_DEV_1_SET: {
+			enum BOOTDEV_ID  bootdev;
+
+			mutex_lock (&ectrl->ioctl_lock);
+			if ( copy_from_user (&bootdev, (const void __user *)arg, sizeof (bootdev)) ) {
+				mutex_unlock (&ectrl->ioctl_lock);
+				return -EFAULT;
+			}
+
+			mutex_lock (&ectrl->fs_lock);
+			if ( setBootDev (ectrl, 0, bootdev) < 0 ) {
+				mutex_unlock (&ectrl->fs_lock);
+				mutex_unlock (&ectrl->ioctl_lock);
+				return -EINVAL;
+			}
+			mutex_unlock (&ectrl->fs_lock);
+
+			mutex_unlock (&ectrl->ioctl_lock);
+			break;
+		}
+
+
+		case ECTRL_BOOT_DEV_2_SET: {
+			enum BOOTDEV_ID  bootdev;
+
+			mutex_unlock (&ectrl->ioctl_lock);
+			if ( copy_from_user (&bootdev, (const void __user *)arg, sizeof (bootdev)) ) {
+				mutex_unlock (&ectrl->ioctl_lock);
+				return -EFAULT;
+			}
+
+			mutex_lock (&ectrl->fs_lock);
+			if ( setBootDev (ectrl, 1, bootdev) < 0 ) {
+				mutex_unlock (&ectrl->fs_lock);
+				mutex_unlock (&ectrl->ioctl_lock);
+				return -EINVAL;
+			}
+			mutex_unlock (&ectrl->fs_lock);
+
+			mutex_unlock (&ectrl->ioctl_lock);
+			break;
+		}
+
+		case ECTRL_BOOT_DEV_3_SET: {
+			enum BOOTDEV_ID  bootdev;
+
+			mutex_lock (&ectrl->ioctl_lock);
+			if ( copy_from_user (&bootdev, (const void __user *)arg, sizeof (bootdev)) ) {
+				mutex_unlock (&ectrl->ioctl_lock);
+				return -EFAULT;
+			}
+
+			mutex_lock (&ectrl->fs_lock);
+			if ( setBootDev (ectrl, 2, bootdev) < 0 ) {
+				mutex_unlock (&ectrl->fs_lock);
+				mutex_unlock (&ectrl->ioctl_lock);
+				return -EINVAL;
+			}
+			mutex_unlock (&ectrl->fs_lock);
+
+			mutex_unlock (&ectrl->ioctl_lock);
+			break;
+		}
+
+		case ECTRL_BOOT_DEV_RECOVERY_SET: {
+			enum BOOTDEV_ID  bootdev;
+
+			mutex_lock (&ectrl->ioctl_lock);
+			if ( copy_from_user (&bootdev, (const void __user *)arg, sizeof (bootdev)) ) {
+				mutex_unlock (&ectrl->ioctl_lock);
+				return -EFAULT;
+			}
+
+			mutex_lock (&ectrl->fs_lock);
+			if ( setBootDev (ectrl, 3, bootdev) < 0 ) {
+				mutex_unlock (&ectrl->fs_lock);
+				mutex_unlock (&ectrl->ioctl_lock);
+				return -EINVAL;
+			}
+			mutex_unlock (&ectrl->fs_lock);
+			mutex_unlock (&ectrl->ioctl_lock);
+
+			break;
+		}
+
+		case ECTRL_WDT_NUM_EVENT_GET: {
+			int n_event = ectrl->nr_wdt_event;
+
+			mutex_lock (&ectrl->ioctl_lock);
+			if ( copy_to_user ((void __user *)arg, &n_event, sizeof (n_event)) ) {
+				mutex_unlock (&ectrl->ioctl_lock);
+				return -EFAULT;
+			}
+
+			mutex_unlock (&ectrl->ioctl_lock);
+			break;
+		}
+
+		case ECTRL_WDT_EVENT_LIST_GET: {
+			int                   n_event  = ectrl->nr_wdt_event;
+			int                   i, size;
+			struct wdt_event_data *ev_list = NULL;
+
+			mutex_lock (&ectrl->ioctl_lock);
+
+			size = sizeof (struct wdt_event_data) * n_event;
+			ev_list = kzalloc (size, GFP_KERNEL);
+			if ( !ev_list ) {
+				mutex_unlock (&ectrl->ioctl_lock);
+				return -ENOMEM;
+			}
+
+			mutex_lock (&ectrl->fs_lock);
+			for ( i = 0 ; i < n_event ; i++ ) {
+				ev_list[i].id = ectrl->wdt_event_list[i].id;
+				strcpy (ev_list[i].label, ectrl->wdt_event_list[i].label);
+			}
+			mutex_unlock (&ectrl->fs_lock);
+
+			if ( copy_to_user ((void __user *)arg, ev_list, size) ) {
+				mutex_unlock (&ectrl->ioctl_lock);
+				return -EFAULT;
+			}
+
+			kfree (ev_list);
+
+			mutex_unlock (&ectrl->ioctl_lock);
+			break;
+		}
+
+		case ECTRL_WDT_GET: {
+			struct ectrl_wdt wdt;
+
+			mutex_lock (&ectrl->ioctl_lock);
+			mutex_lock (&ectrl->fs_lock);
+			wdt.v_enable      = WDTgetEnableReg (ectrl->client);
+			wdt.v_event       = WDTgetEvent (ectrl->client);
+			wdt.v_delay_sec   = WDTgetDelayReg (ectrl->client);
+			wdt.v_timeout_sec = WDTgetTimeoutReg (ectrl->client);
+
+			wdt.f_enable      = WDT_F_getEnableReg (ectrl->client);
+			wdt.f_event       = WDT_F_getEventReg (ectrl->client);
+			wdt.f_delay_sec   = WDT_F_getDelayReg (ectrl->client);
+			wdt.f_timeout_sec = WDT_F_getTimeoutReg (ectrl->client);
+
+			wdt.timer_delay = WDTgetTimer1Reg (ectrl->client);
+			wdt.timer_wd    = WDTgetTimer2Reg (ectrl->client);
+			mutex_unlock (&ectrl->fs_lock);
+
+			if ( copy_to_user ((void __user *)arg, &wdt, sizeof (wdt)) ) {
+				mutex_unlock (&ectrl->ioctl_lock);
+				return -EFAULT;
+			}
+
+			mutex_unlock (&ectrl->ioctl_lock);
+			break;
+		}
+
+		case ECTRL_WDT_SET: {
+			struct ectrl_wdt wdt;
+			int              is_correct = 1;
+			enum wdt_event   v_id, f_id;
+
+			mutex_lock (&ectrl->ioctl_lock);
+			if ( copy_from_user (&wdt, (const void __user *)arg, sizeof (wdt)) ) {
+				mutex_unlock (&ectrl->ioctl_lock);
+				return -EFAULT;
+			}
+
+			if ( wdt.v_enable != 0 && wdt.v_enable != 1 )
+				is_correct = 0;
+			if ( wdt.v_delay_sec < 1 )
+				is_correct = 0;
+			if ( wdt.v_timeout_sec < 1 )
+				is_correct = 0;
+
+			if ( wdt.f_enable != 0 && wdt.f_enable != 1 )
+				is_correct = 0;
+			if ( wdt.f_delay_sec < 1 )
+				is_correct = 0;
+			if ( wdt.f_timeout_sec < 1 )
+				is_correct = 0;
+
+			if ( is_correct == 0 ) {
+				mutex_unlock (&ectrl->ioctl_lock);
+				return -EINVAL;
+			}
+
+			mutex_lock (&ectrl->fs_lock);
+			v_id = WDTgetEvent (ectrl->client);
+			f_id = WDT_F_getEventReg (ectrl->client);
+
+			if ( WDTsetEvent (ectrl->client, wdt.v_event) < 0 ||
+			  WDT_F_setEvent (ectrl->client, wdt.f_event) < 0 )	{
+				//restore old value
+				WDTsetEvent (ectrl->client, v_id);
+				WDT_F_setEvent (ectrl->client, f_id);
+				mutex_unlock (&ectrl->fs_lock);
+				mutex_unlock (&ectrl->ioctl_lock);
+				return -EINVAL;
+			}
+
+			WDTsetEnableReg (ectrl->client, wdt.v_enable);
+			WDTsetDelayReg (ectrl->client, (u16)wdt.v_delay_sec);
+			WDTsetTimeoutReg (ectrl->client, (u16)wdt.v_timeout_sec);
+
+			WDT_F_setEnable (ectrl->client, wdt.f_enable);
+			WDT_F_setDelayReg (ectrl->client, (u16)wdt.f_delay_sec);
+			WDT_F_setTimeoutReg (ectrl->client, (u16)wdt.f_timeout_sec);
+			mutex_unlock (&ectrl->fs_lock);
+
+			mutex_unlock (&ectrl->ioctl_lock);
+			break;
+		}
+
+		case ECTRL_WDT_REFRESH: {
+
+			mutex_lock (&ectrl->ioctl_lock);
+			WDTrefresh (ectrl->client);
+			mutex_unlock (&ectrl->ioctl_lock);
+
+			break;
+		}
+
+		case ECTRL_WDT_RESTORE: {
+			u16 f_delay, f_timeout;
+
+			mutex_lock (&ectrl->ioctl_lock);
+			mutex_lock (&ectrl->fs_lock);
+			f_delay   = (u16)WDT_F_getDelayReg (ectrl->client);
+			f_timeout = (u16)WDT_F_getTimeoutReg (ectrl->client);
+
+			WDTsetDelayReg (ectrl->client, f_delay);
+			WDTsetTimeoutReg (ectrl->client, f_timeout);
+			mutex_unlock (&ectrl->fs_lock);
+
+			mutex_unlock (&ectrl->ioctl_lock);
+			break;
+		}
+
+		default:
+			break;
+	}
+	return retval;
+}
+
+
+static int ectrl_open(struct inode *inode, struct file *file) {
+	file->private_data = ectrl->client;
+	return 0;
+}
+
+
+int ectrl_release(struct inode *inode, struct file *file) {
+	file->private_data = NULL;
+	return 0;
+}
+
+
+static const struct file_operations  ectrl_fileops = {
+	.open = ectrl_open,
+	.unlocked_ioctl = ectrl_ioctl,
+	.release = ectrl_release,
+};
+
+
+static struct miscdevice ectrl_device = {
+	.minor = MISC_DYNAMIC_MINOR,
+	.name = "econtroller",
+	.fops = &ectrl_fileops,
+};
+
+
+
+#if ECTRL_LOGGING
+static void print_debug (struct econtroller *ectrl) {
+	enum BOOTDEV_ID bootdev;
+	int             index, i, enable;
+	enum wdt_event  event;
+
+	ECTRL_INFO ("*** Debug Info State ***");
+
+	ECTRL_INFO ("Event Volatile State");
+	/*  Events  */
+	for (i = 0 ; i < ectrl->nr_evn ; i++) {
+		enable = getEnable (ectrl->client, ectrl->evn_state[i]->reg_idx);
+		ECTRL_INFO ("%s: %d", ectrl->evn_state[i]->label, enable == 0 ? 1 : 0);
+	}
+	ECTRL_INFO ("Event Permanent State");
+	for (i = 0 ; i < ectrl->nr_evn ; i++) {
+		enable = getEnFlash (ectrl->client, ectrl->evn_state[i]->reg_idx);
+		ECTRL_INFO ("%s: %d", ectrl->evn_state[i]->label, enable == 0 ? 1 : 0);
+	}
+
+	/*  Boot   */
+	ECTRL_INFO ("Boot Sequence Setting:");
+	bootdev = (enum BOOTDEV_ID)getBootDev (ectrl, BOOT_IDX0);
+	index = isAvaildableBootdev (ectrl, bootdev);
+	ECTRL_INFO ("Boot Device %d: %s", BOOT_IDX0,
+		  index < 0 ? "<no label>" : ectrl->bootdev_list[index].label);
+	bootdev = (enum BOOTDEV_ID)getBootDev (ectrl, BOOT_IDX1);
+	index = isAvaildableBootdev (ectrl, bootdev);
+	ECTRL_INFO ("Boot Device %d: %s", BOOT_IDX1,
+		  index < 0 ? "<no label>" : ectrl->bootdev_list[index].label);
+	bootdev = (enum BOOTDEV_ID)getBootDev (ectrl, BOOT_IDX2);
+	index = isAvaildableBootdev (ectrl, bootdev);
+	ECTRL_INFO ("Boot Device %d: %s", BOOT_IDX2,
+		  index < 0 ? "<no label>" : ectrl->bootdev_list[index].label);
+	bootdev = (enum BOOTDEV_ID)getBootDev (ectrl, BOOT_IDX3);
+	index = isAvaildableBootdev (ectrl, bootdev);
+	ECTRL_INFO ("Boot Device %d: %s", BOOT_IDX3,
+		  index < 0 ? "<no label>" : ectrl->bootdev_list[index].label);
+
+	/*  WatchDog  */
+	enable = WDTgetEnableReg (ectrl->client);
+	event = WDTgetEvent (ectrl->client);
+	index = (int)event;
+	ECTRL_INFO ("WDT Volatile Setting:");
+	ECTRL_INFO ("enable: %d", enable);
+	ECTRL_INFO ("event: %d", index);
+	ECTRL_INFO ("%20s : %d", ECTRL_ENTRY_WDT_DELAY,    WDTgetDelayReg (ectrl->client));
+	ECTRL_INFO ("%20s : %d", ECTRL_ENTRY_WDT_TIMEOUT,  WDTgetTimeoutReg (ectrl->client));
+	ECTRL_INFO ("%20s : %d", ECTRL_ENTRY_WDT_TIMER1,   WDTgetTimer1Reg (ectrl->client));
+	ECTRL_INFO ("%20s : %d", ECTRL_ENTRY_WDT_TIMER2,   WDTgetTimer2Reg (ectrl->client));
+
+	ECTRL_INFO ("WDT Permanent Setting:");
+	enable = WDT_F_getEnableReg (ectrl->client);
+	event = WDT_F_getEventReg (ectrl->client);
+	index = (int)event;
+	ECTRL_INFO ("enable: %d", enable);
+	ECTRL_INFO ("event: %d", index);
+	ECTRL_INFO ("%20s : %d", ECTRL_ENTRY_WDT_DELAY,    WDT_F_getDelayReg (ectrl->client));
+	ECTRL_INFO ("%20s : %d", ECTRL_ENTRY_WDT_TIMEOUT,  WDT_F_getTimeoutReg (ectrl->client));
+
+	ECTRL_INFO ("*** End Debug ***");
+}
+#endif
+
+
+/************************************/
+
+static void manage_event (struct econtroller *ectrl, struct event_dev *event) {
+	int code = 0;
+	switch (event->id) {
+		case PWR_BUTTON:
+			code = KEY_F4;
+			break;
+		case SLEEP_SIGNAL:
+			code = BTN_ECTRL_SLEEP;
+			break;
+		case WAKE_SIGNAL:
+			code = BTN_ECTRL_WAKE;
+			break;
+		case BATLOW_HL_SIGNAL:
+			code = BTN_ECTRL_BATLOW_HL;
+			break;
+		case BATLOW_LH_SIGNAL:
+			code = BTN_ECTRL_BATLOW_LH;
+			break;
+		case LID_HL_SIGNAL:
+			code = BTN_ECTRL_LID_HL;
+			break;
+		case LID_LH_SIGNAL:
+			code = BTN_ECTRL_LID_LH;
+			break;
+		default:
+			code = -1;
+			break; 
+	}
+	
+	if ( code > 0 ) {
+		input_report_key (event->input, code, 1);
+		input_sync (event->input);
+		input_report_key (event->input, code, 0);
+		input_sync (event->input);
+
+		ECTRL_INFO ("event name: %s, code %d\n", event->name, code);
+	} else {
+		ECTRL_ERR ("invalid event occures !!!");
+	}
+}
+
+
+static int getIdxStatus (struct econtroller *ectrl, int event) {
+	int idx;
+	for (idx = 0 ; idx < ectrl->nr_evn ; idx++)
+		if (ectrl->evn_state[idx]->evn == event)
+			return idx;
+	return -1;
+}
+
+#define TIME_POWER_PRESSED  40 /* ms */
+static void ectr_work_pwr_btn_snooper (struct work_struct *work) {
+	struct econtroller *ectrl = container_of(to_delayed_work(work), struct econtroller, work_snooper_pwr_btn);
+	int status = 0;
+	if (ectrl->client) { 
+		status = getStatus (ectrl->client, 
+				ectrl->evn_state[getIdxStatus(ectrl, EVNT_PWR_BTN)]->reg_idx);
+		if (time_after (jiffies, ectrl->orig_jiffies + TIME_POWER_PRESSED)) {
+			return;
+		} else {
+			if (!status) { // button still active, re-schedule the work
+				schedule_delayed_work (&ectrl->work_snooper_pwr_btn, 
+					msecs_to_jiffies(ectrl->poll_period_snooper_pwr_btn));
+			} else { // button is no longer active, we have a valid short pressed
+				 // power button event, so we will notify this to the system
+				manage_event (ectrl, ectrl->events[PWR_BUTTON]);
+				return;
+			}
+		}
+	} else {
+		return;
+	}
+}
+
+
+#define GET_EVENT_FLAG(reg, event)  ((reg) & event->index_reg) >> event->shift
+
+static void ectrl_work (struct work_struct *work) {	
+	int i;
+	static int  flag_reg = 0;
+	static int  en_reg = 0; 
+	struct econtroller *ectrl = container_of(to_delayed_work(work), struct econtroller, work);
+	if (ectrl->client) {
+		// since an event was detected, we temporary disable all event, writing 
+		// 0x0000 into the enable register. But, first we must save the current
+		// state of this register
+		if (en_reg == 0) {
+			en_reg = getEnableReg (ectrl->client);
+			setEnableReg (ectrl->client, 0x0000);
+		}
+		if (flag_reg == 0) {
+			flag_reg = getFlagReg (ectrl->client);	
+		}
+	} else {
+		return;
+	}
+	if (flag_reg) {
+		// detect event
+		for (i = 0 ; i < ectrl->nr_evnt ; i++) {
+			if (GET_EVENT_FLAG(flag_reg, ectrl->events[i]) == 1) {
+				if (ectrl->events[i]->id == PWR_BUTTON) {
+					ectrl->orig_jiffies = jiffies;
+					schedule_delayed_work (&ectrl->work_snooper_pwr_btn,
+						msecs_to_jiffies(ectrl->poll_period_snooper_pwr_btn));
+				} else {
+					manage_event (ectrl, ectrl->events[i]);
+				}
+				flag_reg &= ~(1 << (*ectrl->events[i]).shift);
+			}
+		}
+		// we have to clean the served event's flag 
+		setFlagReg (ectrl->client, 0);
+		udelay (10);
+		schedule_delayed_work (&ectrl->work, msecs_to_jiffies(ectrl->poll_period));
+	} else {
+		// there is no event to handle
+		// this is a safe write, to ensure that the IRQ signal becomes high
+		ectrl_write_data (ectrl->client, FLAG_REG, 0);
+		enable_irq (ectrl->irq);
+		setEnableReg (ectrl->client, en_reg);
+		en_reg = 0;
+	}
+}
+
+
+static void ectrl_free_irq (struct econtroller *ectrl) {
+	free_irq (ectrl->irq, ectrl);
+        if (cancel_delayed_work_sync(&ectrl->work)) {
+                /*
+                 * Work was pending, therefore we need to enable
+                 * IRQ here to balance the disable_irq() done in the
+                 * interrupt handler.
+                 */
+                enable_irq(ectrl->irq);
+        }
+}
+
+
+static irqreturn_t irq_interrupt_manager (int irq, void *dev_id)  {
+	struct econtroller *ectrl = *((struct econtroller **)dev_id);
+
+	disable_irq_nosync (ectrl->irq);
+	schedule_delayed_work (&ectrl->work, msecs_to_jiffies(ectrl->poll_period));
+
+	return IRQ_HANDLED;
+}
+
+
+static void ectrl_detect_state (struct econtroller *ectrl, int *enable, int *flags, int *states) {
+	*flags = getFlagReg (ectrl->client);
+	*states = getStatusReg (ectrl->client);
+	// to ensure that no other events rise during the resolving of the state of the
+	// machine, the enable of all events will be put to zero.
+	// The normal state of enable register will be restore at the end of this procedure.
+	*enable = getEnableReg (ectrl->client);
+	setEnableReg (ectrl->client, 0x0000);
+}
+
+
+static void ectrl_resolve_state (struct econtroller *ectrl, int enable, int flags, int status) {
+	int i;
+	int nr_events = ectrl->nr_evnt;
+	for (i = 0 ; i < nr_events ; i++) {
+		if (GET_EVENT_FLAG(flags, ectrl->events[i]) == 1) {
+			manage_event (ectrl, ectrl->events[i]);
+			flags &= ~(1 << global_event_list[ectrl->events[i]->id].shift);
+		}
+	}
+	// we have to clean the served event's flag 
+	setFlagReg (ectrl->client, 0x0000);
+	udelay (10);
+	
+	// At this point, the original state of the enable register can be restored
+	setEnableReg (ectrl->client, enable);
+}
+
+
+static int ectrl_notify_sys (struct notifier_block *this, unsigned long code, void *unused) {
+	int retval;
+	switch ( code ) {
+		case SYS_DOWN:
+			retval = ectrl_SystemReboot (ectrl->client);
+			break;
+		case SYS_HALT:
+		case SYS_POWER_OFF:
+			retval = ectrl_SystemHalt (ectrl->client);
+			break;
+		default:
+			break;
+	}
+	return NOTIFY_DONE;
+}
+
+
+static struct notifier_block ectrl_notifier = {
+	.notifier_call = ectrl_notify_sys,
+};
+
+
+static int ectrl_parse_dt (struct econtroller *ectrl, int board_id) {
+
+	struct device dev = ectrl->client->dev;
+	struct device_node *np;
+
+	struct property *prop;
+	int length, num_event;
+	u32 *of_event_list, *event_list;
+	struct event_dev **events;
+
+	int idx, nre, i, idxs;
+	int ret, err;
+
+	int num_bootdev;
+	struct device_node *parent, *child;
+
+
+	np = of_node_get (dev.of_node);
+	if ( ! np )
+		return -EINVAL;
+
+	/* -----------------------------------
+	 * retrive the list of feasible events
+	 * ----------------------------------- */
+	prop = of_find_property (np, "events", &length);
+	if ( ! prop ) {
+		pr_err("%s: could not find property %s\n",
+				of_node_full_name(np), "events");
+		return -EINVAL;
+	}
+
+	num_event = length / sizeof(u32);
+
+	ECTRL_DBG ("Num. of event found: %d", num_event);
+
+	/*  list of event, as u32, retrived directly from device tree  */
+	of_event_list = kzalloc (sizeof (u32) * num_event , GFP_KERNEL);
+	if ( ! of_event_list ) {
+		err = -EINVAL;
+		goto err_alloc_of_event_list;
+	}
+
+	/*  list of event used by the driver  */
+	event_list = kzalloc (sizeof (u32) * num_event, GFP_KERNEL);
+	if ( ! event_list ) {
+		err = -EINVAL;
+		goto err_alloc_event_list;
+	}
+
+	ret = of_property_read_u32_array (np, "events", of_event_list, num_event);
+
+	nre = 0;
+	for ( i = 0 ; i < num_event ; i++ )  {
+
+		/*  switch from DTB data to event index  */
+		switch ( of_event_list[i] ) {
+			case ECTRL_EVNT_PWR_BTN:
+				event_list[i] = EVNT_PWR_BTN;
+				break;
+			case ECTRL_EVNT_RST_BTN:
+				event_list[i] = EVNT_RST_BTN;
+				break;
+			case ECTRL_EVNT_BATTERY:
+				event_list[i] = EVNT_BATTERY;
+				break;
+			case ECTRL_EVNT_LID:
+				event_list[i] = EVNT_LID;
+				break;
+			case ECTRL_EVNT_SLEEP:
+				event_list[i] = EVNT_SLEEP;
+				break;
+			case ECTRL_EVNT_WAKE:
+				event_list[i] = EVNT_WAKE;
+				break;
+			default:
+				/*  unrecognized event code  */
+				return -EINVAL;
+		}
+		
+		/*  count the effective event states used by the driver.
+		 *  Some event source requires two event (one for each edge
+		 *  of the signal.
+		 *  */
+		if ( of_event_list[i] & (ECTRL_EVNT_BATTERY | ECTRL_EVNT_LID) ) 
+			nre += 2;
+		if ( of_event_list[i] & (ECTRL_EVNT_PWR_BTN | ECTRL_EVNT_RST_BTN |
+					ECTRL_EVNT_SLEEP | ECTRL_EVNT_WAKE) )
+			nre++;
+
+	}
+
+	ectrl->nr_evn = board_nr_states[board_id]; 
+	ectrl->evn_state = (struct event_state **)kzalloc (sizeof (struct event_state *) * ectrl->nr_evn, GFP_KERNEL);
+	if (!ectrl->evn_state) {
+		err = -ENOMEM;
+		goto err_alloc_evn_state;
+	}
+      
+	events = (struct event_dev **)kzalloc (sizeof (struct event_dev *) * nre, GFP_KERNEL);
+	if (!events) {
+		err = -ENOMEM;
+		goto err_alloc_events;
+	}
+
+	for ( idx = 0, idxs = 0, i = 0 ; i < num_event ; i++ ) {
+
+		//  check if the event is available for the board
+		if ( board_reg_state_idx[board_id][event_list[i]] != -1 ) {
+			ectrl->evn_state[idxs] = &event_state_list[event_list[i]];
+			ectrl->evn_state[idxs]->reg_idx = board_reg_state_idx[board_id][event_list[i]];
+			idxs++;
+		}
+
+		switch ( event_list[i] ) {
+			case EVNT_PWR_BTN:
+				events[idx] = &global_event_list[PWR_BUTTON];
+				idx++;
+				break;
+			case EVNT_RST_BTN:
+				events[idx] = &global_event_list[RST_BUTTON];
+				idx++;
+				break;
+			case EVNT_SLEEP:
+				events[idx] = &global_event_list[SLEEP_SIGNAL];
+				idx++;
+				break;
+			case EVNT_BATTERY:
+				events[idx] = &global_event_list[BATLOW_HL_SIGNAL];
+				events[idx + 1] = &global_event_list[BATLOW_LH_SIGNAL];
+				idx += 2;
+				break;
+			case EVNT_LID:
+				events[idx] = &global_event_list[LID_HL_SIGNAL];
+				events[idx + 1] = &global_event_list[LID_LH_SIGNAL];
+				idx += 2;
+				break;
+			case EVNT_WAKE:
+				events[idx] = &global_event_list[WAKE_SIGNAL];
+				idx ++;
+				break;
+			default:
+				break;
+		}	
+	}
+
+	ectrl->events = events; 
+	ectrl->nr_evnt = nre;
+
+
+	parent = of_get_child_by_name(np, "boot_device");
+	if ( ! parent ) {
+		ECTRL_ERR ("boot_device node not found");
+		err = -EINVAL;
+		goto err_no_boot_device_node;
+	}
+		
+	num_bootdev = 0;
+	for_each_child_of_node (parent, child) 
+		if ( strcmp (child->name, "bootdev") == 0 )
+				num_bootdev++;
+	
+	if ( !num_bootdev ) {
+		/*  No boot device found  */
+		ECTRL_ERR ("No boot device found!");	
+		err = -EINVAL;
+		goto err_no_boot_device;
+	}
+
+	ECTRL_DBG ("Num of bootdev: %d", num_bootdev);
+	ectrl->nr_bootdev = num_bootdev;
+	ectrl->bootdev_list = kzalloc (sizeof (struct bootdev *) * ectrl->nr_bootdev, GFP_KERNEL);
+	if ( !ectrl->bootdev_list ) {
+		err = -ENOMEM;
+		goto err_alloc_bootdev_list;
+	}
+
+	i = 0;
+	for_each_child_of_node (parent, child) {
+		/*  check if the node is a boot device node info  */
+		if ( strcmp (child->name, "bootdev") == 0 ) {
+			of_property_read_u32 (child, "id", (u32 *)&ectrl->bootdev_list[i].id);
+			of_property_read_string (child, "label", &ectrl->bootdev_list[i].label);
+			i++;
+		}
+	
+	}
+	
+	ectrl->irq = irq_of_parse_and_map (np, 0);
+
+#if ECTRL_LOGGING
+	print_debug (ectrl);
+#endif
+
+	return 0;
+
+err_alloc_bootdev_list:
+err_no_boot_device:
+err_no_boot_device_node:
+	for ( i = 0 ; i < nre ; i++ )
+		kfree (events[i]);
+	kfree (events);
+err_alloc_events:
+	for ( i = 0 ; i < ectrl->nr_evn ; i++ )
+		kfree (ectrl->evn_state[i]);
+	kfree (ectrl->evn_state);
+err_alloc_evn_state:
+	kfree (event_list);
+err_alloc_event_list:
+	kfree (of_event_list);
+err_alloc_of_event_list:
+	kfree (prop);
+
+	return err;
+}
+
+
+static const struct i2c_device_id ectrl_idtable[] = {
+	{ "ectrl", 0 },
+	{ /*  sentinel  */ }
+};
+MODULE_DEVICE_TABLE(i2c, ectrl_idtable);
+
+
+static const struct of_device_id seco_ectrl_i2c_match[] = {
+	{ .compatible = "seco,ectrl" },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, seco_ectrl_of_match);
+
+
+static int ectrl_probe(struct i2c_client *client, const struct i2c_device_id *id) {
+
+	int err, ret, reg = 0, i;
+	int enable_reg, flag_reg, status_reg;
+	int bidx;
+	struct input_dev  *input;
+
+	const struct of_device_id *match = NULL;
+
+	if ( !i2c_check_functionality (client->adapter, 
+				I2C_FUNC_SMBUS_READ_WORD_DATA | I2C_FUNC_I2C) ) {
+		err = -EIO;
+		goto err_i2c_check;
+	}
+
+	ectrl = kzalloc (sizeof (struct econtroller), GFP_KERNEL);
+
+	if ( !ectrl ) {
+		err = -ENOMEM;
+		goto err_alloc_ectrl;
+	}
+
+	if ( client->dev.of_node ) {
+		match = of_match_device (of_match_ptr (seco_ectrl_i2c_match),
+				&client->dev);
+		if ( !match ) {
+			ECTRL_ERR ("No device match found");
+			err = -ENODEV;
+			goto err_no_match;
+		}
+	}
+
+	ectrl->client = client;
+
+#if ECTRL_LOGGING
+	/*  LOGGER INIT */
+	logger_list = kzalloc (sizeof (struct logger_entry), GFP_KERNEL);
+	if ( logger_list != NULL ) {
+		mutex_init (&logger_lock);
+		INIT_LIST_HEAD (&logger_list->list);
+	}
+	/*  -----  */
+#endif /* ECTRL_LOGGING */
+
+	/*  set communication timing */
+	last_jiffies_communication = jiffies;
+	mutex_init (&comm_lock);
+
+	ectrl->board_id = getBoardID(ectrl->client);
+
+	/*  retrive the current board id  */
+	switch (ectrl->board_id) {
+		case BOARD_928_ID:
+			bidx = BOARD_928;
+			break; 
+		case BOARD_962_ID:
+			bidx = BOARD_962;
+			break;
+		case BOARD_984_ID:
+			bidx = BOARD_984;
+			break;
+		case BOARD_B38_ID:
+			bidx = BOARD_B38;
+			break;
+		default:
+			bidx = -1;
+			break;
+	}
+
+	if (bidx == -1) {
+		//  unsupported board
+		ECTRL_ERR ("Unsupported board: %d", ectrl->board_id);	
+		err = -EINVAL;
+		goto err_inv_id;
+	}
+
+	ECTRL_INFO ("Detected board: %s", board_name[bidx]);	
+
+	ret = ectrl_parse_dt (ectrl, bidx);
+
+	if ( ret ) {
+		ECTRL_ERR ("error in parsing dt: %d", ret);
+		err = ret;
+		goto err_parsing_dt;
+	}
+
+	ectrl->wdt_event_list = wdt_evnt_list;
+	ectrl->nr_wdt_event = ARRAY_SIZE (wdt_evnt_list);
+
+	INIT_DELAYED_WORK (&ectrl->work, ectrl_work);
+	ectrl->poll_period  = ECTRL_POLL_PERIOD;
+	INIT_DELAYED_WORK (&ectrl->work_snooper_pwr_btn, ectr_work_pwr_btn_snooper);
+	ectrl->poll_period_snooper_pwr_btn = ECTRL_POLL_PERIOD_SNOOPER_PWR_BTN;
+
+	
+	/* input interface */
+
+	input = input_allocate_device();
+	if ( !input) {
+		err = -ENOMEM;
+		goto err_input;
+	}
+
+	ectrl->phys = kzalloc (sizeof (char) * 32, GFP_KERNEL);
+	snprintf(ectrl->phys, sizeof(char) * 32,
+			"%s/input%d", dev_name(&client->dev), 0);
+
+	input->name        = "seco_ectrl";
+	input->phys        = ectrl->phys;
+	input->id.bustype  = BUS_I2C;
+	input->dev.parent  = &client->dev;
+
+	for ( i = 0 ; i < ectrl->nr_evnt ; i++ ) {
+
+		ectrl->events[i]->input = input;
+
+		switch ( ectrl->events[i]->id ) {
+			case PWR_BUTTON:
+				input_set_capability (input, EV_KEY, KEY_F4);
+				break;
+			case SLEEP_SIGNAL:
+				input_set_capability (input, EV_KEY, BTN_ECTRL_SLEEP);
+				break;
+			case WAKE_SIGNAL:
+				input_set_capability (input, EV_KEY, BTN_ECTRL_WAKE);
+				break;
+			case BATLOW_HL_SIGNAL:
+				input_set_capability (input, EV_KEY, BTN_ECTRL_BATLOW_HL);
+				break;
+			case BATLOW_LH_SIGNAL:
+				input_set_capability (input, EV_KEY, BTN_ECTRL_BATLOW_LH);
+				break;
+			case LID_HL_SIGNAL:
+				input_set_capability (input, EV_KEY, BTN_ECTRL_LID_HL);
+				break;
+			case LID_LH_SIGNAL:
+				input_set_capability (input, EV_KEY, BTN_ECTRL_LID_LH);
+				break;
+			case RST_BUTTON:
+			case PWR_BTN_4SEC:
+				/*  no input for these signals since the embedded 
+				 *  controller will perform a brutal shotdown 
+				 *  when these event rise.
+				 */
+			default:
+				break;
+		}
+
+	}
+
+	err = input_register_device (input);
+	if ( err ) {
+		ECTRL_ERR ("No input assigned");
+		err = -EINVAL;
+		reg = i;
+		goto err_reg_input;
+	}
+
+	ectrl_add_proc_fs (ectrl);
+
+	/* detect and resolve the initial state */
+	ectrl_detect_state (ectrl, &enable_reg, &flag_reg, &status_reg);
+	ectrl_resolve_state (ectrl, enable_reg, flag_reg, status_reg);
+
+	/* mutex initialization */
+	mutex_init (&ectrl->fs_lock);
+	mutex_init (&ectrl->ioctl_lock);
+
+	/* irq acquisition */
+	if ( ectrl->irq == 0 ) {
+		ECTRL_ERR ("No IRQ assigned");
+		err = -EINVAL;
+		goto err_irq;
+	}
+	ret = request_irq (ectrl->irq, irq_interrupt_manager,
+				IRQF_SHARED | IRQF_TRIGGER_FALLING, "ectrl", &ectrl);
+
+	if ( ret ) {
+		ECTRL_ERR ("IRQ not acquired: error %d", ret);
+		err = -EIO;
+		goto err_free_irq;
+	}
+
+	ret = misc_register (&ectrl_device);
+	if ( ret ) {
+		ECTRL_ERR ("misc registration failed: %d", ret);
+		err = -EIO;
+		goto err_misc_register;
+	}
+
+	ret = register_reboot_notifier (&ectrl_notifier);
+	if ( ret != 0 ) {
+		pr_err("cannot register reboot notifier (err=%d)\n", ret);
+		goto err_notifier_register;
+	}
+
+	ECTRL_INFO (" probe done");
+
+	dev_set_drvdata (&client->dev, ectrl);
+
+	return 0;
+
+
+err_notifier_register:
+err_misc_register:
+	ectrl_free_irq (ectrl);
+err_free_irq:
+err_irq:
+	input_unregister_device (input);
+err_reg_input:
+	kfree (input);
+err_input:
+	for ( i = 0 ; i < ectrl->nr_evnt ; i++ )
+		kfree (ectrl->events[i]);
+	kfree (ectrl->events);
+	for ( i = 0 ; i < ectrl->nr_evn ; i++ )
+		kfree (ectrl->evn_state[i]);
+	kfree (ectrl->evn_state);
+err_parsing_dt:
+	kfree (match);
+err_inv_id:
+err_no_match:
+	kfree (ectrl);
+err_alloc_ectrl:
+err_i2c_check:
+
+	return err;
+}
+
+
+static int ectrl_remove(struct i2c_client *client) {
+	int i;
+	struct ectrl_platform_data *data;
+	data = i2c_get_clientdata(client);
+	misc_deregister (&ectrl_device);
+	ectrl_free_irq (ectrl);
+	ectrl_remove_proc_fs (ectrl);
+	unregister_reboot_notifier (&ectrl_notifier);
+	kfree (entry_list);
+
+	for ( i = 0 ; i < ectrl->nr_evnt ; i++ )
+		kfree (ectrl->events[i]);
+	kfree (ectrl->events);
+
+	for ( i = 0 ; i < ectrl->nr_evn ; i++ )
+		kfree (ectrl->evn_state[i]);
+	kfree (ectrl->evn_state);
+
+	kfree (ectrl);
+	kfree (data);
+	return 0;
+}
+
+
+void device_shutdown_ectrl(struct i2c_client *client) {
+}
+
+
+static struct i2c_driver ectrl_driver = {
+	.driver = {
+		.owner	         = THIS_MODULE,
+		.name	         = "ectrl",
+		.of_match_table  = of_match_ptr(seco_ectrl_i2c_match),
+	},
+	.id_table	= ectrl_idtable,
+	.probe		= ectrl_probe,
+	.remove		= ectrl_remove,
+	.shutdown   = device_shutdown_ectrl,
+};
+
+
+//module_i2c_driver(ectrl_driver);
+
+static int __init ectrl_init(void) {
+	return i2c_add_driver(&ectrl_driver);
+}
+
+
+static void __exit ectrl_exit(void) {
+	i2c_del_driver(&ectrl_driver);
+}
+
+
+module_init(ectrl_init);
+module_exit(ectrl_exit);
+
+
+MODULE_AUTHOR("Davide Cardillo, SECO srl");
+MODULE_DESCRIPTION("SECO system halt with Embedded Controller");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
diff --git a/include/dt-bindings/seco/ectrl_msp430.h b/include/dt-bindings/seco/ectrl_msp430.h
new file mode 100644
index 0000000000000000000000000000000000000000..38cc88d216cb1a35536b90fe4be19ed5bfa1e161
--- /dev/null
+++ b/include/dt-bindings/seco/ectrl_msp430.h
@@ -0,0 +1,33 @@
+/*
+ * (C) Copyright 2015 Seco srl
+ *
+ * Author: Davide Cardillo <davide.cardillo@seco.com>
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ *
+ * This header provides constants for the binding Seco Embedded controller
+ *
+ */
+
+#ifndef __DT_BINDINGS_SECO_ECTRL_H
+#define __DT_BINDINGS_SECO_ECTRL_H
+
+
+
+
+#define ECTRL_EVNT_PWR_BTN      0x01
+#define ECTRL_EVNT_RST_BTN      0x02
+#define ECTRL_EVNT_SLEEP        0x04
+#define ECTRL_EVNT_BATTERY      0x08
+#define ECTRL_EVNT_LID          0x10
+#define ECTRL_EVNT_WAKE         0x20
+
+
+
+#define ECTRL_BOOTDEV_USDHC4    0x00
+#define ECTRL_BOOTDEV_USDHC1    0x01
+#define ECTRL_BOOTDEV_EMMC      0x02
+#define ECTRL_BOOTDEV_SPI       0x03
+
+
+#endif   /*  __DT_BINDINGS_SECO_ECTRL_H  */
diff --git a/include/linux/ectrl_msp430.h b/include/linux/ectrl_msp430.h
new file mode 100644
index 0000000000000000000000000000000000000000..35360027ff82f29800c486a522e46e157cd57a11
--- /dev/null
+++ b/include/linux/ectrl_msp430.h
@@ -0,0 +1,50 @@
+#ifndef __LINUX_I2C_ECTRL_H
+#define __LINUX_I2C_ECTRL_H
+
+#include <linux/interrupt.h>
+#include <linux/workqueue.h>
+#include <linux/ioctl.h>
+#include <linux/miscdevice.h>
+
+/* linux/i2c/ectrl_msp430.h */
+
+
+enum wdt_event {
+	WDT_EVNT_WDOUT          = 0,
+	WDT_EVNT_RESET          = 1,
+	WDT_EVNT_PWRBTN1SEC     = 2,
+	WDT_EVNT_PWRBTN4SEC     = 3,
+	WDT_EVNT_BOOT_RECOVERY  = 4,
+};
+
+
+enum ECTRL_EVENTS {
+	EVNT_PWR_BTN, EVNT_RST_BTN, EVNT_SLEEP,
+	EVNT_BATTERY, EVNT_LID, EVNT_WAKE
+};
+
+
+struct data_list {
+	u16 data;
+	struct list_head list;
+};
+
+enum {
+	STOP_OP = (unsigned short int)0, 	// stop all operations
+	R_OP    = (unsigned short int)1,	// read register operation
+	W_OP    = (unsigned short int)2,	// write register operation
+	RVE_OP  = (unsigned short int)3,	// read vector's element operation
+	WVE_OP  = (unsigned short int)4,	// write vector's element operation
+};
+
+struct ectrl_reg {
+	u16 addr;
+	u16 data;
+};
+
+struct ectrl_reg_rw {
+	unsigned short int op;
+	struct ectrl_reg reg;
+};
+
+#endif           /*  __LINUX_I2C_ECTRL_H  */
diff --git a/include/linux/ectrl_msp430_io.h b/include/linux/ectrl_msp430_io.h
new file mode 100644
index 0000000000000000000000000000000000000000..3c029831f1a78b1bc9a5ecdd6fd57df1f6d805d0
--- /dev/null
+++ b/include/linux/ectrl_msp430_io.h
@@ -0,0 +1,129 @@
+
+#ifndef __LINUX_I2C_ECTRL_IO_H
+#define __LINUX_I2C_ECTRL_IO_H
+
+
+#include <linux/ioctl.h>
+#include "ectrl_msp430.h"
+
+
+enum ECTRL_EVENT_ID;
+struct ectrl_ev_state;
+
+enum ECTRL_POWER_STATE;
+
+enum ECTRL_BOOTDEV_ID;
+struct ectrl_boot_device;
+
+enum wdt_event;
+struct wdt_event_data;
+struct ectrl_wdt;
+
+
+#define ECTRL_IOCTL_REG_READ	          _IOWR('o', 1, struct ectrl_reg)
+#define ECTRL_IOCTL_REG_WRITE	          _IOR('o', 2, struct ectrl_reg)
+/*  EVENT  */
+#define ECTRL_EV_STATE_GET                _IOWR('o', 3, struct ectrl_ev_state *)
+#define ECTRL_EV_STATE_SET                _IOR('o', 4, struct ectrl_ev_state *)
+/*  POWER MANAGEMENT  */
+#define ECTRL_PWR_STATE_GET               _IOW('o', 5, enum ECTRL_POWER_STATE *)
+#define ECTRL_PWR_STATE_SET               _IOR('o', 6, enum ECTRL_POWER_STATE *)
+#define ECTRL_PWR_BTN_4SEC_STATE_GET      _IOW('o', 7, struct ectrl_ev_state *)
+#define ECTRL_PWR_BTN_4SEC_STATE_SET      _IOR('o', 8, struct ectrl_ev_state *)
+/*  BOOT MANAGEMENT  */
+#define ECTRL_BOOT_NUM_DEV_GET            _IOW('o', 9, int *)
+#define ECTRL_BOOT_DEV_LIST_GET           _IOW('o', 10, struct ectrl_boot_device *)
+#define ECTRL_BOOT_DEV_1_GET              _IOW('o', 11, struct ectrl_boot_device *)
+#define ECTRL_BOOT_DEV_2_GET              _IOW('o', 12, struct ectrl_boot_device *)
+#define ECTRL_BOOT_DEV_3_GET              _IOW('o', 13, struct ectrl_boot_device *)
+#define ECTRL_BOOT_DEV_RECOVERY_GET       _IOW('o', 14, struct ectrl_boot_device *)
+#define ECTRL_BOOT_DEV_1_SET              _IOR('o', 15, enum ECTRL_BOOTDEV_ID *)
+#define ECTRL_BOOT_DEV_2_SET              _IOR('o', 16, enum ECTRL_BOOTDEV_ID *)
+#define ECTRL_BOOT_DEV_3_SET              _IOR('o', 17, enum ECTRL_BOOTDEV_ID *)
+#define ECTRL_BOOT_DEV_RECOVERY_SET       _IOR('o', 18, enum ECTRL_BOOTDEV_ID *)
+/*  WATCHDOG  */
+#define ECTRL_WDT_NUM_EVENT_GET           _IOW('o', 19, int *)
+#define ECTRL_WDT_EVENT_LIST_GET          _IOW('o', 20, struct wdt_event_data *)
+#define ECTRL_WDT_GET                     _IOW('o', 21, struct ectrl_wdt *)
+#define ECTRL_WDT_SET                     _IOR('o', 21, struct ectrl_wdt *)
+#define ECTRL_WDT_REFRESH                 _IO('o', 22)
+#define ECTRL_WDT_RESTORE                 _IO('o', 23)
+
+
+
+
+/*  EVENT  */
+
+enum ECTRL_EVENT_ID {
+	PWR_BUTTON        =  0,
+	RST_BUTTON        =  1,
+	SLEEP_SIGNAL      =  2,
+	BATLOW_HL_SIGNAL  =  3,	// when BATLOW becomes HIGH - battery charge low
+	BATLOW_LH_SIGNAL  =  4,	// when BATLOW becomes LOW - battery full
+	LID_HL_SIGNAL     =  5,	// when LID becomes HIGH
+	LID_LH_SIGNAL     =  6,	// when LID becomes LOW
+	WAKE_SIGNAL       =  7,
+	PWR_BTN_4SEC      =  8,
+};
+
+
+struct ectrl_ev_state {
+	enum ECTRL_EVENT_ID  id;
+	int                  v_enable;
+	int                  f_enable;
+};
+
+
+/*  POWER MANAGEMENT  */
+
+enum ECTRL_POWER_STATE {
+	PWR_ALWAYS_OFF,
+	PWR_ALWAYS_ON,
+};
+
+
+/*  BOOT MANAGEMENT  */
+
+enum ECTRL_BOOTDEV_ID {
+	BOOT_USDHC4  = (u8)0,
+	BOOT_USBHC1  = (u8)1,
+	BOOT_EMMC    = (u8)2,
+	BOOT_SPI     = (u8)3,
+};
+
+
+#define BOOTDEV_NAME_MAX_LEN  30
+struct ectrl_boot_device {
+	enum ECTRL_BOOTDEV_ID   id;
+	char                    label[BOOTDEV_NAME_MAX_LEN];
+};
+
+
+/*  WATCHDOG  */
+
+#define WDT_NAME_MAX_LEN  30
+struct wdt_event_data {
+	enum wdt_event id;
+	char           label[WDT_NAME_MAX_LEN];
+
+};
+
+
+struct ectrl_wdt {
+	/*  volatile settings  */
+	int            v_enable;
+	enum wdt_event v_event;
+	u16            v_delay_sec;
+	u16            v_timeout_sec;
+	/*  permanent settings  */
+	int            f_enable;
+	enum wdt_event f_event;
+	u16            f_delay_sec;
+	u16            f_timeout_sec;
+	/*  run time state  */
+	u16            timer_delay;
+	u16            timer_wd;
+};
+
+
+#endif             /*  __LINUX_I2C_ECTRL_IO_H  */
diff --git a/include/uapi/linux/input-event-codes.h b/include/uapi/linux/input-event-codes.h
index 225ec87d4f2283c7e2aacba55fbf3d405753b570..326960a9947734234bec91fd7b8d04ef932c1cc1 100644
--- a/include/uapi/linux/input-event-codes.h
+++ b/include/uapi/linux/input-event-codes.h
@@ -777,6 +777,15 @@
 #define BTN_TRIGGER_HAPPY39		0x2e6
 #define BTN_TRIGGER_HAPPY40		0x2e7
 
+
+#define BTN_ECTRL_PWR                   0x152
+#define BTN_ECTRL_BATLOW_HL             0x153
+#define BTN_ECTRL_BATLOW_LH             0x154
+#define BTN_ECTRL_LID_HL                0x155
+#define BTN_ECTRL_LID_LH                0x156
+#define BTN_ECTRL_SLEEP                 0x157
+#define BTN_ECTRL_WAKE                  0x158
+
 /* We avoid low common keys in module aliases so they don't get huge. */
 #define KEY_MIN_INTERESTING	KEY_MUTE
 #define KEY_MAX			0x2ff