Warning: large number of unneeded non-static and static defines
authorTom Knot <tomasknot@gmail.com>
Mon, 26 Feb 2018 21:41:10 +0000 (22:41 +0100)
committerTom Knot <tomasknot@gmail.com>
Mon, 26 Feb 2018 21:41:10 +0000 (22:41 +0100)
- Refactored the module into logical subunits

16 files changed:
modules/neuron_spi/Makefile
modules/neuron_spi/src/unipi_common.h [new file with mode: 0644]
modules/neuron_spi/src/unipi_gpio.c
modules/neuron_spi/src/unipi_gpio.h
modules/neuron_spi/src/unipi_iio.c
modules/neuron_spi/src/unipi_iio.h
modules/neuron_spi/src/unipi_misc.c [new file with mode: 0644]
modules/neuron_spi/src/unipi_misc.h [new file with mode: 0644]
modules/neuron_spi/src/unipi_platform.c
modules/neuron_spi/src/unipi_platform.h
modules/neuron_spi/src/unipi_spi.c
modules/neuron_spi/src/unipi_spi.h
modules/neuron_spi/src/unipi_sysfs.c
modules/neuron_spi/src/unipi_sysfs.h
modules/neuron_spi/src/unipi_uart.c
modules/neuron_spi/src/unipi_uart.h

index 647aa5528b24e927d1e274818379e3713e0ec299..321946c1562b8f93756a3d694c61cdc25d7a2a64 100644 (file)
@@ -14,18 +14,25 @@ C_SRC_FILES += unipi_iio.c
 C_SRC_FILES += unipi_gpio.c
 C_SRC_FILES += unipi_uart.c
 C_SRC_FILES += unipi_sysfs.c
+C_SRC_FILES += unipi_misc.c
+C_SRC_FILES += unipi_platform.c
 
 H_SRC_FILES = unipi_spi.h
 H_SRC_FILES += unipi_iio.h
 H_SRC_FILES += unipi_gpio.h
 H_SRC_FILES += unipi_uart.h
 H_SRC_FILES += unipi_sysfs.h
+H_SRC_FILES += unipi_misc.h
+H_SRC_FILES += unipi_platform.h
+H_SRC_FILES += unipi_common.h
 
 OBJ_FILES = src/unipi_spi.o
 OBJ_FILES += src/unipi_iio.o
 OBJ_FILES += src/unipi_gpio.o
 OBJ_FILES += src/unipi_uart.o
 OBJ_FILES += src/unipi_sysfs.o
+OBJ_FILES += src/unipi_misc.o
+OBJ_FILES += src/unipi_platform.o
 
 KERNEL_MODULE_NAME = unipi
 obj-m += ${KERNEL_MODULE_NAME}.o
diff --git a/modules/neuron_spi/src/unipi_common.h b/modules/neuron_spi/src/unipi_common.h
new file mode 100644 (file)
index 0000000..f8df483
--- /dev/null
@@ -0,0 +1,283 @@
+/*
+ * unipi_common.h
+ *
+ *  Created on: 26 Feb 2018
+ *      Author: Tom Knot <knot@faster.cz>
+ */
+
+#ifndef MODULES_NEURON_SPI_SRC_UNIPI_COMMON_H_
+#define MODULES_NEURON_SPI_SRC_UNIPI_COMMON_H_
+
+#include <linux/bitops.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/gpio.h>
+#include <linux/gpio/driver.h>
+#include <linux/i2c.h>
+#include <linux/iio/iio.h>
+#include <uapi/linux/iio/types.h>
+#include <linux/iio/sysfs.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/regmap.h>
+#include <linux/serial_core.h>
+#include <linux/serial.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/spi/spi.h>
+#include <linux/leds.h>
+#include <linux/uaccess.h>
+#include <asm/termbits.h>
+#include <asm/gpio.h>
+
+/***************
+ * Definitions *
+ ***************/
+#define NEURONSPI_SCHED_REQUIRED 0 // Older kernels do not require sched/types to be specifically imported
+
+#define NEURONSPI_MAJOR_VERSIONSTRING "Development Beta Version 0.02:12:02:2018"
+
+#define NEURONSPI_MAX_DEVS                             3
+#define NEURONSPI_MAX_UART                             128
+#define NEURONSPI_BUFFER_MAX                   1152
+#define NEURONSPI_HEADER_LENGTH                10
+#define NEURONSPI_FIRST_MESSAGE_LENGTH 6
+#define NEURONSPI_EDGE_DELAY                   10
+#define NEURONSPI_B_PER_WORD                   8
+#define NEURONSPI_DEFAULT_FREQ                 600000
+#define NEURONSPI_COMMON_FREQ                  12000000
+#define NEURONSPI_SLOWER_FREQ                  8000000
+#define NEURONSPI_MAX_TX                               62
+#define NEURONSPI_MAX_BAUD                             115200
+#define NEURONSPI_FIFO_SIZE                            256
+#define NEURONSPI_DETAILED_DEBUG               0
+#define NEURONSPI_LAST_TRANSFER_DELAY  40
+
+
+#define NEURON_DEVICE_NAME                             "neuronspi"
+#define NEURON_DEVICE_CLASS                    "modbus_spi"
+#define NEURON_DRIVER_NAME                             "NEURONSPI"
+#define PORT_NEURONSPI                                 184
+
+#define STRICT_RESERVING
+#define NEURONSPI_ALWAYS_EXPORT
+
+#define NEURONSPI_GET_COIL_READ_PHASE2_BYTE_LENGTH(X)  ((((X) + 15) >> 4) << 1)
+
+#define NEURONSPI_NO_INTERRUPT_MODELS_LEN                              3
+static const uint16_t NEURONSPI_NO_INTERRUPT_MODELS[NEURONSPI_NO_INTERRUPT_MODELS_LEN] = {
+               0xb10, 0xc10, 0xf10
+};
+
+enum neuron_str_attribute_type {
+               NEURON_SATTR_MODEL,
+               NEURON_SATTR_EEPROM,
+               NEURON_SATTR_BOARD_NAME,
+               NEURON_SATTR_GPIO_GROUP_NAME
+};
+
+enum neuron_num_attribute_type {
+               NEURON_NATTR_BOARDCOUNT,
+               NEURON_NATTR_MODE,
+               NEURON_NATTR_CURRENT_VALUE
+};
+
+struct neuronspi_devtype
+{
+       u8      name[10];
+       int32_t nr_gpio;
+       int32_t nr_uart;
+};
+
+struct neuronspi_port
+{
+       struct uart_port                        port;
+       u8                                                      line;
+       struct kthread_work                     tx_work;
+       struct kthread_work                     rx_work;
+       struct kthread_work                     irq_work;
+       u32                                                     flags;
+       u8                                                      ier_clear;
+       u8                                                      buf[NEURONSPI_FIFO_SIZE];
+       struct neuronspi_uart_data      *parent;
+       u8                                                      dev_index;
+       u8                                                      dev_port;
+       u8                                                      parmrk_enabled;
+       u64                                                     parmrk_frame_delay;
+};
+
+struct neuronspi_uart_data
+{
+       const struct neuronspi_devtype  *devtype;
+       struct kthread_worker                   kworker;
+       struct task_struct                              *kworker_task;
+       struct neuronspi_port                   *p;
+       u8                                                              p_count;
+};
+
+
+// Instantiated once
+struct neuronspi_char_driver
+{
+       int32_t major_number;
+       u8 *message;
+       u16 message_size;
+       u32 open_counter;
+       struct class* driver_class;
+       struct device* dev;
+};
+
+
+// Instantiated once per SPI device
+struct neuronspi_driver_data
+{
+       struct spi_driver *spi_driver;
+       struct neuronspi_char_driver *char_driver;
+       struct uart_driver *serial_driver;
+       struct neuronspi_uart_data *uart_data;
+       struct neuronspi_led_driver *led_driver;
+       struct neuronspi_di_driver **di_driver;
+       struct neuronspi_do_driver **do_driver;
+       struct neuronspi_ro_driver **ro_driver;
+       struct platform_device *board_device;
+       struct iio_dev *stm_ai_driver;
+       struct iio_dev *stm_ao_driver;
+       struct iio_dev **sec_ai_driver;
+       struct iio_dev **sec_ao_driver;
+       struct kthread_worker primary_worker;
+       struct task_struct *primary_worker_task;
+       struct regmap *reg_map;
+       struct task_struct *poll_thread;
+       struct mutex device_lock;
+       struct neuronspi_board_features *features;
+       struct neuronspi_board_regstart_table *regstart_table;
+       struct spinlock sysfs_regmap_lock;
+       char platform_name[sizeof("io_group0")];
+       u8 *send_buf;
+       u8 *recv_buf;
+       u8 *first_probe_reply;
+       u8 *second_probe_reply;
+       u8 reserved_device;
+       u8 uart_count;
+       u8 uart_read;
+       u8 *uart_buf;
+       u8 slower_model;
+       u8 no_irq;
+       u8 lower_board_id;
+       u8 upper_board_id;
+       u8 combination_id;
+       int32_t neuron_index;
+       uint16_t sysfs_regmap_target;
+       uint16_t sysfs_counter_target;
+       uint32_t ideal_frequency;
+};
+
+struct neuronspi_di_driver {
+       struct spi_device* spi;
+       struct gpio_chip gpio_c;
+       struct platform_device *plat_dev;
+       u8 di_index;
+       char name[sizeof("di_0_00")];
+};
+
+struct neuronspi_do_driver
+{
+       struct spi_device* spi;
+       struct gpio_chip gpio_c;
+       struct platform_device *plat_dev;
+       u8 do_index;
+       char name[sizeof("do_0_00")];
+};
+
+struct neuronspi_ro_driver
+{
+       struct spi_device* spi;
+       struct gpio_chip gpio_c;
+       struct platform_device *plat_dev;
+       u8 ro_index;
+       char name[sizeof("ro_0_00")];
+};
+
+struct neuronspi_sec_ai_driver
+{
+       struct iio *devices;
+       u16 dev_count;
+};
+
+struct neuronspi_sec_ao_driver
+{
+       struct iio *devices;
+       u16 dev_count;
+};
+
+struct neuronspi_stm_ai_data
+{
+       u32 mode;
+       struct spi_device *parent;
+};
+
+struct neuronspi_stm_ao_data
+{
+       u32 mode;
+       struct spi_device *parent;
+};
+
+struct neuronspi_sec_ai_data
+{
+       u32 index;
+       u32 mode;
+       struct spi_device *parent;
+};
+
+struct neuronspi_sec_ao_data
+{
+       u32 index;
+       u32 mode;
+       struct spi_device *parent;
+};
+
+// Instantiated once per LED
+struct neuronspi_led_driver
+{
+       struct led_classdev     ldev;
+       struct spi_device       *spi;
+       struct kthread_work     led_work;
+       int                                     id;
+       int                                     brightness;
+       char                            name[sizeof("neuron:green:uled-x1")];
+       spinlock_t                      lock;
+};
+
+static struct mutex neuronspi_master_mutex;
+
+struct neuronspi_file_data
+{
+       struct spi_device** spi_device;
+       struct mutex            lock;
+       u8                                      *send_buf;
+       u8                                      *recv_buf;
+       uint32_t                        message_len;
+};
+
+struct neuronspi_direct_acc
+{
+       void __iomem            *vaddr;
+       u32                                     size;
+};
+
+static struct neuronspi_char_driver neuronspi_cdrv =
+{
+       .dev = NULL
+};
+
+static struct spinlock* neuronspi_spi_w_spinlock;
+static u8 neuronspi_spi_w_flag = 1;
+static u8 neuronspi_probe_count = 0;
+static int neuronspi_model_id = -1;
+static spinlock_t neuronspi_probe_spinlock;
+static struct spi_device* neuronspi_s_dev[NEURONSPI_MAX_DEVS];
+static struct task_struct *neuronspi_invalidate_thread;
+
+#endif /* MODULES_NEURON_SPI_SRC_UNIPI_COMMON_H_ */
index 9037c4d3fb29316d3a4b6adc39bc200bfb15de97..9716a78345decdc0aa27262b01bc918c91733937 100644 (file)
  *
  */
 
+#include "unipi_gpio.h"
+#include "unipi_spi.h"
+
+int neuronspi_gpio_di_direction_input(struct gpio_chip *chip, unsigned offset) {
+       return 0;
+}
+int neuronspi_gpio_di_direction_output(struct gpio_chip *chip, unsigned offset, int value) {
+       return -EINVAL;
+}
+int    neuronspi_gpio_di_get(struct gpio_chip *chip, unsigned offset) {
+       struct neuronspi_di_driver *n_di = gpiochip_get_data(chip);
+       struct spi_device *spi = n_di->spi;
+       return neuronspi_spi_gpio_di_get(spi, n_di->di_index);
+}
+
+int neuronspi_gpio_do_direction_output(struct gpio_chip *chip, unsigned offset, int value) {
+       return 0;
+}
+void neuronspi_gpio_do_set(struct gpio_chip *chip, unsigned offset, int value) {
+       struct neuronspi_do_driver *n_do = gpiochip_get_data(chip);
+       struct spi_device *spi = n_do->spi;
+       neuronspi_spi_gpio_do_set(spi, n_do->do_index, value);
+}
+
+int neuronspi_gpio_ro_direction_output(struct gpio_chip *chip, unsigned offset, int value) {
+       return 0;
+}
+void neuronspi_gpio_ro_set(struct gpio_chip *chip, unsigned offset, int value) {
+       struct neuronspi_ro_driver *n_ro = gpiochip_get_data(chip);
+       struct spi_device *spi = n_ro->spi;
+       neuronspi_spi_gpio_ro_set(spi, n_ro->ro_index, value);
+}
 
index 2c124f7a579fb1132f557e005a515914cd4bdfdb..471f07eb795ba3840f74951fba42a872a68174d5 100644 (file)
 #ifndef MODULES_NEURON_SPI_SRC_UNIPI_GPIO_H_
 #define MODULES_NEURON_SPI_SRC_UNIPI_GPIO_H_
 
+#include <linux/bitops.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/gpio.h>
+#include <linux/gpio/driver.h>
+#include <linux/i2c.h>
+#include <linux/iio/iio.h>
+#include <uapi/linux/iio/types.h>
+#include <linux/iio/sysfs.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/regmap.h>
+#include <linux/serial_core.h>
+#include <linux/serial.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/spi/spi.h>
+#include <linux/leds.h>
+#include <linux/uaccess.h>
+#include <asm/termbits.h>
+#include <asm/gpio.h>
 
+#include "unipi_common.h"
+
+int neuronspi_gpio_di_direction_input(struct gpio_chip *chip, unsigned offset);
+int neuronspi_gpio_di_direction_output(struct gpio_chip *chip, unsigned offset, int value);
+int    neuronspi_gpio_di_get(struct gpio_chip *chip, unsigned offset);
+int neuronspi_gpio_do_direction_input(struct gpio_chip *chip, unsigned offset);
+int neuronspi_gpio_do_direction_output(struct gpio_chip *chip, unsigned offset, int value);
+void neuronspi_gpio_do_set(struct gpio_chip *chip, unsigned offset, int value);
+int neuronspi_gpio_ro_direction_input(struct gpio_chip *chip, unsigned offset);
+int neuronspi_gpio_ro_direction_output(struct gpio_chip *chip, unsigned offset, int value);
+void neuronspi_gpio_ro_set(struct gpio_chip *chip, unsigned offset, int value);
 
 #endif /* MODULES_NEURON_SPI_SRC_UNIPI_GPIO_H_ */
index b43a7f5ea0e459e3b0d40bb1b7fd1c41bd5ed33d..340594d3f97079bc1d4836e55b16600e3ed7c370 100644 (file)
  * (at your option) any later version.
  *
  */
+
+#include "unipi_iio.h"
+#include "unipi_spi.h"
+
+
+int neuronspi_iio_stm_ai_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *ch, int *val, int *val2, long mask) {
+       struct neuronspi_stm_ai_data *ai_data = iio_priv(indio_dev);
+       struct spi_device *spi = ai_data->parent;
+       struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi);
+       regmap_read(n_spi->reg_map, n_spi->regstart_table->stm_ai_mode_reg, &ai_data->mode);
+       switch(ai_data->mode) {
+       case 0: {
+               if (ch->type == IIO_VOLTAGE) {
+                       neuronspi_spi_iio_stm_ai_read_voltage(indio_dev, ch, val, val2, mask);
+                       return IIO_VAL_INT;
+               } else {
+                       return -EINVAL;
+               }
+               break;
+       }
+       case 1: {
+               if (ch->type == IIO_CURRENT) {
+                       neuronspi_spi_iio_stm_ai_read_current(indio_dev, ch, val, val2, mask);
+                       return IIO_VAL_INT;
+               } else {
+                       return -EINVAL;
+               }
+               break;
+       }
+       default: {
+               return -EINVAL;
+               break;
+       }
+       }
+}
+
+int neuronspi_iio_stm_ao_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *ch, int *val, int *val2, long mask)
+{
+       struct neuronspi_stm_ao_data *ao_data = iio_priv(indio_dev);
+       struct spi_device *spi = ao_data->parent;
+       struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi);
+       regmap_read(n_spi->reg_map, n_spi->regstart_table->stm_ao_mode_reg, &ao_data->mode);
+       switch(ao_data->mode) {
+       case 3: {
+               if (ch->type == IIO_RESISTANCE) {
+                       neuronspi_spi_iio_stm_ao_read_resistance(indio_dev, ch, val, val2, mask);
+                       return IIO_VAL_INT;
+               } else {
+                       return -EINVAL;
+               }
+               break;
+       }
+       default: {
+               return -EINVAL;
+               break;
+       }
+       }
+}
+
+int neuronspi_iio_stm_ao_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *ch, int val, int val2, long mask)
+{
+       struct neuronspi_stm_ao_data *ao_data = iio_priv(indio_dev);
+       struct spi_device *spi = ao_data->parent;
+       struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi);
+       regmap_read(n_spi->reg_map, n_spi->regstart_table->stm_ao_mode_reg, &ao_data->mode);
+       switch(ao_data->mode) {
+       case 0: {
+               if (ch->type == IIO_VOLTAGE) {
+                       neuronspi_spi_iio_stm_ao_set_voltage(indio_dev, ch, val, val2, mask);
+                       return 0;
+               } else {
+                       return -EINVAL;
+               }
+               break;
+       }
+       case 1: {
+               if (ch->type == IIO_CURRENT) {
+                       neuronspi_spi_iio_stm_ao_set_current(indio_dev, ch, val, val2, mask);
+                       return 0;
+               } else {
+                       return -EINVAL;
+               }
+               break;
+       }
+       default: {
+               return -EINVAL;
+               break;
+       }
+       }
+}
+
+int neuronspi_iio_sec_ai_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *ch, int *val, int *val2, long mask)
+{
+       struct neuronspi_sec_ai_data *ai_data = iio_priv(indio_dev);
+       struct spi_device *spi = ai_data->parent;
+       struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi);
+       regmap_read(n_spi->reg_map, n_spi->regstart_table->sec_ai_mode_reg, &ai_data->mode);
+       switch(ai_data->mode) {
+       case 0: {
+               return -EINVAL;
+               break;
+       }
+       case 1: {
+               if (ch->type == IIO_VOLTAGE) {
+                       neuronspi_spi_iio_sec_ai_read_voltage(indio_dev, ch, val, val2, mask);
+                       return IIO_VAL_FRACTIONAL;
+               } else {
+                       return -EINVAL;
+               }
+               break;
+       }
+       case 2: {
+               if (ch->type == IIO_VOLTAGE) {
+                       neuronspi_spi_iio_sec_ai_read_voltage(indio_dev, ch, val, val2, mask);
+                       return IIO_VAL_FRACTIONAL;
+               } else {
+                       return -EINVAL;
+               }
+               break;
+       }
+       case 3: {
+               if (ch->type == IIO_CURRENT) {
+                       neuronspi_spi_iio_sec_ai_read_current(indio_dev, ch, val, val2, mask);
+                       return IIO_VAL_FRACTIONAL;
+               } else {
+                       return -EINVAL;
+               }
+               break;
+       }
+       case 4: {
+               if (ch->type == IIO_RESISTANCE) {
+                       neuronspi_spi_iio_sec_ai_read_resistance(indio_dev, ch, val, val2, mask);
+                       return IIO_VAL_FRACTIONAL;
+               } else {
+                       return -EINVAL;
+               }
+               break;
+       }
+       case 5: {
+               if (ch->type == IIO_RESISTANCE) {
+                       neuronspi_spi_iio_sec_ai_read_resistance(indio_dev, ch, val, val2, mask);
+                       return IIO_VAL_FRACTIONAL;
+               } else {
+                       return -EINVAL;
+               }
+               break;
+       }
+       default: {
+               return -EINVAL;
+               break;
+       }
+       }
+}
+
+int neuronspi_iio_sec_ao_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *ch, int val, int val2, long mask)
+{
+       if (ch->type == IIO_VOLTAGE) {
+               neuronspi_spi_iio_stm_ao_set_voltage(indio_dev, ch, val, val2, mask);
+               return 0;
+       } else {
+               return -EINVAL;
+       }
+}
index e1d9ba228a109dfbb9465715ad4a47c5f5e11200..bd700ac9ddec43d56d7b7cb6823e11b7472ebf36 100644 (file)
 #ifndef MODULES_NEURON_SPI_SRC_UNIPI_IIO_H_
 #define MODULES_NEURON_SPI_SRC_UNIPI_IIO_H_
 
+#include <linux/bitops.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/gpio.h>
+#include <linux/gpio/driver.h>
+#include <linux/i2c.h>
+#include <linux/iio/iio.h>
+#include <uapi/linux/iio/types.h>
+#include <linux/iio/sysfs.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/regmap.h>
+#include <linux/serial_core.h>
+#include <linux/serial.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/spi/spi.h>
+#include <linux/leds.h>
+#include <linux/uaccess.h>
+#include <asm/termbits.h>
+#include <asm/gpio.h>
 
+#include "unipi_common.h"
 
-
+int neuronspi_iio_stm_ai_read_raw(struct iio_dev *iio_dev, struct iio_chan_spec const *ch, int *val, int *val2, long mask);
+int neuronspi_iio_stm_ao_read_raw(struct iio_dev *iio_dev, struct iio_chan_spec const *ch, int *val, int *val2, long mask);
+int neuronspi_iio_stm_ao_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int val, int val2, long mask);
+int neuronspi_iio_sec_ai_read_raw(struct iio_dev *iio_dev, struct iio_chan_spec const *ch, int *val, int *val2, long mask);
+int neuronspi_iio_sec_ao_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int val, int val2, long mask);
 
 #endif /* MODULES_NEURON_SPI_SRC_UNIPI_IIO_H_ */
diff --git a/modules/neuron_spi/src/unipi_misc.c b/modules/neuron_spi/src/unipi_misc.c
new file mode 100644 (file)
index 0000000..26a96e9
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * unipi_misc.c
+ *
+ *  Created on: 26 Feb 2018
+ *      Author: Tom Knot <knot@faster.cz>
+ */
+
+#include "unipi_misc.h"
+#include "unipi_spi.h"
+
+void neuronspi_led_proc(struct kthread_work *ws)
+{
+       struct neuronspi_led_driver *led = to_led_driver(ws, led_work);
+       printk("NEURONSPI: BRIGHT id:%d\n", led->id);
+       neuronspi_spi_led_set_brightness(led->spi, led->brightness, led->id);
+}
+
+void neuronspi_led_set_brightness(struct led_classdev *ldev, enum led_brightness brightness)
+{
+       struct neuronspi_led_driver *led = container_of(ldev, struct neuronspi_led_driver, ldev);
+       struct neuronspi_driver_data *n_spi = spi_get_drvdata(led->spi);
+       spin_lock(&led->lock);
+       led->brightness = brightness;
+       kthread_queue_work(&n_spi->primary_worker, &led->led_work);
+       spin_unlock(&led->lock);
+}
diff --git a/modules/neuron_spi/src/unipi_misc.h b/modules/neuron_spi/src/unipi_misc.h
new file mode 100644 (file)
index 0000000..9551b4f
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * unipi_misc.h
+ *
+ *  Created on: 26 Feb 2018
+ *      Author: Tom Knot <knot@faster.cz>
+ */
+
+#ifndef MODULES_NEURON_SPI_SRC_UNIPI_MISC_H_
+#define MODULES_NEURON_SPI_SRC_UNIPI_MISC_H_
+
+#include <linux/bitops.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/gpio.h>
+#include <linux/gpio/driver.h>
+#include <linux/i2c.h>
+#include <linux/iio/iio.h>
+#include <uapi/linux/iio/types.h>
+#include <linux/iio/sysfs.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/regmap.h>
+#include <linux/serial_core.h>
+#include <linux/serial.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/spi/spi.h>
+#include <linux/leds.h>
+#include <linux/uaccess.h>
+#include <asm/termbits.h>
+#include <asm/gpio.h>
+
+#include "unipi_common.h"
+
+
+void neuronspi_led_proc(struct kthread_work *ws);
+void neuronspi_led_set_brightness(struct led_classdev *ldev, enum led_brightness brightness);
+
+#endif /* MODULES_NEURON_SPI_SRC_UNIPI_MISC_H_ */
index 1607152e7c3572af920df1d35cfac62e1129f1c8..c2b0ec8300e3b26aef31d607a461bda00de8b2e4 100644 (file)
@@ -5,4 +5,320 @@
  *      Author: Tom Knot <knot@faster.cz>
  */
 
+#include "unipi_platform.h"
+#include "unipi_spi.h"
+#include "unipi_common.h"
+
+s32 neuronspi_regmap_invalidate(void *data)
+{
+       int i;
+       int freq_cnt = 0;
+       while (!kthread_should_stop()) {
+               usleep_range(15000,25000);
+               if (freq_cnt == 450001) freq_cnt = 0;
+               for (i = 0; i < NEURONSPI_MAX_DEVS; i++) {
+                       if (neuronspi_s_dev[i] != NULL) {
+                               struct neuronspi_driver_data *d_data = spi_get_drvdata(neuronspi_s_dev[i]);
+                               if (d_data->combination_id == 0xFF) {
+                                       continue;
+                               }
+                               neuronspi_regmap_invalidate_device(d_data->reg_map, NEURONSPI_BOARDTABLE[d_data->combination_id].definition, freq_cnt);
+                       }
+               }
+               freq_cnt++;
+       }
+       return 0;
+}
+
+void neuronspi_regmap_invalidate_device(struct regmap *reg_map, struct neuronspi_board_combination *device_def, u32 period_counter)
+{
+       int block_start, block_len, block_counter, current_period, period_len;
+       int i;
+       block_start = -1;
+       block_len = -1;
+       block_counter = 0;
+       period_len = 1;
+
+       for (i = 0; i < device_def->block_count; i++) {
+               if (block_start == -1) {
+                       block_start = device_def->blocks[i];
+                       block_counter = 0;
+               } else if (block_len == -1) {
+                       block_len = device_def->blocks[i];
+               } else if ((block_counter != block_len)) {
+                       current_period = device_def->blocks[i] & 0x00FF0000;
+                       if ((block_counter + 1 != block_len) && ((device_def->blocks[i + 1] & 0x00FF0000) == current_period)) {
+                               period_len++;
+                       } else {
+                               switch (current_period) {
+                               case NEURONSPI_REGFLAG_ACC_AFAP: {
+                                       regcache_drop_region(reg_map, block_start + block_counter - period_len + 1, block_start + block_counter);
+                                       break;
+                               }
+                               case NEURONSPI_REGFLAG_ACC_10HZ: {
+                                       if ((period_counter) % 5) {
+                                               regcache_drop_region(reg_map, block_start + block_counter - period_len + 1, block_start + block_counter);
+                                       }
+                                       break;
+                               }
+                               case NEURONSPI_REGFLAG_ACC_1HZ: {
+                                       if ((period_counter % 50) == 0) {
+                                               regcache_drop_region(reg_map, block_start + block_counter - period_len + 1, block_start + block_counter);
+                                       }
+                                       break;
+                               }
+                               case NEURONSPI_REGFLAG_ACC_6SEC: {
+                                       if ((period_counter % 300) == 0) {
+                                               regcache_drop_region(reg_map, block_start + block_counter - period_len + 1, block_start + block_counter);
+                                       }
+                                       break;
+                               }
+                               case NEURONSPI_REGFLAG_ACC_1MIN: {
+                                       if ((period_counter % 3000) == 0) {
+                                               regcache_drop_region(reg_map, block_start + block_counter - period_len + 1, block_start + block_counter);
+                                       }
+                                       break;
+                               }
+                               case NEURONSPI_REGFLAG_ACC_15MIN: {
+                                       if ((period_counter % 45000) == 0) {
+                                               regcache_drop_region(reg_map, block_start + block_counter - period_len + 1, block_start + block_counter);
+                                       }
+                                       break;
+                               }
+                               default:
+                                       break;
+                               }
+                               period_len = 1;
+                       }
+                       block_counter++;
+               }
+               if (block_counter == block_len) {
+                       block_counter = 0;
+                       block_start = -1;
+                       block_len = -1;
+               }
+       }
+}
+
+int neuronspi_regmap_hw_reg_read(void *context, unsigned int reg, unsigned int *val) {
+       struct spi_device *spi = context;
+       struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi);
+       u8 *inp_buf;
+       u8 *outp_buf;
+       int write_length;
+       printk(KERN_INFO "NEURONSPI: RM_REG_READ\n");
+       write_length = neuronspi_spi_compose_single_register_read(reg, &inp_buf, &outp_buf);
+       neuronspi_spi_send_message(spi, inp_buf, outp_buf, write_length, n_spi->ideal_frequency, 25, 1);
+       memcpy(val, &outp_buf[NEURONSPI_HEADER_LENGTH], sizeof(u16));
+       kfree(inp_buf);
+       kfree(outp_buf);
+       return 0;
+}
+
+int neuronspi_regmap_hw_write(void *context, const void *data, size_t count) {
+       BUG_ON(count < 1);
+       return neuronspi_regmap_hw_gather_write(context, data, 1, data + 1, count - 1);
+}
+
+int neuronspi_regmap_hw_reg_write(void *context, unsigned int reg, unsigned int val) {
+       struct spi_device *spi = context;
+       struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi);
+       u8 *inp_buf;
+       u8 *outp_buf;
+       int write_length;
+       write_length = neuronspi_spi_compose_single_register_write(reg, &inp_buf, &outp_buf, (val >> 8));
+       printk(KERN_INFO "HW_REG_WRITE l:%d, r:%d, v:%d\n", write_length, reg, (val >> 8));
+       neuronspi_spi_send_message(spi, inp_buf, outp_buf, write_length, n_spi->ideal_frequency, 25, 1);
+       memcpy(&val, &outp_buf[NEURONSPI_HEADER_LENGTH], sizeof(u16));
+       kfree(inp_buf);
+       kfree(outp_buf);
+       return 0;
+}
+
+int neuronspi_regmap_hw_gather_write(void *context, const void *reg, size_t reg_size, const void *val, size_t val_size) {
+       u16 *mb_reg_buf = (u16*)reg;
+       u32 *mb_val_buf = (u32*)val;
+       struct spi_device *spi = context;
+       struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi);
+       u8 *inp_buf;
+       u8 *outp_buf;
+       int i, write_length;
+       int block_counter = 0;
+       printk(KERN_INFO "HW_REG_GATHER_WRITE:%d, %d, %x, %x\n", val_size, reg_size, mb_reg_buf[0], mb_val_buf[0]);
+       if (reg_size == 1) {
+               neuronspi_regmap_hw_reg_write(context,mb_reg_buf[0],mb_val_buf[0]);
+       } else {
+               for (i = 0; i < reg_size; i++) {
+                       // Swap endianness
+                       cpu_to_be16s((u16*)&(mb_val_buf[i]));
+                       // Check for continuity and read the largest possible continuous block
+                       if (block_counter == (reg_size - 1) || ((mb_reg_buf[i] + 1) != mb_reg_buf[i + 1]))  {
+                               write_length = neuronspi_spi_compose_multiple_register_write(block_counter, mb_reg_buf[i - block_counter], &inp_buf, &outp_buf,
+                                                                                                    (u8*)(&mb_val_buf[i - block_counter]));
+                               neuronspi_spi_send_message(spi, inp_buf, outp_buf, write_length, n_spi->ideal_frequency, 125, 1);
+                               block_counter = 0;
+                               kfree(inp_buf);
+                               kfree(outp_buf);
+                       } else {
+                               block_counter++;
+                       }
+               }
+       }
+       return 0;
+}
+
+int neuronspi_create_reg_starts(struct neuronspi_board_regstart_table *out_table, struct neuronspi_board_combination *board) {
+       if (board->features.di_count > 0) {
+               out_table->di_val_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_DI_READ);
+               out_table->di_counter_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_DI_COUNTER_UPPER);
+               out_table->di_deboun_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_DI_DEBOUNCE);
+               out_table->di_direct_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_DS_ENABLE);
+               out_table->di_polar_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_DS_POLARITY);
+               out_table->di_toggle_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_DS_TOGGLE);
+       }
+       if (board->features.do_count > 0) {
+               out_table->do_val_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_DO_RW);
+               out_table->do_pwm_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_PWM_DUTY);
+               out_table->do_pwm_c_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_PWM_CYCLE);
+               out_table->do_pwm_ps_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_PWM_PRESCALE);
+       }
+       if (board->features.led_count > 0) {
+               out_table->led_val_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_LED_RW);
+       }
+       if (board->features.light_count > 0) {
+               // TODO: Fill in light bus registers
+       }
+       if (board->features.ro_count > 0) {
+               out_table->ro_val_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_DO_RW);
+       }
+       if (board->features.sec_ai_count > 0) {
+               out_table->sec_ai_val_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_AI_VER2_READ_LOWER);
+               out_table->sec_ai_mode_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_AI_VER2_MODE);
+       }
+       if (board->features.sec_ao_count > 0) {
+               out_table->sec_ao_val_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_AO_VER2_RW);
+       }
+       if (board->features.stm_ao_count > 0) {
+               out_table->stm_ao_val_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_AO_BRAIN);
+               out_table->stm_ao_mode_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_AO_BRAIN_MODE);
+               out_table->stm_ao_vol_err = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_AO_BRAIN_V_ERR);
+               out_table->stm_ao_vol_off = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_AO_BRAIN_V_OFF);
+               out_table->stm_ao_curr_err = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_AO_BRAIN_I_ERR);
+               out_table->stm_ao_curr_off = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_AO_BRAIN_I_OFF);
+       }
+       if (board->features.stm_ai_count > 0) {
+               out_table->stm_ai_val_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_AI_BRAIN);
+               out_table->stm_ai_mode_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_AI_BRAIN_MODE);
+               out_table->stm_ai_vol_err = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_AI_BRAIN_V_ERR);
+               out_table->stm_ai_vol_off = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_AI_BRAIN_V_OFF);
+               out_table->stm_ai_curr_err = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_AI_BRAIN_I_ERR);
+               out_table->stm_ai_curr_off = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_AI_BRAIN_I_OFF);
+               out_table->stm_aio_val_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_AIO_BRAIN);
+               out_table->stm_aio_vol_err = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_AIO_BRAIN_ERR);
+               out_table->stm_aio_vol_off = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_AIO_BRAIN_OFF);
+               out_table->vref_inp = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_V_REF_INP);
+       }
+       out_table->uart_queue_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_TX_QUEUE_LEN);
+       out_table->uart_conf_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_RS485_CONFIG);
+       out_table->vref_int = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_V_REF_INT);
+       out_table->wd_timeout_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_MWD_TO);
+       out_table->sys_serial_num = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_SERIAL_NR_LOWER);
+       out_table->sys_sw_ver = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_SW_VER);
+       out_table->sys_hw_ver = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_HW_VER);
+       out_table->sys_hw_flash_ver = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_FLASH_HW_VER);
+       return 0;
+}
+
+s32 neuronspi_find_reg_start(struct neuronspi_board_combination *board, u16 regfun) {
+       int i;
+       int block_start = -1;
+       int block_len = -1;
+       int block_counter = 0;
+       for (i = 0; i < board->block_count; i++) {
+               if (block_start == -1) {
+                       block_start = board->blocks[i];
+               } else if (block_len == -1) {
+                       block_len = board->blocks[i];
+               } else if ((board->blocks[i] & 0xFFFF) == regfun) {
+                       //printk(KERN_INFO "NEURONSPI: Reg Start Fun: %x RegS: %d", regfun, block_start + block_counter);
+                       return block_start + block_counter;
+               } else {
+                       block_counter++;
+               }
+               if (block_counter == block_len) {
+                       block_counter = 0;
+                       block_start = -1;
+                       block_len = -1;
+               }
+       }
+       return -1;
+}
+
+int neuronspi_regmap_hw_read(void *context, const void *reg_buf, size_t reg_size, void *val_buf, size_t val_size) {
+       const u16 *mb_reg_buf = reg_buf;
+       u16 *mb_val_buf = val_buf;
+       struct spi_device *spi;
+       struct neuronspi_driver_data *n_spi;
+       u8 *inp_buf;
+       u8 *outp_buf;
+       int i, write_length;
+       int block_counter = 0;
+       if (context == NULL) {
+               return 0;
+       }
+       spi = context;
+       n_spi = spi_get_drvdata(spi);
+       if (n_spi == NULL) {
+               return 0;
+       }
+       for (i = 0; i < (reg_size / 2); i++) {
+               // Check for continuity and read the largest possible continuous block
+               if (block_counter == ((reg_size / 2) - 1) || ((mb_reg_buf[i] + 1) != mb_reg_buf[i + 1])) {
+                       write_length = neuronspi_spi_compose_multiple_register_read(block_counter + 1, mb_reg_buf[i - block_counter], &inp_buf, &outp_buf);
+                       neuronspi_spi_send_message(spi, inp_buf, outp_buf, write_length, n_spi->ideal_frequency, 125, 1);
+                       memcpy(&mb_val_buf[i - block_counter], &outp_buf[NEURONSPI_HEADER_LENGTH], (block_counter + 1) * 2);
+                       kfree(inp_buf);
+                       kfree(outp_buf);
+                       block_counter = 0;
+               } else {
+                       block_counter++;
+               }
+       }
+       printk(KERN_INFO "NEURONSPI: RM_READ %d %x %d %x\n", reg_size, mb_reg_buf[0], val_size, mb_val_buf[0]);
+       return 0;
+}
+
+s32 neuronspi_find_model_id(u32 probe_count)
+{
+       struct neuronspi_driver_data *n_spi;
+       int i,j, ret = -1;
+       u8 *inv = kzalloc(sizeof(*inv) * NEURONSPI_MODELTABLE_LEN, GFP_KERNEL);
+       for (i = 0; i < probe_count; i++) {
+               if (neuronspi_s_dev[i]) {
+                       n_spi = spi_get_drvdata(neuronspi_s_dev[i]);
+                       for (j = 0; j < NEURONSPI_MODELTABLE_LEN; j++) {
+                               if (i + 1 > NEURONSPI_MODELTABLE[j].combination_count) {
+                                       inv[j] = 1;
+                               } else if (NEURONSPI_MODELTABLE[j].combinations[i].combination_board_id != n_spi->combination_id) {
+                                       inv[j] = 1;
+                               }
+                       }
+               } else {
+                       for (j = 0; j < NEURONSPI_MODELTABLE_LEN; j++) {
+                               if (i + 1 < NEURONSPI_MODELTABLE[j].combination_count) {
+                                       inv[j] = 1;
+                               }
+                       }
+               }
+       }
+       for (i = 0; i < NEURONSPI_MODELTABLE_LEN; i++) {
+               if (inv[i] != 1) {
+                       ret = i;
+                       break;
+               }
+       }
+       kfree(inv);
+       return ret;
+}
+
 
index 0c5e5221951ebb48fde0ae4297ef2551d7f63ff9..6fd6aa1bb3ca7e6c8b94a4acff720eacecb5d38b 100644 (file)
 #ifndef MODULES_NEURON_SPI_SRC_UNIPI_PLATFORM_H_
 #define MODULES_NEURON_SPI_SRC_UNIPI_PLATFORM_H_
 
+#include <linux/bitops.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/gpio.h>
+#include <linux/gpio/driver.h>
+#include <linux/i2c.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/regmap.h>
+#include <linux/serial_core.h>
+#include <linux/serial.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/spi/spi.h>
+#include <linux/leds.h>
+#include <linux/uaccess.h>
+#include <asm/termbits.h>
+#include <asm/gpio.h>
+#include <uapi/linux/iio/types.h>
 
+#include "unipi_common.h"
+
+/********************************
+ * HW Constants Data Structures *
+ ********************************/
+
+struct neuronspi_board_entry {
+       u16             index;
+       u16             lower_board_id;
+       u16             upper_board_id;
+       u16             data_register_count;
+       u16             config_register_count;
+       struct neuronspi_board_combination *definition;
+};
+
+struct neuronspi_register_block
+{
+       u32     starting_register;
+       u32     register_count;
+       u32             *register_flags;
+};
+
+struct neuronspi_board_features
+{
+       u32             do_count;
+       u32             ro_count;
+       u32             ds_count;
+       u32             di_count;
+       u32             led_count;
+       u32             stm_ai_count;
+       u32             stm_ao_count;
+       u32             sec_ai_count;
+       u32             sec_ao_count;
+       u32             uart_master_count;
+       u32             uart_slave_count;
+       u32             pwm_channel_count;
+       u32             wd_count;
+       u32             extension_sys_count;
+       u32             light_count;
+       u32             owire_count;
+};
+
+struct neuronspi_board_regstart_table
+{
+       u32             do_val_reg;
+       u32             do_val_coil;
+       u32             do_pwm_reg;
+       u32             do_pwm_ps_reg;
+       u32             do_pwm_c_reg;
+       u32             di_val_reg;
+       u32             di_counter_reg;
+       u32             di_direct_reg;
+       u32             di_deboun_reg;
+       u32             di_polar_reg;
+       u32             di_toggle_reg;
+       u32             uart_queue_reg;
+       u32             uart_conf_reg;
+       u32             uart_address_reg;
+       u32             led_val_coil;
+       u32             led_val_reg;
+       u32             wd_val_reg;
+       u32             wd_timeout_reg;
+       u32             wd_nv_sav_coil;
+       u32             wd_reset_coil;
+       u32             reg_start_reg;
+       u32             ro_val_reg;
+       u32             ro_val_coil;
+       u32             vref_inp;
+       u32             vref_int;
+       u32             stm_ao_val_reg;
+       u32             stm_ao_mode_reg;
+       u32             stm_ao_vol_err;
+       u32             stm_ao_vol_off;
+       u32             stm_ao_curr_err;
+       u32             stm_ao_curr_off;
+       u32             stm_ai_val_reg;
+       u32             stm_ai_mode_reg;
+       u32             stm_ai_curr_err;
+       u32             stm_ai_curr_off;
+       u32             stm_ai_vol_err;
+       u32             stm_ai_vol_off;
+       u32             stm_aio_val_reg;
+       u32             stm_aio_vol_err;
+       u32             stm_aio_vol_off;
+       u32             sec_ao_val_reg;
+       u32             sec_ao_mode_reg;
+       u32             sec_ai_val_reg;
+       u32             sec_ai_mode_reg;
+       u32             sys_serial_num;
+       u32             sys_hw_ver;
+       u32             sys_hw_flash_ver;
+       u32             sys_sw_ver;
+};
+
+struct neuronspi_board_combination
+{
+       u32                                                                     combination_board_id;
+       uint16_t                                                        lower_board_id;
+       uint16_t                                                        upper_board_id;
+       u32                                                             block_count;
+       size_t                                                          name_length;
+       const char*                                                     combination_name;
+       struct neuronspi_board_features         features;
+       u32                                                                     *blocks;
+};
+
+struct neuronspi_model_definition
+{
+       size_t                                                          eeprom_length;
+       const char*                                             eeprom_name;
+       size_t                                                          name_length;
+       const char*                                                     model_name;
+       u32                                                                     combination_count;
+       struct neuronspi_board_combination *combinations;
+};
+
+
+/******************
+ * HW Definitions *
+ ******************/
+// Lower Boards:
+#define NEURONSPI_BOARD_LOWER_B1000_ID         0
+#define NEURONSPI_BOARD_LOWER_E8DI8RO_ID       1
+#define NEURONSPI_BOARD_LOWER_E14RO_ID         2
+#define NEURONSPI_BOARD_LOWER_E16DI_ID         3
+#define NEURONSPI_BOARD_LOWER_E4AI4AO_ID       11
+#define NEURONSPI_BOARD_LOWER_B485_ID          13
+#define NEURONSPI_BOARD_LOWER_E4LIGHT_ID       14
+
+
+// Upper Boards:
+#define NEURONSPI_BOARD_UPPER_NONE_ID          0
+#define NEURONSPI_BOARD_UPPER_P11DIR485_ID     1
+#define NEURONSPI_BOARD_UPPER_U14RO_ID         2
+#define NEURONSPI_BOARD_UPPER_U14DI_ID         3
+#define NEURONSPI_BOARD_UPPER_P6DI5RO_ID       4
+#define NEURONSPI_BOARD_UPPER_U6DI5RO_ID       5
+
+// Register function codes:
+#define NEURONSPI_FUNGROUP_DI                                  0
+#define NEURONSPI_REGFUN_DI_READ                       0 | NEURONSPI_FUNGROUP_DI << 8
+#define NEURONSPI_REGFUN_DI_COUNTER_LOWER      1 | NEURONSPI_FUNGROUP_DI << 8
+#define NEURONSPI_REGFUN_DI_COUNTER_UPPER      2 | NEURONSPI_FUNGROUP_DI << 8
+#define NEURONSPI_REGFUN_DI_DEBOUNCE           3 | NEURONSPI_FUNGROUP_DI << 8
+#define NEURONSPI_REGFUN_DS_ENABLE                     4 | NEURONSPI_FUNGROUP_DI << 8
+#define NEURONSPI_REGFUN_DS_POLARITY           5 | NEURONSPI_FUNGROUP_DI << 8
+#define NEURONSPI_REGFUN_DS_TOGGLE                     6 | NEURONSPI_FUNGROUP_DI << 8
+
+#define NEURONSPI_FUNGROUP_DO                                  1
+#define NEURONSPI_REGFUN_DO_RW                         0 | NEURONSPI_FUNGROUP_DO << 8
+
+#define NEURONSPI_FUNGROUP_AO_BRAIN                            2
+#define NEURONSPI_REGFUN_AO_BRAIN                      0 | NEURONSPI_FUNGROUP_AO_BRAIN << 8
+#define NEURONSPI_REGFUN_AO_BRAIN_MODE         1 | NEURONSPI_FUNGROUP_AO_BRAIN << 8
+#define NEURONSPI_REGFUN_AO_BRAIN_V_ERR                2 | NEURONSPI_FUNGROUP_AO_BRAIN << 8
+#define NEURONSPI_REGFUN_AO_BRAIN_V_OFF                3 | NEURONSPI_FUNGROUP_AO_BRAIN << 8
+#define NEURONSPI_REGFUN_AO_BRAIN_I_ERR        4 | NEURONSPI_FUNGROUP_AO_BRAIN << 8
+#define NEURONSPI_REGFUN_AO_BRAIN_I_OFF        5 | NEURONSPI_FUNGROUP_AO_BRAIN << 8
+
+#define NEURONSPI_FUNGROUP_AI_BRAIN                            3
+#define NEURONSPI_REGFUN_AI_BRAIN                      0 | NEURONSPI_FUNGROUP_AI_BRAIN << 8
+#define NEURONSPI_REGFUN_AIO_BRAIN                     1 | NEURONSPI_FUNGROUP_AI_BRAIN << 8
+#define NEURONSPI_REGFUN_AI_BRAIN_MODE         2 | NEURONSPI_FUNGROUP_AI_BRAIN << 8
+#define NEURONSPI_REGFUN_AI_BRAIN_V_ERR                3 | NEURONSPI_FUNGROUP_AI_BRAIN << 8
+#define NEURONSPI_REGFUN_AI_BRAIN_V_OFF                4 | NEURONSPI_FUNGROUP_AI_BRAIN << 8
+#define NEURONSPI_REGFUN_AI_BRAIN_I_ERR                5 | NEURONSPI_FUNGROUP_AI_BRAIN << 8
+#define NEURONSPI_REGFUN_AI_BRAIN_I_OFF                6 | NEURONSPI_FUNGROUP_AI_BRAIN << 8
+#define NEURONSPI_REGFUN_AIO_BRAIN_ERR         7 | NEURONSPI_FUNGROUP_AI_BRAIN << 8
+#define NEURONSPI_REGFUN_AIO_BRAIN_OFF         8 | NEURONSPI_FUNGROUP_AI_BRAIN << 8
+
+#define NEURONSPI_FUNGROUP_SYSTEM                              4
+#define NEURONSPI_REGFUN_V_REF_INT                     0 | NEURONSPI_FUNGROUP_SYSTEM << 8
+#define NEURONSPI_REGFUN_V_REF_INP                     1 | NEURONSPI_FUNGROUP_SYSTEM << 8
+#define NEURONSPI_REGFUN_LED_RW                                2 | NEURONSPI_FUNGROUP_SYSTEM << 8
+#define NEURONSPI_REGFUN_SW_VER                        3 | NEURONSPI_FUNGROUP_SYSTEM << 8
+#define NEURONSPI_REGFUN_DIDO_COUNT                    4 | NEURONSPI_FUNGROUP_SYSTEM << 8
+#define NEURONSPI_REGFUN_UAIO_COUNT                    5 | NEURONSPI_FUNGROUP_SYSTEM << 8
+#define NEURONSPI_REGFUN_HW_VER                                6 | NEURONSPI_FUNGROUP_SYSTEM << 8
+#define NEURONSPI_REGFUN_FLASH_HW_VER          7 | NEURONSPI_FUNGROUP_SYSTEM << 8
+#define NEURONSPI_REGFUN_SERIAL_NR_LOWER       8 | NEURONSPI_FUNGROUP_SYSTEM << 8
+#define NEURONSPI_REGFUN_SERIAL_NR_UPPER       9 | NEURONSPI_FUNGROUP_SYSTEM << 8
+#define NEURONSPI_REGFUN_INTERRUPTS                    10 | NEURONSPI_FUNGROUP_SYSTEM << 8
+#define NEURONSPI_REGFUN_NONE_TEST                     11 | NEURONSPI_FUNGROUP_SYSTEM << 8
+
+#define NEURONSPI_FUNGROUP_MWD                                 5
+#define NEURONSPI_REGFUN_MWD_TO                                0 | NEURONSPI_FUNGROUP_MWD << 8
+#define NEURONSPI_REGFUN_MWD_STATUS                    1 | NEURONSPI_FUNGROUP_MWD << 8
+
+#define NEURONSPI_FUNGROUP_PWM                                 6
+#define NEURONSPI_REGFUN_PWM_DUTY                      0 | NEURONSPI_FUNGROUP_PWM << 8
+#define NEURONSPI_REGFUN_PWM_PRESCALE          1 | NEURONSPI_FUNGROUP_PWM << 8
+#define NEURONSPI_REGFUN_PWM_CYCLE                     2 | NEURONSPI_FUNGROUP_PWM << 8
+
+
+#define NEURONSPI_FUNGROUP_RS485                               7
+#define NEURONSPI_REGFUN_TX_QUEUE_LEN          0 | NEURONSPI_FUNGROUP_RS485 << 8
+#define NEURONSPI_REGFUN_RS485_CONFIG          1 | NEURONSPI_FUNGROUP_RS485 << 8
+#define NEURONSPI_REGFUN_RS485_ADDRESS         2 | NEURONSPI_FUNGROUP_RS485 << 8
+
+#define NEURONSPI_FUNGROUP_AO_VER2                             8
+#define NEURONSPI_REGFUN_AO_VER2_RW                    0 | NEURONSPI_FUNGROUP_AO_VER2 << 8
+
+#define NEURONSPI_FUNGROUP_AI_VER2                             9
+#define NEURONSPI_REGFUN_AI_VER2_READ_LOWER    0 | NEURONSPI_FUNGROUP_AI_VER2 << 8
+#define NEURONSPI_REGFUN_AI_VER2_READ_UPPER    0 | NEURONSPI_FUNGROUP_AI_VER2 << 8
+#define NEURONSPI_REGFUN_AI_VER2_MODE          1 | NEURONSPI_FUNGROUP_AI_VER2 << 8
+
+// Register access flags:
+#define NEURONSPI_REGFLAG_ACC_NEVER    0
+#define NEURONSPI_REGFLAG_ACC_AFAP     0x1 << 16
+#define NEURONSPI_REGFLAG_ACC_10HZ     0x2 << 16
+#define NEURONSPI_REGFLAG_ACC_1HZ   0x3 << 16
+#define NEURONSPI_REGFLAG_ACC_6SEC  0x4 << 16
+#define NEURONSPI_REGFLAG_ACC_1MIN  0x5 << 16
+#define NEURONSPI_REGFLAG_ACC_15MIN 0x6 << 16
+#define NEURONSPI_REGFLAG_ACC_ONCE     0x7 << 16
+
+// Register system flags:
+#define NEURONSPI_REGFLAG_SYS_READ_ONLY        0x10 << 24
+
+#define NEURONSPI_IIO_AI_STM_MODE_VOLTAGE 0x0
+#define NEURONSPI_IIO_AI_STM_MODE_CURRENT 0x1
+#define NEURONSPI_IIO_AI_STM_MODE_RESISTANCE 0x3
+
+/*********************
+ * Board Definitions *
+ *********************/
+
+// B_1000 (S103)
+#define NEURONSPI_BOARD_B1000_HW_DEFINITION_BLOCK_SIZE 57
+static u32 NEURONSPI_BOARD_B1000_HW_DEFINITION_BLOCK[NEURONSPI_BOARD_B1000_HW_DEFINITION_BLOCK_SIZE] = {
+               0, 21,  // Register block beginning and size
+               NEURONSPI_REGFUN_DI_READ | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY,                // 0
+               NEURONSPI_REGFUN_DO_RW | NEURONSPI_REGFLAG_ACC_10HZ,                                                                                    // 1
+               NEURONSPI_REGFUN_AO_BRAIN | NEURONSPI_REGFLAG_ACC_AFAP,                                                                                 // 2
+               NEURONSPI_REGFUN_AI_BRAIN | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY,       // 3
+               NEURONSPI_REGFUN_AIO_BRAIN | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY,              // 4
+               NEURONSPI_REGFUN_V_REF_INP | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY,              // 5
+               NEURONSPI_REGFUN_MWD_STATUS | NEURONSPI_REGFLAG_ACC_6SEC | NEURONSPI_REGFLAG_SYS_READ_ONLY,     // 6
+               NEURONSPI_REGFUN_TX_QUEUE_LEN | NEURONSPI_REGFLAG_ACC_10HZ,                                                                             // 7
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 8
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 9
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 10
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 11
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 12
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 13
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 14
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 15
+               NEURONSPI_REGFUN_PWM_DUTY | NEURONSPI_REGFLAG_ACC_6SEC,                                                                                 // 16
+               NEURONSPI_REGFUN_PWM_DUTY | NEURONSPI_REGFLAG_ACC_6SEC,                                                                                 // 17
+               NEURONSPI_REGFUN_PWM_DUTY | NEURONSPI_REGFLAG_ACC_6SEC,                                                                                 // 18
+               NEURONSPI_REGFUN_PWM_DUTY | NEURONSPI_REGFLAG_ACC_6SEC,                                                                                 // 19
+               NEURONSPI_REGFUN_LED_RW | NEURONSPI_REGFLAG_ACC_AFAP,                                                                                   // 20
+               1000, 32, // Register block beginning and size
+               NEURONSPI_REGFUN_SW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,                 // 1000
+               NEURONSPI_REGFUN_DIDO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,             // 1001
+               NEURONSPI_REGFUN_UAIO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,     // 1002
+               NEURONSPI_REGFUN_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE  | NEURONSPI_REGFLAG_SYS_READ_ONLY,                // 1003
+               NEURONSPI_REGFUN_FLASH_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,   // 1004
+               NEURONSPI_REGFUN_SERIAL_NR_LOWER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1005
+               NEURONSPI_REGFUN_SERIAL_NR_UPPER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1006
+               NEURONSPI_REGFUN_INTERRUPTS | NEURONSPI_REGFLAG_ACC_AFAP,                                                                               // 1007
+               NEURONSPI_REGFUN_MWD_TO | NEURONSPI_REGFLAG_ACC_6SEC | NEURONSPI_REGFLAG_SYS_READ_ONLY,                 // 1008
+               NEURONSPI_REGFUN_V_REF_INT | NEURONSPI_REGFLAG_ACC_ONCE,                                                                                // 1009
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1010
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1011
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1012
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1013
+               NEURONSPI_REGFUN_DS_ENABLE | NEURONSPI_REGFLAG_ACC_1HZ,                                                                                 // 1014
+               NEURONSPI_REGFUN_DS_POLARITY | NEURONSPI_REGFLAG_ACC_1HZ,                                                                               // 1015
+               NEURONSPI_REGFUN_DS_TOGGLE | NEURONSPI_REGFLAG_ACC_1HZ,                                                                                 // 1016
+               NEURONSPI_REGFUN_PWM_PRESCALE | NEURONSPI_REGFLAG_ACC_1HZ,                                                                      // 1017
+               NEURONSPI_REGFUN_PWM_CYCLE | NEURONSPI_REGFLAG_ACC_1HZ,                                                                         // 1018
+               NEURONSPI_REGFUN_AO_BRAIN_MODE | NEURONSPI_REGFLAG_ACC_1HZ,                                                                             // 1019
+               NEURONSPI_REGFUN_AO_BRAIN_V_ERR | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1020
+               NEURONSPI_REGFUN_AO_BRAIN_V_OFF | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1021
+               NEURONSPI_REGFUN_AO_BRAIN_I_ERR | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1022
+               NEURONSPI_REGFUN_AO_BRAIN_I_OFF | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1023
+               NEURONSPI_REGFUN_AI_BRAIN_MODE | NEURONSPI_REGFLAG_ACC_1HZ,                                                                             // 1024
+               NEURONSPI_REGFUN_AI_BRAIN_V_ERR | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1025
+               NEURONSPI_REGFUN_AI_BRAIN_V_OFF | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1026
+               NEURONSPI_REGFUN_AI_BRAIN_I_ERR | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1027
+               NEURONSPI_REGFUN_AI_BRAIN_I_OFF | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1028
+               NEURONSPI_REGFUN_AIO_BRAIN_OFF | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,  // 1029
+               NEURONSPI_REGFUN_AIO_BRAIN_ERR | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,  // 1030
+               NEURONSPI_REGFUN_RS485_CONFIG | NEURONSPI_REGFLAG_ACC_6SEC                                                                              // 1031
+};
+
+#define NEURONSPI_BOARD_B1000_HW_FEATURES {    \
+               .do_count =                                       4,    \
+               .ro_count =                                       0,    \
+               .ds_count =                                       4,    \
+               .di_count =                                       4,    \
+               .led_count =                              4,    \
+               .stm_ai_count =                           1,    \
+               .stm_ao_count =                           1,    \
+               .sec_ai_count =                           0,    \
+               .sec_ao_count =                           0,    \
+               .uart_master_count =              1,    \
+               .uart_slave_count =               0,    \
+               .pwm_channel_count =              4,    \
+               .wd_count =                               1,    \
+               .extension_sys_count =            0,    \
+               .light_count =                            0,    \
+               .owire_count =                            1,    \
+}
+
+#define NEURONSPI_BOARD_B1000_HW_DEFINITION { \
+               .combination_board_id =         0, \
+               .lower_board_id =                       NEURONSPI_BOARD_LOWER_B1000_ID, \
+               .upper_board_id =                       NEURONSPI_BOARD_UPPER_NONE_ID, \
+               .block_count =                          NEURONSPI_BOARD_B1000_HW_DEFINITION_BLOCK_SIZE, \
+               .name_length =                          6, \
+               .combination_name =                     "B_1000", \
+               .features =                                     NEURONSPI_BOARD_B1000_HW_FEATURES, \
+               .blocks =                                       NEURONSPI_BOARD_B1000_HW_DEFINITION_BLOCK \
+}
+static struct neuronspi_board_combination NEURONSPI_BOARD_B1000_HW_COMBINATION[] = {NEURONSPI_BOARD_B1000_HW_DEFINITION};
+
+// E-8Di8Ro (M103)
+#define NEURONSPI_BOARD_E8DI8RO_HW_DEFINITION_BLOCK_SIZE 44
+static u32 NEURONSPI_BOARD_E8DI8RO_HW_DEFINITION_BLOCK[NEURONSPI_BOARD_E8DI8RO_HW_DEFINITION_BLOCK_SIZE] = {
+               0, 19,  // Register block beginning and size
+               NEURONSPI_REGFUN_DI_READ | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY,                // 0
+               NEURONSPI_REGFUN_DO_RW | NEURONSPI_REGFLAG_ACC_10HZ,                                                                                    // 1
+               NEURONSPI_REGFUN_MWD_STATUS | NEURONSPI_REGFLAG_ACC_6SEC | NEURONSPI_REGFLAG_SYS_READ_ONLY,     // 2
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 3
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 4
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 5
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 6
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 7
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 8
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 9
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 10
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 11
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 12
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 13
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 14
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 15
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 16
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 17
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 18
+               1000, 17, // Register block beginning and size
+               NEURONSPI_REGFUN_SW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,                 // 1000
+               NEURONSPI_REGFUN_DIDO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,             // 1001
+               NEURONSPI_REGFUN_UAIO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,             // 1002
+               NEURONSPI_REGFUN_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,                 // 1003
+               NEURONSPI_REGFUN_FLASH_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,   // 1004
+               NEURONSPI_REGFUN_SERIAL_NR_LOWER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1005
+               NEURONSPI_REGFUN_SERIAL_NR_UPPER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1006
+               NEURONSPI_REGFUN_INTERRUPTS | NEURONSPI_REGFLAG_ACC_AFAP,                                                                               // 1007
+               NEURONSPI_REGFUN_MWD_TO | NEURONSPI_REGFLAG_ACC_6SEC,                                                                                   // 1008
+               NEURONSPI_REGFUN_V_REF_INT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,              // 1009
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1010
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1011
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1012
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1013
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1014
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1015
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1016
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1017
+               NEURONSPI_REGFUN_DS_ENABLE | NEURONSPI_REGFLAG_ACC_1HZ,                                                                                 // 1018
+               NEURONSPI_REGFUN_DS_POLARITY | NEURONSPI_REGFLAG_ACC_1HZ,                                                                               // 1019
+               NEURONSPI_REGFUN_DS_TOGGLE | NEURONSPI_REGFLAG_ACC_1HZ,                                                                                 // 1020
+};
+
+#define NEURONSPI_BOARD_E8DI8RO_HW_FEATURES {  \
+               .do_count =                                       0,    \
+               .ro_count =                                       8,    \
+               .ds_count =                                       8,    \
+               .di_count =                                       8,    \
+               .led_count =                              0,    \
+               .stm_ai_count =                           0,    \
+               .stm_ao_count =                           0,    \
+               .sec_ai_count =                           0,    \
+               .sec_ao_count =                           0,    \
+               .uart_master_count =              0,    \
+               .uart_slave_count =               0,    \
+               .pwm_channel_count =              0,    \
+               .wd_count =                               1,    \
+               .extension_sys_count =            0,    \
+               .light_count =                            0,    \
+               .owire_count =                            0,    \
+}
+
+#define NEURONSPI_BOARD_E8DI8RO_HW_DEFINITION { \
+               .combination_board_id =         1, \
+               .lower_board_id =                       NEURONSPI_BOARD_LOWER_E8DI8RO_ID, \
+               .upper_board_id =                       NEURONSPI_BOARD_UPPER_NONE_ID, \
+               .block_count =                          NEURONSPI_BOARD_E8DI8RO_HW_DEFINITION_BLOCK_SIZE, \
+               .name_length =                          8, \
+               .combination_name =                     "E_8Di8Ro", \
+               .blocks =                                       NEURONSPI_BOARD_E8DI8RO_HW_DEFINITION_BLOCK, \
+               .features =                                     NEURONSPI_BOARD_E8DI8RO_HW_FEATURES     \
+}
+static struct neuronspi_board_combination NEURONSPI_BOARD_E8DI8RO_HW_COMBINATION[] = {NEURONSPI_BOARD_E8DI8RO_HW_DEFINITION};
+
+// E-14Ro
+#define NEURONSPI_BOARD_E14RO_HW_DEFINITION_BLOCK_SIZE 15
+static u32 NEURONSPI_BOARD_E14RO_HW_DEFINITION_BLOCK[NEURONSPI_BOARD_E14RO_HW_DEFINITION_BLOCK_SIZE] = {
+               0, 1,   // Register block beginning and size
+               NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE,                                                                                // 0
+               1000, 10,
+               NEURONSPI_REGFUN_SW_VER | NEURONSPI_REGFLAG_ACC_ONCE,                                                                                   // 1000
+               NEURONSPI_REGFUN_DIDO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE,                                                                               // 1001
+               NEURONSPI_REGFUN_UAIO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE,                                                                               // 1002
+               NEURONSPI_REGFUN_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE,                                                                                   // 1003
+               NEURONSPI_REGFUN_FLASH_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE,                                                                     // 1004
+               NEURONSPI_REGFUN_SERIAL_NR_LOWER | NEURONSPI_REGFLAG_ACC_ONCE,                                                                  // 1005
+               NEURONSPI_REGFUN_SERIAL_NR_UPPER | NEURONSPI_REGFLAG_ACC_ONCE,                                                                  // 1006
+               NEURONSPI_REGFUN_INTERRUPTS | NEURONSPI_REGFLAG_ACC_AFAP,                                                                               // 1007
+               NEURONSPI_REGFUN_MWD_TO | NEURONSPI_REGFLAG_ACC_6SEC,                                                                                   // 1008
+               NEURONSPI_REGFUN_V_REF_INT | NEURONSPI_REGFLAG_ACC_ONCE,                                                                                // 1009
+};
+
+#define NEURONSPI_BOARD_E14RO_HW_FEATURES {    \
+               .do_count =                                       0,    \
+               .ro_count =                                       14,   \
+               .ds_count =                                       0,    \
+               .di_count =                                       0,    \
+               .led_count =                              0,    \
+               .stm_ai_count =                           0,    \
+               .stm_ao_count =                           0,    \
+               .sec_ai_count =                           0,    \
+               .sec_ao_count =                           0,    \
+               .uart_master_count =              0,    \
+               .uart_slave_count =               0,    \
+               .pwm_channel_count =              0,    \
+               .wd_count =                               1,    \
+               .extension_sys_count =            0,    \
+               .light_count =                            0,    \
+               .owire_count =                            0,    \
+}
+
+#define NEURONSPI_BOARD_E14RO_HW_DEFINITION { \
+               .combination_board_id =         2, \
+               .lower_board_id =                       NEURONSPI_BOARD_LOWER_E14RO_ID, \
+               .upper_board_id =                       NEURONSPI_BOARD_UPPER_NONE_ID, \
+               .block_count =                          NEURONSPI_BOARD_E14RO_HW_DEFINITION_BLOCK_SIZE, \
+               .name_length =                          6, \
+               .combination_name =                     "E_14Ro", \
+               .blocks =                                       NEURONSPI_BOARD_E14RO_HW_DEFINITION_BLOCK, \
+               .features =                             NEURONSPI_BOARD_E14RO_HW_FEATURES \
+}
+static struct neuronspi_board_combination NEURONSPI_BOARD_E14RO_HW_COMBINATION[] = {NEURONSPI_BOARD_E14RO_HW_DEFINITION};
+
+// E-16Di
+#define NEURONSPI_BOARD_E16DI_HW_DEFINITION_BLOCK_SIZE 15
+static u32 NEURONSPI_BOARD_E16DI_HW_DEFINITION_BLOCK[NEURONSPI_BOARD_E16DI_HW_DEFINITION_BLOCK_SIZE] = {
+               0, 1,   // Register block beginning and size
+               NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE,                                                                                // 0
+               1000, 10,
+               NEURONSPI_REGFUN_SW_VER | NEURONSPI_REGFLAG_ACC_ONCE,                                                                                   // 1000
+               NEURONSPI_REGFUN_DIDO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE,                                                                               // 1001
+               NEURONSPI_REGFUN_UAIO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE,                                                                               // 1002
+               NEURONSPI_REGFUN_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE,                                                                                   // 1003
+               NEURONSPI_REGFUN_FLASH_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE,                                                                     // 1004
+               NEURONSPI_REGFUN_SERIAL_NR_LOWER | NEURONSPI_REGFLAG_ACC_ONCE,                                                                  // 1005
+               NEURONSPI_REGFUN_SERIAL_NR_UPPER | NEURONSPI_REGFLAG_ACC_ONCE,                                                                  // 1006
+               NEURONSPI_REGFUN_INTERRUPTS | NEURONSPI_REGFLAG_ACC_AFAP,                                                                               // 1007
+               NEURONSPI_REGFUN_MWD_TO | NEURONSPI_REGFLAG_ACC_6SEC,                                                                                   // 1008
+               NEURONSPI_REGFUN_V_REF_INT | NEURONSPI_REGFLAG_ACC_ONCE,                                                                                // 1009
+};
+
+#define NEURONSPI_BOARD_E16DI_HW_FEATURES {    \
+               .do_count =                                       0,    \
+               .ro_count =                                       0,    \
+               .ds_count =                                       0,    \
+               .di_count =                                       16,   \
+               .led_count =                              0,    \
+               .stm_ai_count =                           0,    \
+               .stm_ao_count =                           0,    \
+               .sec_ai_count =                           0,    \
+               .sec_ao_count =                           0,    \
+               .uart_master_count =              0,    \
+               .uart_slave_count =               0,    \
+               .pwm_channel_count =              0,    \
+               .wd_count =                               1,    \
+               .extension_sys_count =            0,    \
+               .light_count =                            0,    \
+               .owire_count =                            0,    \
+}
+
+#define NEURONSPI_BOARD_E16DI_HW_DEFINITION { \
+               .combination_board_id =         3, \
+               .lower_board_id =                       NEURONSPI_BOARD_LOWER_E16DI_ID, \
+               .upper_board_id =                       NEURONSPI_BOARD_UPPER_NONE_ID, \
+               .block_count =                          NEURONSPI_BOARD_E16DI_HW_DEFINITION_BLOCK_SIZE, \
+               .name_length =                          6, \
+               .combination_name =                     "E_16Di", \
+               .blocks =                                       NEURONSPI_BOARD_E16DI_HW_DEFINITION_BLOCK, \
+               .features =                             NEURONSPI_BOARD_E16DI_HW_FEATURES \
+}
+
+static struct neuronspi_board_combination NEURONSPI_BOARD_E16DI_HW_COMBINATION[] = {NEURONSPI_BOARD_E16DI_HW_DEFINITION};
+
+// E-8Di8Ro_P-11DiR485 (xS10)
+#define NEURONSPI_BOARD_E8DI8ROP11DIR485_HW_DEFINITION_BLOCK_SIZE 47
+static u32 NEURONSPI_BOARD_E8DI8ROP11DIR485_HW_DEFINITION_BLOCK[NEURONSPI_BOARD_E8DI8ROP11DIR485_HW_DEFINITION_BLOCK_SIZE] = {
+               0, 20,  // Register block beginning and size
+               NEURONSPI_REGFUN_DI_READ | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY,                // 0
+               NEURONSPI_REGFUN_DO_RW | NEURONSPI_REGFLAG_ACC_10HZ,                                                                                    // 1
+               NEURONSPI_REGFUN_MWD_STATUS | NEURONSPI_REGFLAG_ACC_6SEC | NEURONSPI_REGFLAG_SYS_READ_ONLY,     // 2
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 3
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 4
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 5
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 6
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 7
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 8
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 9
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 10
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 11
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 12
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 13
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 14
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 15
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 16
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 17
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 18
+               NEURONSPI_REGFUN_LED_RW | NEURONSPI_REGFLAG_ACC_1HZ,                                                                                    // 19
+               1000, 23, // Register block beginning and size
+               NEURONSPI_REGFUN_SW_VER | NEURONSPI_REGFLAG_ACC_ONCE,                                                                                   // 1000
+               NEURONSPI_REGFUN_DIDO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE,                                                                               // 1001
+               NEURONSPI_REGFUN_UAIO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE,                                                                               // 1002
+               NEURONSPI_REGFUN_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE,                                                                                   // 1003
+               NEURONSPI_REGFUN_FLASH_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE,                                                                     // 1004
+               NEURONSPI_REGFUN_SERIAL_NR_LOWER | NEURONSPI_REGFLAG_ACC_ONCE,                                                                  // 1005
+               NEURONSPI_REGFUN_SERIAL_NR_UPPER | NEURONSPI_REGFLAG_ACC_ONCE,                                                                  // 1006
+               NEURONSPI_REGFUN_INTERRUPTS | NEURONSPI_REGFLAG_ACC_AFAP,                                                                               // 1007
+               NEURONSPI_REGFUN_MWD_TO | NEURONSPI_REGFLAG_ACC_6SEC,                                                                                   // 1008
+               NEURONSPI_REGFUN_V_REF_INT | NEURONSPI_REGFLAG_ACC_ONCE,                                                                                // 1009
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1010
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1011
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1012
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1013
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1014
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1015
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1016
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1017
+               NEURONSPI_REGFUN_DS_ENABLE   | NEURONSPI_REGFLAG_ACC_1HZ,                                                                               // 1018
+               NEURONSPI_REGFUN_DS_POLARITY | NEURONSPI_REGFLAG_ACC_1HZ,                                                                               // 1019
+               NEURONSPI_REGFUN_DS_TOGGLE   | NEURONSPI_REGFLAG_ACC_1HZ,                                                                               // 1020
+               NEURONSPI_REGFUN_RS485_CONFIG | NEURONSPI_REGFLAG_ACC_6SEC,                                                                             // 1021
+               NEURONSPI_REGFUN_RS485_ADDRESS | NEURONSPI_REGFLAG_ACC_6SEC                                                                             // 1022
+};
+
+#define NEURONSPI_BOARD_E8DI8ROP11DIR485_HW_FEATURES { \
+               .do_count =                                       0,    \
+               .ro_count =                                       8,    \
+               .ds_count =                                       8,    \
+               .di_count =                                       8,    \
+               .led_count =                              0,    \
+               .stm_ai_count =                           0,    \
+               .stm_ao_count =                           0,    \
+               .sec_ai_count =                           0,    \
+               .sec_ao_count =                           0,    \
+               .uart_master_count =              0,    \
+               .uart_slave_count =               1,    \
+               .pwm_channel_count =              0,    \
+               .wd_count =                               1,    \
+               .extension_sys_count =            1,    \
+               .light_count =                            0,    \
+               .owire_count =                            0,    \
+}
+
+#define NEURONSPI_BOARD_E8DI8ROP11DIR485_HW_DEFINITION { \
+               .combination_board_id =         4, \
+               .lower_board_id =                       NEURONSPI_BOARD_LOWER_E8DI8RO_ID, \
+               .upper_board_id =                       NEURONSPI_BOARD_UPPER_P11DIR485_ID, \
+               .block_count =                          NEURONSPI_BOARD_E8DI8ROP11DIR485_HW_DEFINITION_BLOCK_SIZE, \
+               .name_length =                          19, \
+               .combination_name =                     "E_8Di8Ro_P_11DiR485", \
+               .blocks =                                       NEURONSPI_BOARD_E8DI8ROP11DIR485_HW_DEFINITION_BLOCK, \
+               .features =                                     NEURONSPI_BOARD_E8DI8ROP11DIR485_HW_FEATURES \
+}
+static struct neuronspi_board_combination NEURONSPI_BOARD_E8DI8ROP11DIR485_HW_COMBINATION[] = {NEURONSPI_BOARD_E8DI8ROP11DIR485_HW_DEFINITION};
+
+// E-14Ro_P-11DiR485 (xS40)
+#define NEURONSPI_BOARD_E14ROP11DIR485_HW_DEFINITION_BLOCK_SIZE 71
+static u32 NEURONSPI_BOARD_E14ROP11DIR485_HW_DEFINITION_BLOCK[NEURONSPI_BOARD_E14ROP11DIR485_HW_DEFINITION_BLOCK_SIZE] = {
+               0, 36,  // Register block beginning and size
+               NEURONSPI_REGFUN_DI_READ | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY,                // 0
+               NEURONSPI_REGFUN_DO_RW | NEURONSPI_REGFLAG_ACC_10HZ,                                                                                    // 1
+               NEURONSPI_REGFUN_MWD_STATUS | NEURONSPI_REGFLAG_ACC_6SEC | NEURONSPI_REGFLAG_SYS_READ_ONLY,     // 2
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 3
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 4
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 5
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 6
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 7
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 8
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 9
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 10
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 11
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 12
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 13
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 14
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 15
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 16
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 17
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 18
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 19
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 20
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 21
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 22
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 23
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 24
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 25
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 26
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 27
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 28
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 29
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 30
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 31
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 32
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 33
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 34
+               NEURONSPI_REGFUN_LED_RW | NEURONSPI_REGFLAG_ACC_1HZ,                                                                    // 35
+               1000, 31, // Register block beginning and size
+               NEURONSPI_REGFUN_SW_VER | NEURONSPI_REGFLAG_ACC_ONCE,                                                                                   // 1000
+               NEURONSPI_REGFUN_DIDO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE,                                                                               // 1001
+               NEURONSPI_REGFUN_UAIO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE,                                                                               // 1002
+               NEURONSPI_REGFUN_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE,                                                                                   // 1003
+               NEURONSPI_REGFUN_FLASH_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE,                                                                     // 1004
+               NEURONSPI_REGFUN_SERIAL_NR_LOWER | NEURONSPI_REGFLAG_ACC_ONCE,                                                                  // 1005
+               NEURONSPI_REGFUN_SERIAL_NR_UPPER | NEURONSPI_REGFLAG_ACC_ONCE,                                                                  // 1006
+               NEURONSPI_REGFUN_INTERRUPTS | NEURONSPI_REGFLAG_ACC_AFAP,                                                                               // 1007
+               NEURONSPI_REGFUN_MWD_TO | NEURONSPI_REGFLAG_ACC_6SEC,                                                                                   // 1008
+               NEURONSPI_REGFUN_V_REF_INT | NEURONSPI_REGFLAG_ACC_ONCE,                                                                                // 1009
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1010
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1011
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1012
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1013
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1014
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1015
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1016
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1017
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1018
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1019
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1020
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1021
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1022
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1023
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1024
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1025
+               NEURONSPI_REGFUN_DS_ENABLE | NEURONSPI_REGFLAG_ACC_1HZ,                                                                                 // 1026
+               NEURONSPI_REGFUN_DS_POLARITY | NEURONSPI_REGFLAG_ACC_1HZ,                                                                               // 1027
+               NEURONSPI_REGFUN_DS_TOGGLE | NEURONSPI_REGFLAG_ACC_1HZ,                                                                                 // 1028
+               NEURONSPI_REGFUN_RS485_CONFIG | NEURONSPI_REGFLAG_ACC_6SEC,                                                                             // 1029
+               NEURONSPI_REGFUN_RS485_ADDRESS | NEURONSPI_REGFLAG_ACC_6SEC                                                                             // 1030
+};
+
+#define NEURONSPI_BOARD_E14ROP11DIR485_HW_FEATURES {   \
+               .do_count =                                       0,    \
+               .ro_count =                                       14,   \
+               .ds_count =                                       8,    \
+               .di_count =                                       8,    \
+               .led_count =                              0,    \
+               .stm_ai_count =                           0,    \
+               .stm_ao_count =                           0,    \
+               .sec_ai_count =                           0,    \
+               .sec_ao_count =                           0,    \
+               .uart_master_count =              0,    \
+               .uart_slave_count =               1,    \
+               .pwm_channel_count =              0,    \
+               .wd_count =                               1,    \
+               .extension_sys_count =            1,    \
+               .light_count =                            0,    \
+               .owire_count =                            0,    \
+}
+
+#define NEURONSPI_BOARD_E14ROP11DIR485_HW_DEFINITION { \
+               .combination_board_id =         5, \
+               .lower_board_id =                       NEURONSPI_BOARD_LOWER_E14RO_ID, \
+               .upper_board_id =                       NEURONSPI_BOARD_UPPER_P11DIR485_ID, \
+               .name_length =                          17, \
+               .combination_name =                     "E_14Ro_P_11DiR485", \
+               .block_count =                          NEURONSPI_BOARD_E14ROP11DIR485_HW_DEFINITION_BLOCK_SIZE, \
+               .blocks =                                       NEURONSPI_BOARD_E14ROP11DIR485_HW_DEFINITION_BLOCK, \
+               .features =                                     NEURONSPI_BOARD_E14ROP11DIR485_HW_FEATURES \
+}
+static struct neuronspi_board_combination NEURONSPI_BOARD_E14ROP11DIR485_HW_COMBINATION[] = {NEURONSPI_BOARD_E14ROP11DIR485_HW_DEFINITION};
+
+// E-16Di_P-11DiR485 (xS30)
+#define NEURONSPI_BOARD_E16DIP11DIR485_HW_DEFINITION_BLOCK_SIZE 92
+static u32 NEURONSPI_BOARD_E16DIP11DIR485_HW_DEFINITION_BLOCK[NEURONSPI_BOARD_E16DIP11DIR485_HW_DEFINITION_BLOCK_SIZE] = {
+               0, 52,  // Register block beginning and size
+               NEURONSPI_REGFUN_DI_READ | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY,                // 0
+               NEURONSPI_REGFUN_DI_READ | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY,                // 1
+               NEURONSPI_REGFUN_MWD_STATUS | NEURONSPI_REGFLAG_ACC_6SEC,                                                                               // 2
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 3
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 4
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 5
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 6
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 7
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 8
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 9
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 10
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 11
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 12
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 13
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 14
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 15
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 16
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 17
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 18
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 19
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 20
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 21
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 22
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 23
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 24
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 25
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 26
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 27
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 28
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 29
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 30
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 31
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 32
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 33
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 34
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 35
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 36
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 37
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 38
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 39
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 40
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 41
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 42
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 43
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 44
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 45
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 46
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 47
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 48
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 49
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 50
+               NEURONSPI_REGFUN_LED_RW | NEURONSPI_REGFLAG_ACC_1HZ,                                                                                    // 51
+               1000, 36, // Register block beginning and size
+               NEURONSPI_REGFUN_SW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,                 // 1000
+               NEURONSPI_REGFUN_DIDO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,             // 1001
+               NEURONSPI_REGFUN_UAIO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,             // 1002
+               NEURONSPI_REGFUN_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,                 // 1003
+               NEURONSPI_REGFUN_FLASH_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,   // 1004
+               NEURONSPI_REGFUN_SERIAL_NR_LOWER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1005
+               NEURONSPI_REGFUN_SERIAL_NR_UPPER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1006
+               NEURONSPI_REGFUN_INTERRUPTS | NEURONSPI_REGFLAG_ACC_AFAP,                                                                               // 1007
+               NEURONSPI_REGFUN_MWD_TO | NEURONSPI_REGFLAG_ACC_6SEC,                                                                                   // 1008
+               NEURONSPI_REGFUN_V_REF_INT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,              // 1009
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1010
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1011
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1012
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1013
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1014
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1015
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1016
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1017
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1018
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1019
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1020
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1021
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1022
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1023
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1024
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1025
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1026
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1027
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1028
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1029
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1030
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1031
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1032
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1033
+               NEURONSPI_REGFUN_RS485_CONFIG | NEURONSPI_REGFLAG_ACC_6SEC,                                                                             // 1034
+               NEURONSPI_REGFUN_RS485_ADDRESS | NEURONSPI_REGFLAG_ACC_6SEC                                                                             // 1035
+};
+
+#define NEURONSPI_BOARD_E16DIP11DIR485_HW_FEATURES {   \
+               .do_count =                                       0,    \
+               .ro_count =                                       0,    \
+               .ds_count =                                       0,    \
+               .di_count =                                       23,   \
+               .led_count =                              0,    \
+               .stm_ai_count =                           0,    \
+               .stm_ao_count =                           0,    \
+               .sec_ai_count =                           0,    \
+               .sec_ao_count =                           0,    \
+               .uart_master_count =              0,    \
+               .uart_slave_count =               1,    \
+               .pwm_channel_count =              0,    \
+               .wd_count =                               1,    \
+               .extension_sys_count =            1,    \
+               .light_count =                            0,    \
+               .owire_count =                            0,    \
+}
+
+#define NEURONSPI_BOARD_E16DIP11DIR485_HW_DEFINITION { \
+               .combination_board_id =         6, \
+               .lower_board_id =                       NEURONSPI_BOARD_LOWER_E16DI_ID, \
+               .upper_board_id =                       NEURONSPI_BOARD_UPPER_P11DIR485_ID, \
+               .name_length =                          17, \
+               .combination_name =                     "E_16Di_P_11DiR485", \
+               .block_count =                          NEURONSPI_BOARD_E16DIP11DIR485_HW_DEFINITION_BLOCK_SIZE, \
+               .blocks =                                       NEURONSPI_BOARD_E16DIP11DIR485_HW_DEFINITION_BLOCK, \
+               .features =                                     NEURONSPI_BOARD_E16DIP11DIR485_HW_FEATURES \
+}
+static struct neuronspi_board_combination NEURONSPI_BOARD_E16DIP11DIR485_HW_COMBINATION[] = {NEURONSPI_BOARD_E16DIP11DIR485_HW_DEFINITION};
+
+// E-14Ro_U-14Ro (M403)
+#define NEURONSPI_BOARD_E14ROU14RO_HW_DEFINITION_BLOCK_SIZE 17
+static u32 NEURONSPI_BOARD_E14ROU14RO_HW_DEFINITION_BLOCK[NEURONSPI_BOARD_E14ROU14RO_HW_DEFINITION_BLOCK_SIZE] = {
+               0, 3,   // Register block beginning and size
+               NEURONSPI_REGFUN_DO_RW | NEURONSPI_REGFLAG_ACC_10HZ,                                                                                    // 0
+               NEURONSPI_REGFUN_DO_RW | NEURONSPI_REGFLAG_ACC_10HZ,                                                                                    // 1
+               NEURONSPI_REGFUN_MWD_STATUS | NEURONSPI_REGFLAG_ACC_6SEC | NEURONSPI_REGFLAG_SYS_READ_ONLY,     // 2
+               1000, 10, // Register block beginning and size
+               NEURONSPI_REGFUN_SW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,                 // 1000
+               NEURONSPI_REGFUN_DIDO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,             // 1001
+               NEURONSPI_REGFUN_UAIO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,             // 1002
+               NEURONSPI_REGFUN_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,                 // 1003
+               NEURONSPI_REGFUN_FLASH_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,   // 1004
+               NEURONSPI_REGFUN_SERIAL_NR_LOWER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1005
+               NEURONSPI_REGFUN_SERIAL_NR_UPPER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1006
+               NEURONSPI_REGFUN_INTERRUPTS | NEURONSPI_REGFLAG_ACC_AFAP,                                                                               // 1007
+               NEURONSPI_REGFUN_MWD_TO | NEURONSPI_REGFLAG_ACC_6SEC,                                                                                   // 1008
+               NEURONSPI_REGFUN_V_REF_INT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,              // 1009
+};
+
+#define NEURONSPI_BOARD_E14ROU14RO_HW_FEATURES {       \
+               .do_count =                                       0,    \
+               .ro_count =                                       28,   \
+               .ds_count =                                       0,    \
+               .di_count =                                       0,    \
+               .led_count =                              0,    \
+               .stm_ai_count =                           0,    \
+               .stm_ao_count =                           0,    \
+               .sec_ai_count =                           0,    \
+               .sec_ao_count =                           0,    \
+               .uart_master_count =              0,    \
+               .uart_slave_count =               0,    \
+               .pwm_channel_count =              0,    \
+               .wd_count =                               1,    \
+               .extension_sys_count =            1,    \
+               .light_count =                            0,    \
+               .owire_count =                            0,    \
+}
+
+#define NEURONSPI_BOARD_E14ROU14RO_HW_DEFINITION { \
+               .combination_board_id =         7, \
+               .lower_board_id =                       NEURONSPI_BOARD_LOWER_E14RO_ID, \
+               .upper_board_id =                       NEURONSPI_BOARD_UPPER_U14RO_ID, \
+               .name_length =                          13, \
+               .combination_name =                     "E_14Ro_U_14Ro", \
+               .block_count =                          NEURONSPI_BOARD_E14ROU14RO_HW_DEFINITION_BLOCK_SIZE, \
+               .blocks =                                       NEURONSPI_BOARD_E14ROU14RO_HW_DEFINITION_BLOCK, \
+               .features =                             NEURONSPI_BOARD_E14ROU14RO_HW_FEATURES \
+}
+static struct neuronspi_board_combination NEURONSPI_BOARD_E14ROU14RO_HW_COMBINATION[] = {NEURONSPI_BOARD_E14ROU14RO_HW_DEFINITION};
+
+// E-16Di_U-14Ro (M203)
+#define NEURONSPI_BOARD_E16DIU14RO_HW_DEFINITION_BLOCK_SIZE 68
+static u32 NEURONSPI_BOARD_E16DIU14RO_HW_DEFINITION_BLOCK[NEURONSPI_BOARD_E16DIU14RO_HW_DEFINITION_BLOCK_SIZE] = {
+               0, 35,  // Register block beginning and size
+               NEURONSPI_REGFUN_DI_READ | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY,                // 0
+               NEURONSPI_REGFUN_DO_RW | NEURONSPI_REGFLAG_ACC_10HZ,                                                                                    // 1
+               NEURONSPI_REGFUN_MWD_STATUS | NEURONSPI_REGFLAG_ACC_6SEC | NEURONSPI_REGFLAG_SYS_READ_ONLY,     // 2
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 3
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 4
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 5
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 6
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 7
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 8
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 9
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 10
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 11
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 12
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 13
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 14
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 15
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 16
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 17
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 18
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 19
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 20
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 21
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 22
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 23
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 24
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 25
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 26
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 27
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 28
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 29
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 30
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 31
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 32
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 33
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 34
+               1000, 29, // Register block beginning and size
+               NEURONSPI_REGFUN_SW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,                 // 1000
+               NEURONSPI_REGFUN_DIDO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,             // 1001
+               NEURONSPI_REGFUN_UAIO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,             // 1002
+               NEURONSPI_REGFUN_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,                 // 1003
+               NEURONSPI_REGFUN_FLASH_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,   // 1004
+               NEURONSPI_REGFUN_SERIAL_NR_LOWER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1005
+               NEURONSPI_REGFUN_SERIAL_NR_UPPER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1006
+               NEURONSPI_REGFUN_INTERRUPTS | NEURONSPI_REGFLAG_ACC_AFAP,                                                                               // 1007
+               NEURONSPI_REGFUN_MWD_TO | NEURONSPI_REGFLAG_ACC_6SEC,                                                                                   // 1008
+               NEURONSPI_REGFUN_V_REF_INT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,              // 1009
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1010
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1011
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1012
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1013
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1014
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1015
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1016
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1017
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1018
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1019
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1020
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1021
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1022
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1023
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1024
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1025
+               NEURONSPI_REGFUN_DS_ENABLE | NEURONSPI_REGFLAG_ACC_1HZ,                                                                                 // 1026
+               NEURONSPI_REGFUN_DS_POLARITY | NEURONSPI_REGFLAG_ACC_1HZ,                                                                               // 1027
+               NEURONSPI_REGFUN_DS_TOGGLE | NEURONSPI_REGFLAG_ACC_1HZ,                                                                                 // 1028
+};
+
+#define NEURONSPI_BOARD_E16DIU14RO_HW_FEATURES {       \
+               .do_count =                                       0,    \
+               .ro_count =                                       14,   \
+               .ds_count =                                       14,   \
+               .di_count =                                       16,   \
+               .led_count =                              0,    \
+               .stm_ai_count =                           0,    \
+               .stm_ao_count =                           0,    \
+               .sec_ai_count =                           0,    \
+               .sec_ao_count =                           0,    \
+               .uart_master_count =              0,    \
+               .uart_slave_count =               0,    \
+               .pwm_channel_count =              0,    \
+               .wd_count =                               1,    \
+               .extension_sys_count =            0,    \
+               .light_count =                            0,    \
+               .owire_count =                            0,    \
+}
+
+#define NEURONSPI_BOARD_E16DIU14RO_HW_DEFINITION { \
+               .combination_board_id =         8, \
+               .lower_board_id =                       NEURONSPI_BOARD_LOWER_E16DI_ID, \
+               .upper_board_id =                       NEURONSPI_BOARD_UPPER_U14RO_ID, \
+               .name_length =                          13, \
+               .combination_name =                     "E_16Di_U_14Ro", \
+               .block_count =                          NEURONSPI_BOARD_E16DIU14RO_HW_DEFINITION_BLOCK_SIZE, \
+               .blocks =                                       NEURONSPI_BOARD_E16DIU14RO_HW_DEFINITION_BLOCK, \
+               .features =                                     NEURONSPI_BOARD_E16DIU14RO_HW_FEATURES \
+}
+static struct neuronspi_board_combination NEURONSPI_BOARD_E16DIU14RO_HW_COMBINATION[] = {NEURONSPI_BOARD_E16DIU14RO_HW_DEFINITION};
+
+// E-14Ro_U-14Di (L503)
+#define NEURONSPI_BOARD_E14ROU14DI_HW_DEFINITION_BLOCK_SIZE 62
+static u32 NEURONSPI_BOARD_E14ROU14DI_HW_DEFINITION_BLOCK[NEURONSPI_BOARD_E14ROU14DI_HW_DEFINITION_BLOCK_SIZE] = {
+               0, 31,  // Register block beginning and size
+               NEURONSPI_REGFUN_DI_READ | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY,                // 0
+               NEURONSPI_REGFUN_DO_RW | NEURONSPI_REGFLAG_ACC_10HZ,                                                                                    // 1
+               NEURONSPI_REGFUN_MWD_STATUS | NEURONSPI_REGFLAG_ACC_6SEC | NEURONSPI_REGFLAG_SYS_READ_ONLY,     // 2
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 3
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 4
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 5
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 6
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 7
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 8
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 9
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 10
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 11
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 12
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 13
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 14
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 15
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 16
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 17
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 18
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 19
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 20
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 21
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 22
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 23
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 24
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 25
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 26
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 27
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 28
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 29
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 30
+               1000, 27, // Register block beginning and size
+               NEURONSPI_REGFUN_SW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,                 // 1000
+               NEURONSPI_REGFUN_DIDO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,             // 1001
+               NEURONSPI_REGFUN_UAIO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,             // 1002
+               NEURONSPI_REGFUN_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,                 // 1003
+               NEURONSPI_REGFUN_FLASH_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,   // 1004
+               NEURONSPI_REGFUN_SERIAL_NR_LOWER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1005
+               NEURONSPI_REGFUN_SERIAL_NR_UPPER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1006
+               NEURONSPI_REGFUN_INTERRUPTS | NEURONSPI_REGFLAG_ACC_AFAP,                                                                               // 1007
+               NEURONSPI_REGFUN_MWD_TO | NEURONSPI_REGFLAG_ACC_6SEC,                                                                                   // 1008
+               NEURONSPI_REGFUN_V_REF_INT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,              // 1009
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1010
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1011
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1012
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1013
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1014
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1015
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1016
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1017
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1018
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1019
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1020
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1021
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1022
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1023
+               NEURONSPI_REGFUN_DS_ENABLE | NEURONSPI_REGFLAG_ACC_1HZ,                                                                                 // 1024
+               NEURONSPI_REGFUN_DS_POLARITY | NEURONSPI_REGFLAG_ACC_1HZ,                                                                               // 1025
+               NEURONSPI_REGFUN_DS_TOGGLE | NEURONSPI_REGFLAG_ACC_1HZ                                                                                  // 1026
+};
+
+#define NEURONSPI_BOARD_E14ROU14DI_HW_FEATURES {       \
+               .do_count =                                       0,    \
+               .ro_count =                                       14,   \
+               .ds_count =                                       14,   \
+               .di_count =                                       14,   \
+               .led_count =                              0,    \
+               .stm_ai_count =                           0,    \
+               .stm_ao_count =                           0,    \
+               .sec_ai_count =                           0,    \
+               .sec_ao_count =                           0,    \
+               .uart_master_count =              0,    \
+               .uart_slave_count =               0,    \
+               .pwm_channel_count =              0,    \
+               .wd_count =                               1,    \
+               .extension_sys_count =            0,    \
+               .light_count =                            0,    \
+               .owire_count =                            0,    \
+}
+
+#define NEURONSPI_BOARD_E14ROU14DI_HW_DEFINITION { \
+               .combination_board_id =         9, \
+               .lower_board_id =                       NEURONSPI_BOARD_LOWER_E14RO_ID, \
+               .upper_board_id =                       NEURONSPI_BOARD_UPPER_U14DI_ID, \
+               .name_length =                          13, \
+               .combination_name =                     "E_14Ro_U_14Di", \
+               .block_count =                          NEURONSPI_BOARD_E14ROU14DI_HW_DEFINITION_BLOCK_SIZE, \
+               .blocks =                                       NEURONSPI_BOARD_E14ROU14DI_HW_DEFINITION_BLOCK, \
+               .features =                                     NEURONSPI_BOARD_E14ROU14DI_HW_FEATURES \
+}
+static struct neuronspi_board_combination NEURONSPI_BOARD_E14ROU14DI_HW_COMBINATION[] = {NEURONSPI_BOARD_E14ROU14DI_HW_DEFINITION};
+
+
+// E-16Di_U-14Di (M303)
+#define NEURONSPI_BOARD_E16DIU14DI_HW_DEFINITION_BLOCK_SIZE 107
+static u32 NEURONSPI_BOARD_E16DIU14DI_HW_DEFINITION_BLOCK[NEURONSPI_BOARD_E16DIU14DI_HW_DEFINITION_BLOCK_SIZE] = {
+               0, 63,  // Register block beginning and size
+               NEURONSPI_REGFUN_DI_READ | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY,                // 0
+               NEURONSPI_REGFUN_DO_RW | NEURONSPI_REGFLAG_ACC_10HZ,                                                                                    // 1
+               NEURONSPI_REGFUN_MWD_STATUS | NEURONSPI_REGFLAG_ACC_6SEC | NEURONSPI_REGFLAG_SYS_READ_ONLY,     // 2
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 3
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 4
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 5
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 6
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 7
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 8
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 9
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 10
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 11
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 12
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 13
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 14
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 15
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 16
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 17
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 18
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 19
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 20
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 21
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 22
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 23
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 24
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 25
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 26
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 27
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 28
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 29
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 30
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 31
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 32
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 33
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 34
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 35
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 36
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 37
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 38
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 39
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 40
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 41
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 42
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 43
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 44
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 45
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 46
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 47
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 48
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 49
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 50
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 51
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 52
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 53
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 54
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 55
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 56
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 57
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 58
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 59
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 60
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 61
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 62
+               1000, 40, // Register block beginning and size
+               NEURONSPI_REGFUN_SW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,                 // 1000
+               NEURONSPI_REGFUN_DIDO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,             // 1001
+               NEURONSPI_REGFUN_UAIO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,             // 1002
+               NEURONSPI_REGFUN_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,                 // 1003
+               NEURONSPI_REGFUN_FLASH_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,   // 1004
+               NEURONSPI_REGFUN_SERIAL_NR_LOWER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1005
+               NEURONSPI_REGFUN_SERIAL_NR_UPPER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1006
+               NEURONSPI_REGFUN_INTERRUPTS | NEURONSPI_REGFLAG_ACC_AFAP,                                                                               // 1007
+               NEURONSPI_REGFUN_MWD_TO | NEURONSPI_REGFLAG_ACC_6SEC,                                                                                   // 1008
+               NEURONSPI_REGFUN_V_REF_INT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,              // 1009
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1010
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1011
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1012
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1013
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1014
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1015
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1016
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1017
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1018
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1019
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1020
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1021
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1022
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1023
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1024
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1025
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1026
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1027
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1028
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1029
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1030
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1031
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1032
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1033
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1034
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1035
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1036
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1037
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1038
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1039
+};
+
+#define NEURONSPI_BOARD_E16DIU14DI_HW_FEATURES {       \
+               .do_count =                                       0,    \
+               .ro_count =                                       0,    \
+               .ds_count =                                       0,    \
+               .di_count =                                       30,   \
+               .led_count =                              0,    \
+               .stm_ai_count =                           0,    \
+               .stm_ao_count =                           0,    \
+               .sec_ai_count =                           0,    \
+               .sec_ao_count =                           0,    \
+               .uart_master_count =              0,    \
+               .uart_slave_count =               0,    \
+               .pwm_channel_count =              0,    \
+               .wd_count =                               1,    \
+               .extension_sys_count =            0,    \
+               .light_count =                            0,    \
+               .owire_count =                            0,    \
+}
+
+#define NEURONSPI_BOARD_E16DIU14DI_HW_DEFINITION { \
+               .combination_board_id =         10, \
+               .lower_board_id =                       NEURONSPI_BOARD_LOWER_E16DI_ID, \
+               .upper_board_id =                       NEURONSPI_BOARD_UPPER_U14DI_ID, \
+               .name_length =                          13, \
+               .combination_name =                     "E_16Di_U_14Di", \
+               .block_count =                          NEURONSPI_BOARD_E16DIU14DI_HW_DEFINITION_BLOCK_SIZE, \
+               .blocks =                                       NEURONSPI_BOARD_E16DIU14DI_HW_DEFINITION_BLOCK, \
+               .features =                                     NEURONSPI_BOARD_E16DIU14DI_HW_FEATURES \
+}
+static struct neuronspi_board_combination NEURONSPI_BOARD_E16DIU14DI_HW_COMBINATION[] = {NEURONSPI_BOARD_E16DIU14DI_HW_DEFINITION};
+
+// E-4Ai4Ao
+#define NEURONSPI_BOARD_E4AI4AO_HW_DEFINITION_BLOCK_SIZE 15
+static u32 NEURONSPI_BOARD_E4AI4AO_HW_DEFINITION_BLOCK[NEURONSPI_BOARD_E4AI4AO_HW_DEFINITION_BLOCK_SIZE] = {
+               0, 1,   // Register block beginning and size
+               NEURONSPI_REGFUN_DO_RW | NEURONSPI_REGFLAG_ACC_10HZ | NEURONSPI_REGFLAG_SYS_READ_ONLY,                  // 0
+               1000, 10, // Register block beginning and size
+               NEURONSPI_REGFUN_SW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,                 // 1000
+               NEURONSPI_REGFUN_DIDO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,             // 1001
+               NEURONSPI_REGFUN_UAIO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,             // 1002
+               NEURONSPI_REGFUN_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,                 // 1003
+               NEURONSPI_REGFUN_FLASH_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,   // 1004
+               NEURONSPI_REGFUN_SERIAL_NR_LOWER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1005
+               NEURONSPI_REGFUN_SERIAL_NR_UPPER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1006
+               NEURONSPI_REGFUN_INTERRUPTS | NEURONSPI_REGFLAG_ACC_AFAP,                                                                               // 1007
+               NEURONSPI_REGFUN_MWD_TO | NEURONSPI_REGFLAG_ACC_6SEC,                                                                                   // 1008
+               NEURONSPI_REGFUN_V_REF_INT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,              // 1009
+};
+
+#define NEURONSPI_BOARD_E4AI4AO_HW_FEATURES {  \
+               .do_count =                                       0,    \
+               .ro_count =                                       0,    \
+               .ds_count =                                       0,    \
+               .di_count =                                       0,    \
+               .led_count =                              0,    \
+               .stm_ai_count =                           0,    \
+               .stm_ao_count =                           0,    \
+               .sec_ai_count =                           4,    \
+               .sec_ao_count =                           4,    \
+               .uart_master_count =              0,    \
+               .uart_slave_count =               0,    \
+               .pwm_channel_count =              0,    \
+               .wd_count =                               1,    \
+               .extension_sys_count =            0,    \
+               .light_count =                            0,    \
+               .owire_count =                            0,    \
+}
+
+
+#define NEURONSPI_BOARD_E4AI4AO_HW_DEFINITION { \
+               .combination_board_id =         11, \
+               .lower_board_id =                       NEURONSPI_BOARD_LOWER_E4AI4AO_ID, \
+               .upper_board_id =                       NEURONSPI_BOARD_UPPER_NONE_ID, \
+               .name_length =                          8, \
+               .combination_name =                     "E_4Ai4Ao", \
+               .block_count =                          NEURONSPI_BOARD_E4AI4AO_HW_DEFINITION_BLOCK_SIZE, \
+               .blocks =                                       NEURONSPI_BOARD_E4AI4AO_HW_DEFINITION_BLOCK, \
+               .features =                                     NEURONSPI_BOARD_E4AI4AO_HW_FEATURES \
+}
+static struct neuronspi_board_combination NEURONSPI_BOARD_E4AI4AO_HW_COMBINATION[] = {NEURONSPI_BOARD_E4AI4AO_HW_DEFINITION};
+
+// E-4Ai4Ao_P-6Di5Ro (xS50)
+#define NEURONSPI_BOARD_E4AI4AOP6DI5RO_HW_DEFINITION_BLOCK_SIZE 56
+static u32 NEURONSPI_BOARD_E4AI4AOP6DI5RO_HW_DEFINITION_BLOCK[NEURONSPI_BOARD_E4AI4AOP6DI5RO_HW_DEFINITION_BLOCK_SIZE] = {
+               0, 27,  // Register block beginning and size
+               NEURONSPI_REGFUN_DI_READ | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY,                        // 0
+               NEURONSPI_REGFUN_DO_RW | NEURONSPI_REGFLAG_ACC_10HZ,                                                                                            // 1
+               NEURONSPI_REGFUN_AO_VER2_RW | NEURONSPI_REGFLAG_ACC_10HZ,                                                                                       // 2
+               NEURONSPI_REGFUN_AO_VER2_RW | NEURONSPI_REGFLAG_ACC_10HZ,                                                                                       // 3
+               NEURONSPI_REGFUN_AO_VER2_RW | NEURONSPI_REGFLAG_ACC_10HZ,                                                                                       // 4
+               NEURONSPI_REGFUN_AO_VER2_RW | NEURONSPI_REGFLAG_ACC_10HZ,                                                                                       // 5
+               NEURONSPI_REGFUN_AI_VER2_READ_LOWER | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY,     // 6
+               NEURONSPI_REGFUN_AI_VER2_READ_UPPER | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY,     // 7
+               NEURONSPI_REGFUN_AI_VER2_READ_LOWER | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY,     // 8
+               NEURONSPI_REGFUN_AI_VER2_READ_UPPER | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY,     // 9
+               NEURONSPI_REGFUN_AI_VER2_READ_LOWER | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY,     // 10
+               NEURONSPI_REGFUN_AI_VER2_READ_UPPER | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY,     // 11
+               NEURONSPI_REGFUN_AI_VER2_READ_LOWER | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY,     // 12
+               NEURONSPI_REGFUN_AI_VER2_READ_UPPER | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY,     // 13
+               NEURONSPI_REGFUN_MWD_STATUS | NEURONSPI_REGFLAG_ACC_6SEC,                                                                                       // 14
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                         // 15
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                         // 16
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                         // 17
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                         // 18
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                         // 19
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                         // 20
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                         // 21
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                         // 22
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                         // 23
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                         // 24
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                         // 25
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                         // 26
+               1000, 25, // Register block beginning and size
+               NEURONSPI_REGFUN_SW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,                 // 1000
+               NEURONSPI_REGFUN_DIDO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,             // 1001
+               NEURONSPI_REGFUN_UAIO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,             // 1002
+               NEURONSPI_REGFUN_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,                 // 1003
+               NEURONSPI_REGFUN_FLASH_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,   // 1004
+               NEURONSPI_REGFUN_SERIAL_NR_LOWER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1005
+               NEURONSPI_REGFUN_SERIAL_NR_UPPER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1006
+               NEURONSPI_REGFUN_INTERRUPTS | NEURONSPI_REGFLAG_ACC_AFAP,                                                                               // 1007
+               NEURONSPI_REGFUN_MWD_TO | NEURONSPI_REGFLAG_ACC_6SEC,                                                                                   // 1008
+               NEURONSPI_REGFUN_V_REF_INT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,              // 1009
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1010
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1011
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1012
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1013
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1014
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1015
+               NEURONSPI_REGFUN_DS_ENABLE   | NEURONSPI_REGFLAG_ACC_1HZ,                                                                               // 1016
+               NEURONSPI_REGFUN_DS_POLARITY | NEURONSPI_REGFLAG_ACC_1HZ,                                                                               // 1017
+               NEURONSPI_REGFUN_DS_TOGGLE   | NEURONSPI_REGFLAG_ACC_1HZ,                                                                               // 1018
+               NEURONSPI_REGFUN_AI_VER2_MODE | NEURONSPI_REGFLAG_ACC_1HZ,                                                                              // 1019
+               NEURONSPI_REGFUN_AI_VER2_MODE | NEURONSPI_REGFLAG_ACC_1HZ,                                                                              // 1020
+               NEURONSPI_REGFUN_AI_VER2_MODE | NEURONSPI_REGFLAG_ACC_1HZ,                                                                              // 1021
+               NEURONSPI_REGFUN_AI_VER2_MODE | NEURONSPI_REGFLAG_ACC_1HZ,                                                                              // 1022
+               NEURONSPI_REGFUN_RS485_CONFIG | NEURONSPI_REGFLAG_ACC_6SEC,                                                                             // 1023
+               NEURONSPI_REGFUN_RS485_ADDRESS | NEURONSPI_REGFLAG_ACC_6SEC                                                                             // 1024
+};
+
+#define NEURONSPI_BOARD_E4AI4AOP6DI5RO_HW_FEATURES {   \
+               .do_count =                                       0,    \
+               .ro_count =                                       6,    \
+               .ds_count =                                       5,    \
+               .di_count =                                       5,    \
+               .led_count =                              0,    \
+               .stm_ai_count =                           0,    \
+               .stm_ao_count =                           0,    \
+               .sec_ai_count =                           4,    \
+               .sec_ao_count =                           4,    \
+               .uart_master_count =              0,    \
+               .uart_slave_count =               1,    \
+               .pwm_channel_count =              0,    \
+               .wd_count =                               1,    \
+               .extension_sys_count =            1,    \
+               .light_count =                            0,    \
+               .owire_count =                            0,    \
+}
+
+#define NEURONSPI_BOARD_E4AI4AOP6DI5RO_HW_DEFINITION { \
+               .combination_board_id =         12, \
+               .lower_board_id =                       NEURONSPI_BOARD_LOWER_E4AI4AO_ID, \
+               .upper_board_id =                       NEURONSPI_BOARD_UPPER_P6DI5RO_ID, \
+               .name_length =                          17, \
+               .combination_name =                     "E_4Ai4Ao_P_6Di5Ro", \
+               .block_count =                          NEURONSPI_BOARD_E4AI4AOP6DI5RO_HW_DEFINITION_BLOCK_SIZE, \
+               .blocks =                                       NEURONSPI_BOARD_E4AI4AOP6DI5RO_HW_DEFINITION_BLOCK, \
+               .features =                                     NEURONSPI_BOARD_E4AI4AOP6DI5RO_HW_FEATURES \
+}
+static struct neuronspi_board_combination NEURONSPI_BOARD_E4AI4AOP6DI5RO_HW_COMBINATION[] = {NEURONSPI_BOARD_E4AI4AOP6DI5RO_HW_DEFINITION};
+
+// B-485
+#define NEURONSPI_BOARD_B485_HW_DEFINITION_BLOCK_SIZE 15
+static u32 NEURONSPI_BOARD_B485_HW_DEFINITION_BLOCK[NEURONSPI_BOARD_B485_HW_DEFINITION_BLOCK_SIZE] = {
+               0, 1,   // Register block beginning and size
+               NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE,                                                                                // 0
+               1000, 10,
+               NEURONSPI_REGFUN_SW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,                 // 1000
+               NEURONSPI_REGFUN_DIDO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,             // 1001
+               NEURONSPI_REGFUN_UAIO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,             // 1002
+               NEURONSPI_REGFUN_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,                 // 1003
+               NEURONSPI_REGFUN_FLASH_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,   // 1004
+               NEURONSPI_REGFUN_SERIAL_NR_LOWER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1005
+               NEURONSPI_REGFUN_SERIAL_NR_UPPER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1006
+               NEURONSPI_REGFUN_INTERRUPTS | NEURONSPI_REGFLAG_ACC_AFAP,                                                                               // 1007
+               NEURONSPI_REGFUN_MWD_TO | NEURONSPI_REGFLAG_ACC_6SEC,                                                                                   // 1008
+               NEURONSPI_REGFUN_V_REF_INT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,              // 1009
+};
+
+#define NEURONSPI_BOARD_B485_HW_FEATURES {     \
+       .do_count =                                       0,    \
+       .ro_count =                                       0,    \
+       .ds_count =                                       0,    \
+       .di_count =                                       0,    \
+       .led_count =                              0,    \
+       .stm_ai_count =                           0,    \
+       .stm_ao_count =                           0,    \
+       .sec_ai_count =                           4,    \
+       .sec_ao_count =                           4,    \
+       .uart_master_count =              1,    \
+       .uart_slave_count =               0,    \
+       .pwm_channel_count =              0,    \
+       .wd_count =                               1,    \
+       .extension_sys_count =            0,    \
+       .light_count =                            0,    \
+       .owire_count =                            0,    \
+}
+
+#define NEURONSPI_BOARD_B485_HW_DEFINITION { \
+               .combination_board_id =         13, \
+               .lower_board_id =                       NEURONSPI_BOARD_LOWER_B485_ID, \
+               .upper_board_id =                       NEURONSPI_BOARD_UPPER_NONE_ID, \
+               .name_length =                          5, \
+               .combination_name =                     "B_485", \
+               .block_count =                          NEURONSPI_BOARD_B485_HW_DEFINITION_BLOCK_SIZE, \
+               .blocks =                                       NEURONSPI_BOARD_B485_HW_DEFINITION_BLOCK, \
+               .features =                                     NEURONSPI_BOARD_B485_HW_FEATURES \
+}
+static struct neuronspi_board_combination NEURONSPI_BOARD_B485_HW_COMBINATION[] = {NEURONSPI_BOARD_B485_HW_DEFINITION};
+
+// E-4Light (M613)
+#define NEURONSPI_BOARD_E4LIGHT_HW_DEFINITION_BLOCK_SIZE 35
+static u32 NEURONSPI_BOARD_E4LIGHT_HW_DEFINITION_BLOCK[NEURONSPI_BOARD_E4LIGHT_HW_DEFINITION_BLOCK_SIZE] = {
+               0, 21,  // Register block beginning and size
+               NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE,                                                                                // 0
+               NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE,                                                                                // 1
+               NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE,                                                                                // 2
+               NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE,                                                                                // 3
+               NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE,                                                                                // 4
+               NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE,                                                                                // 5
+               NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE,                                                                                // 6
+               NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE,                                                                                // 7
+               NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE,                                                                                // 8
+               NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE,                                                                                // 9
+               NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE,                                                                                // 10
+               NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE,                                                                                // 11
+               NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE,                                                                                // 12
+               NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE,                                                                                // 13
+               NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE,                                                                                // 14
+               NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE,                                                                                // 15
+               NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE,                                                                                // 16
+               NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE,                                                                                // 17
+               NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE,                                                                                // 18
+               NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE,                                                                                // 19
+               NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE,                                                                                // 20
+               1000, 10,
+               NEURONSPI_REGFUN_SW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,                 // 1000
+               NEURONSPI_REGFUN_DIDO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,             // 1001
+               NEURONSPI_REGFUN_UAIO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,             // 1002
+               NEURONSPI_REGFUN_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,                 // 1003
+               NEURONSPI_REGFUN_FLASH_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,   // 1004
+               NEURONSPI_REGFUN_SERIAL_NR_LOWER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1005
+               NEURONSPI_REGFUN_SERIAL_NR_UPPER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1006
+               NEURONSPI_REGFUN_INTERRUPTS | NEURONSPI_REGFLAG_ACC_AFAP,                                                                               // 1007
+               NEURONSPI_REGFUN_MWD_TO | NEURONSPI_REGFLAG_ACC_6SEC,                                                                                   // 1008
+               NEURONSPI_REGFUN_V_REF_INT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,              // 1009
+};
+
+#define NEURONSPI_BOARD_E4LIGHT_HW_FEATURES {  \
+       .do_count =                                       0,    \
+       .ro_count =                                       0,    \
+       .ds_count =                                       0,    \
+       .di_count =                                       0,    \
+       .led_count =                              0,    \
+       .stm_ai_count =                           0,    \
+       .stm_ao_count =                           0,    \
+       .sec_ai_count =                           0,    \
+       .sec_ao_count =                           0,    \
+       .uart_master_count =              0,    \
+       .uart_slave_count =               0,    \
+       .pwm_channel_count =              0,    \
+       .wd_count =                               1,    \
+       .extension_sys_count =            0,    \
+       .light_count =                            4,    \
+       .owire_count =                            0,    \
+}
+
+#define NEURONSPI_BOARD_E4LIGHT_HW_DEFINITION { \
+               .combination_board_id =         14, \
+               .lower_board_id =                       NEURONSPI_BOARD_LOWER_E4LIGHT_ID, \
+               .upper_board_id =                       NEURONSPI_BOARD_UPPER_NONE_ID, \
+               .name_length =                          8, \
+               .combination_name =                     "E_4Light", \
+               .block_count =                          NEURONSPI_BOARD_E4LIGHT_HW_DEFINITION_BLOCK_SIZE, \
+               .blocks =                                       NEURONSPI_BOARD_E4LIGHT_HW_DEFINITION_BLOCK, \
+               .features =                                     NEURONSPI_BOARD_E4LIGHT_HW_FEATURES \
+}
+static struct neuronspi_board_combination NEURONSPI_BOARD_E4LIGHT_HW_COMBINATION[] = {NEURONSPI_BOARD_E4LIGHT_HW_DEFINITION};
+
+// E-4Ai4Ao_U-6Di5Ro (L503)
+#define NEURONSPI_BOARD_E4AI4AOU6DI5RO_HW_DEFINITION_BLOCK_SIZE 56
+static u32 NEURONSPI_BOARD_E4AI4AOU6DI5RO_HW_DEFINITION_BLOCK[NEURONSPI_BOARD_E4AI4AOU6DI5RO_HW_DEFINITION_BLOCK_SIZE] = {
+               0, 28,  // Register block beginning and size
+               NEURONSPI_REGFUN_DI_READ | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY,                                // 0
+               NEURONSPI_REGFUN_DO_RW | NEURONSPI_REGFLAG_ACC_10HZ,                                                                                                    // 1
+               NEURONSPI_REGFUN_AO_VER2_RW | NEURONSPI_REGFLAG_ACC_AFAP,                                                                                               // 2
+               NEURONSPI_REGFUN_AO_VER2_RW | NEURONSPI_REGFLAG_ACC_AFAP,                                                                                               // 3
+               NEURONSPI_REGFUN_AO_VER2_RW | NEURONSPI_REGFLAG_ACC_AFAP,                                                                                               // 4
+               NEURONSPI_REGFUN_AO_VER2_RW | NEURONSPI_REGFLAG_ACC_AFAP,                                                                                               // 5
+               NEURONSPI_REGFUN_AI_VER2_READ_LOWER | NEURONSPI_REGFLAG_ACC_AFAP,       // 6
+               NEURONSPI_REGFUN_AI_VER2_READ_UPPER | NEURONSPI_REGFLAG_ACC_AFAP,       // 7
+               NEURONSPI_REGFUN_AI_VER2_READ_LOWER | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY,     // 8
+               NEURONSPI_REGFUN_AI_VER2_READ_UPPER | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY,     // 9
+               NEURONSPI_REGFUN_AI_VER2_READ_LOWER | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY,     // 10
+               NEURONSPI_REGFUN_AI_VER2_READ_UPPER | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY,     // 11
+               NEURONSPI_REGFUN_AI_VER2_READ_LOWER | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY,     // 12
+               NEURONSPI_REGFUN_AI_VER2_READ_UPPER | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY,     // 13
+               NEURONSPI_REGFUN_MWD_STATUS | NEURONSPI_REGFLAG_ACC_6SEC | NEURONSPI_REGFLAG_SYS_READ_ONLY,                     // 14
+               NEURONSPI_REGFUN_TX_QUEUE_LEN | NEURONSPI_REGFLAG_ACC_10HZ,                                                                                             // 15
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                                 // 16
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                                 // 17
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                                 // 18
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                                 // 19
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                                 // 20
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                                 // 21
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                                 // 22
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                                 // 23
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                                 // 24
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                                 // 25
+               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                                 // 26
+               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                                 // 27
+               1000, 24, // Register block beginning and size
+               NEURONSPI_REGFUN_SW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,                                 // 1000
+               NEURONSPI_REGFUN_DIDO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,                             // 1001
+               NEURONSPI_REGFUN_UAIO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,                             // 1002
+               NEURONSPI_REGFUN_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,                                 // 1003
+               NEURONSPI_REGFUN_FLASH_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,                   // 1004
+               NEURONSPI_REGFUN_SERIAL_NR_LOWER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,                // 1005
+               NEURONSPI_REGFUN_SERIAL_NR_UPPER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,                // 1006
+               NEURONSPI_REGFUN_INTERRUPTS | NEURONSPI_REGFLAG_ACC_AFAP,                                                                                               // 1007
+               NEURONSPI_REGFUN_MWD_TO | NEURONSPI_REGFLAG_ACC_6SEC,                                                                                                   // 1008
+               NEURONSPI_REGFUN_V_REF_INT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,                              // 1009
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                                              // 1010
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                                              // 1011
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                                              // 1012
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                                              // 1013
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                                              // 1014
+               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                                              // 1015
+               NEURONSPI_REGFUN_DS_ENABLE | NEURONSPI_REGFLAG_ACC_1HZ,                                                                                                 // 1016
+               NEURONSPI_REGFUN_DS_POLARITY | NEURONSPI_REGFLAG_ACC_1HZ,                                                                                               // 1017
+               NEURONSPI_REGFUN_DS_TOGGLE | NEURONSPI_REGFLAG_ACC_1HZ,                                                                                                 // 1018
+               NEURONSPI_REGFUN_AI_VER2_MODE | NEURONSPI_REGFLAG_ACC_1HZ,                                                                                              // 1019
+               NEURONSPI_REGFUN_AI_VER2_MODE | NEURONSPI_REGFLAG_ACC_1HZ,                                                                                              // 1020
+               NEURONSPI_REGFUN_AI_VER2_MODE | NEURONSPI_REGFLAG_ACC_1HZ,                                                                                              // 1021
+               NEURONSPI_REGFUN_AI_VER2_MODE | NEURONSPI_REGFLAG_ACC_1HZ,                                                                                              // 1022
+               NEURONSPI_REGFUN_RS485_CONFIG | NEURONSPI_REGFLAG_ACC_6SEC                                                                                              // 1023
+};
+
+#define NEURONSPI_BOARD_E4AI4AOU6DI5RO_HW_FEATURES {   \
+       .do_count =                                       0,    \
+       .ro_count =                                       5,    \
+       .ds_count =                                       5,    \
+       .di_count =                                       6,    \
+       .led_count =                              0,    \
+       .stm_ai_count =                           0,    \
+       .stm_ao_count =                           0,    \
+       .sec_ai_count =                           4,    \
+       .sec_ao_count =                           4,    \
+       .uart_master_count =              0,    \
+       .uart_slave_count =               0,    \
+       .pwm_channel_count =              0,    \
+       .wd_count =                               1,    \
+       .extension_sys_count =            0,    \
+       .light_count =                            4,    \
+       .owire_count =                            0,    \
+}
+
+#define NEURONSPI_BOARD_E4AI4AOU6DI5RO_HW_DEFINITION { \
+               .combination_board_id =         15, \
+               .lower_board_id =                       NEURONSPI_BOARD_LOWER_E4AI4AO_ID, \
+               .upper_board_id =                       NEURONSPI_BOARD_UPPER_U6DI5RO_ID, \
+               .name_length =                          17, \
+               .combination_name =                     "E_4Ai4Ao_U_6Di5Ro", \
+               .block_count =                          NEURONSPI_BOARD_E4AI4AOU6DI5RO_HW_DEFINITION_BLOCK_SIZE, \
+               .blocks =                                       NEURONSPI_BOARD_E4AI4AOU6DI5RO_HW_DEFINITION_BLOCK, \
+               .features =                                     NEURONSPI_BOARD_E4AI4AOU6DI5RO_HW_FEATURES \
+}
+static struct neuronspi_board_combination NEURONSPI_BOARD_E4AI4AOU6DI5RO_HW_COMBINATION[] = {NEURONSPI_BOARD_E4AI4AOU6DI5RO_HW_DEFINITION};
+
+
+/*********************
+ * Model Definitions *
+ *********************/
+
+#define NEURONSPI_MODEL_S103_HW_DEFINITION_BOARD_SIZE 1
+static struct neuronspi_board_combination NEURONSPI_MODEL_S103_HW_DEFINITION_BOARD[NEURONSPI_MODEL_S103_HW_DEFINITION_BOARD_SIZE] = {
+               NEURONSPI_BOARD_B1000_HW_DEFINITION
+};
+
+#define NEURONSPI_MODEL_S103G_HW_DEFINITION_BOARD_SIZE 1
+static struct neuronspi_board_combination NEURONSPI_MODEL_S103G_HW_DEFINITION_BOARD[NEURONSPI_MODEL_S103G_HW_DEFINITION_BOARD_SIZE] = {
+               NEURONSPI_BOARD_B1000_HW_DEFINITION
+};
+
+#define NEURONSPI_MODEL_S103IQ_HW_DEFINITION_BOARD_SIZE 1
+static struct neuronspi_board_combination NEURONSPI_MODEL_S103IQ_HW_DEFINITION_BOARD[NEURONSPI_MODEL_S103IQ_HW_DEFINITION_BOARD_SIZE] = {
+               NEURONSPI_BOARD_B1000_HW_DEFINITION
+};
+
+#define NEURONSPI_MODEL_S103EO_HW_DEFINITION_BOARD_SIZE 1
+static struct neuronspi_board_combination NEURONSPI_MODEL_S103EO_HW_DEFINITION_BOARD[NEURONSPI_MODEL_S103EO_HW_DEFINITION_BOARD_SIZE] = {
+               NEURONSPI_BOARD_B1000_HW_DEFINITION
+};
+
+#define NEURONSPI_MODEL_M103_HW_DEFINITION_BOARD_SIZE 2
+static struct neuronspi_board_combination NEURONSPI_MODEL_M103_HW_DEFINITION_BOARD[NEURONSPI_MODEL_M103_HW_DEFINITION_BOARD_SIZE] = {
+               NEURONSPI_BOARD_B1000_HW_DEFINITION, NEURONSPI_BOARD_E8DI8RO_HW_DEFINITION
+};
+
+#define NEURONSPI_MODEL_M203_HW_DEFINITION_BOARD_SIZE 2
+static struct neuronspi_board_combination NEURONSPI_MODEL_M203_HW_DEFINITION_BOARD[NEURONSPI_MODEL_M203_HW_DEFINITION_BOARD_SIZE] = {
+               NEURONSPI_BOARD_B1000_HW_DEFINITION, NEURONSPI_BOARD_E16DIU14RO_HW_DEFINITION
+};
+
+#define NEURONSPI_MODEL_M303_HW_DEFINITION_BOARD_SIZE 2
+static struct neuronspi_board_combination NEURONSPI_MODEL_M303_HW_DEFINITION_BOARD[NEURONSPI_MODEL_M303_HW_DEFINITION_BOARD_SIZE] = {
+               NEURONSPI_BOARD_B1000_HW_DEFINITION, NEURONSPI_BOARD_E16DIU14DI_HW_DEFINITION
+};
+
+#define NEURONSPI_MODEL_M403_HW_DEFINITION_BOARD_SIZE 2
+static struct neuronspi_board_combination NEURONSPI_MODEL_M403_HW_DEFINITION_BOARD[NEURONSPI_MODEL_M403_HW_DEFINITION_BOARD_SIZE] = {
+               NEURONSPI_BOARD_B1000_HW_DEFINITION, NEURONSPI_BOARD_E14ROU14RO_HW_DEFINITION
+};
+
+#define NEURONSPI_MODEL_M503_HW_DEFINITION_BOARD_SIZE 2
+static struct neuronspi_board_combination NEURONSPI_MODEL_M503_HW_DEFINITION_BOARD[NEURONSPI_MODEL_M503_HW_DEFINITION_BOARD_SIZE] = {
+               NEURONSPI_BOARD_B1000_HW_DEFINITION, NEURONSPI_BOARD_E4AI4AOU6DI5RO_HW_DEFINITION
+};
+
+#define NEURONSPI_MODEL_M603_HW_DEFINITION_BOARD_SIZE 2
+static struct neuronspi_board_combination NEURONSPI_MODEL_M603_HW_DEFINITION_BOARD[NEURONSPI_MODEL_M603_HW_DEFINITION_BOARD_SIZE] = {
+               NEURONSPI_BOARD_B1000_HW_DEFINITION, NEURONSPI_BOARD_E4LIGHT_HW_DEFINITION
+};
+
+#define NEURONSPI_MODEL_L203_HW_DEFINITION_BOARD_SIZE 3
+static struct neuronspi_board_combination NEURONSPI_MODEL_L203_HW_DEFINITION_BOARD[NEURONSPI_MODEL_L203_HW_DEFINITION_BOARD_SIZE] = {
+               NEURONSPI_BOARD_B1000_HW_DEFINITION, NEURONSPI_BOARD_E16DIU14RO_HW_DEFINITION, NEURONSPI_BOARD_E16DIU14RO_HW_DEFINITION
+};
+
+#define NEURONSPI_MODEL_L303_HW_DEFINITION_BOARD_SIZE 3
+static struct neuronspi_board_combination NEURONSPI_MODEL_L303_HW_DEFINITION_BOARD[NEURONSPI_MODEL_L303_HW_DEFINITION_BOARD_SIZE] = {
+               NEURONSPI_BOARD_B1000_HW_DEFINITION, NEURONSPI_BOARD_E16DIU14DI_HW_DEFINITION, NEURONSPI_BOARD_E16DIU14DI_HW_DEFINITION
+};
+
+#define NEURONSPI_MODEL_L403_HW_DEFINITION_BOARD_SIZE 3
+static struct neuronspi_board_combination NEURONSPI_MODEL_L403_HW_DEFINITION_BOARD[NEURONSPI_MODEL_L403_HW_DEFINITION_BOARD_SIZE] = {
+               NEURONSPI_BOARD_B1000_HW_DEFINITION, NEURONSPI_BOARD_E14ROU14RO_HW_DEFINITION, NEURONSPI_BOARD_E14ROU14RO_HW_DEFINITION
+};
+
+#define NEURONSPI_MODEL_L503_HW_DEFINITION_BOARD_SIZE 3
+static struct neuronspi_board_combination NEURONSPI_MODEL_L503_HW_DEFINITION_BOARD[NEURONSPI_MODEL_L503_HW_DEFINITION_BOARD_SIZE] = {
+               NEURONSPI_BOARD_B1000_HW_DEFINITION,  NEURONSPI_BOARD_E4AI4AOU6DI5RO_HW_DEFINITION, NEURONSPI_BOARD_E14ROU14DI_HW_DEFINITION
+};
+
+#define NEURONSPI_MODEL_L513_HW_DEFINITION_BOARD_SIZE 3
+static struct neuronspi_board_combination NEURONSPI_MODEL_L513_HW_DEFINITION_BOARD[NEURONSPI_MODEL_L513_HW_DEFINITION_BOARD_SIZE] = {
+               NEURONSPI_BOARD_B1000_HW_DEFINITION, NEURONSPI_BOARD_E4AI4AOU6DI5RO_HW_DEFINITION, NEURONSPI_BOARD_E4AI4AOU6DI5RO_HW_DEFINITION
+};
+
+// Board table
+// Column 4 is the number of 0-indexed registers and column 5 is the number of 1000-indexed ones
+#define NEURONSPI_BOARDTABLE_LEN               16
+static struct neuronspi_board_entry NEURONSPI_BOARDTABLE[NEURONSPI_BOARDTABLE_LEN] = {
+       {.index = 0, .lower_board_id = NEURONSPI_BOARD_LOWER_B1000_ID,          .upper_board_id = NEURONSPI_BOARD_UPPER_NONE_ID,
+                       .data_register_count = 21,      .config_register_count = 32, .definition = NEURONSPI_BOARD_B1000_HW_COMBINATION},       // B_1000 (S103)
+       {.index = 1, .lower_board_id = NEURONSPI_BOARD_LOWER_E8DI8RO_ID,        .upper_board_id = NEURONSPI_BOARD_UPPER_NONE_ID,
+                       .data_register_count = 19,      .config_register_count = 21, .definition = NEURONSPI_BOARD_E8DI8RO_HW_COMBINATION},     // E-8Di8Ro (M103)
+       {.index = 2, .lower_board_id = NEURONSPI_BOARD_LOWER_E14RO_ID,          .upper_board_id = NEURONSPI_BOARD_UPPER_NONE_ID,
+                       .data_register_count = 1,       .config_register_count = 0,  .definition = NEURONSPI_BOARD_E14RO_HW_COMBINATION},               // E-14Ro
+       {.index = 3, .lower_board_id = NEURONSPI_BOARD_LOWER_E16DI_ID,          .upper_board_id = NEURONSPI_BOARD_UPPER_NONE_ID,
+                       .data_register_count = 1,       .config_register_count = 0,      .definition = NEURONSPI_BOARD_E16DI_HW_COMBINATION},           // E-16Di
+       {.index = 4, .lower_board_id = NEURONSPI_BOARD_LOWER_E8DI8RO_ID,        .upper_board_id = NEURONSPI_BOARD_UPPER_P11DIR485_ID,
+                       .data_register_count = 36,      .config_register_count = 31,  .definition = NEURONSPI_BOARD_E8DI8ROP11DIR485_HW_COMBINATION},   // E-8Di8Ro_P-11DiR485 (xS10)
+       {.index = 5, .lower_board_id = NEURONSPI_BOARD_LOWER_E14RO_ID,          .upper_board_id = NEURONSPI_BOARD_UPPER_P11DIR485_ID,
+                       .data_register_count = 20,      .config_register_count = 23,  .definition = NEURONSPI_BOARD_E14ROP11DIR485_HW_COMBINATION},     // E-14Ro_P-11DiR485 (xS40)
+       {.index = 6, .lower_board_id = NEURONSPI_BOARD_LOWER_E16DI_ID,          .upper_board_id = NEURONSPI_BOARD_UPPER_P11DIR485_ID,
+                       .data_register_count = 52,      .config_register_count = 36,  .definition = NEURONSPI_BOARD_E16DIP11DIR485_HW_COMBINATION},     // E-16Di_P-11DiR485 (xS30)
+       {.index = 7, .lower_board_id = NEURONSPI_BOARD_LOWER_E14RO_ID,          .upper_board_id = NEURONSPI_BOARD_UPPER_U14RO_ID,
+                       .data_register_count = 3,       .config_register_count = 10,  .definition = NEURONSPI_BOARD_E14ROU14RO_HW_COMBINATION}, // E-14Ro_U-14Ro (M403)
+       {.index = 8, .lower_board_id = NEURONSPI_BOARD_LOWER_E16DI_ID,          .upper_board_id = NEURONSPI_BOARD_UPPER_U14RO_ID,
+                       .data_register_count = 35,      .config_register_count = 29,  .definition = NEURONSPI_BOARD_E16DIU14RO_HW_COMBINATION}, // E-16Di_U-14Ro (M203)
+       {.index = 9, .lower_board_id = NEURONSPI_BOARD_LOWER_E14RO_ID,          .upper_board_id = NEURONSPI_BOARD_UPPER_U14DI_ID,
+                       .data_register_count = 31,      .config_register_count = 27,  .definition = NEURONSPI_BOARD_E14ROU14DI_HW_COMBINATION}, // E-14Ro_U-14Di (L503)
+       {.index = 10, .lower_board_id = NEURONSPI_BOARD_LOWER_E16DI_ID,         .upper_board_id = NEURONSPI_BOARD_UPPER_U14DI_ID,
+                       .data_register_count = 63, .config_register_count = 40,   .definition = NEURONSPI_BOARD_E16DIU14DI_HW_COMBINATION},     // E-16Di_U-14Di (M303)
+       {.index = 11, .lower_board_id = NEURONSPI_BOARD_LOWER_E4AI4AO_ID,       .upper_board_id = NEURONSPI_BOARD_UPPER_NONE_ID,
+                       .data_register_count = 1,       .config_register_count = 0,   .definition = NEURONSPI_BOARD_E4AI4AO_HW_COMBINATION},            // E-4Ai4Ao
+       {.index = 12, .lower_board_id = NEURONSPI_BOARD_LOWER_E4AI4AO_ID,       .upper_board_id = NEURONSPI_BOARD_UPPER_P6DI5RO_ID,
+                       .data_register_count = 27, .config_register_count = 25,   .definition = NEURONSPI_BOARD_E4AI4AOP6DI5RO_HW_COMBINATION}, // E-4Ai4Ao_P-6Di5Ro (xS50)
+       {.index = 13, .lower_board_id = NEURONSPI_BOARD_LOWER_B485_ID,          .upper_board_id = NEURONSPI_BOARD_UPPER_NONE_ID,
+                       .data_register_count = 1,  .config_register_count = 0,    .definition = NEURONSPI_BOARD_B485_HW_COMBINATION},           // B-485
+       {.index = 14, .lower_board_id = NEURONSPI_BOARD_LOWER_E4LIGHT_ID,       .upper_board_id = NEURONSPI_BOARD_UPPER_NONE_ID,
+                       .data_register_count = 21, .config_register_count = 8,    .definition = NEURONSPI_BOARD_E4LIGHT_HW_COMBINATION},                // E-4Light (M603)
+       {.index = 15, .lower_board_id = NEURONSPI_BOARD_LOWER_E4AI4AO_ID,       .upper_board_id = NEURONSPI_BOARD_UPPER_U6DI5RO_ID,
+                       .data_register_count = 28, .config_register_count = 24,   .definition = NEURONSPI_BOARD_E4AI4AOU6DI5RO_HW_COMBINATION}          // E-4Ai4Ao_U-6Di5Ro (M503)
+};
+
+// Module table
+#define NEURONSPI_MODELTABLE_LEN               15
+static struct neuronspi_model_definition NEURONSPI_MODELTABLE[NEURONSPI_MODELTABLE_LEN] = {
+               {.eeprom_length = 4, .eeprom_name = "S103", .name_length = 4, .model_name = "S103",
+                               .combination_count = 1, .combinations = NEURONSPI_MODEL_S103_HW_DEFINITION_BOARD},
+               {.eeprom_length = 4, .eeprom_name = "S103", .name_length = 6, .model_name = "S103-G",
+                               .combination_count = 1, .combinations = NEURONSPI_MODEL_S103G_HW_DEFINITION_BOARD},
+               {.eeprom_length = 6, .eeprom_name = "S103IQ", .name_length = 7, .model_name = "S103-IQ",
+                               .combination_count = 1, .combinations = NEURONSPI_MODEL_S103IQ_HW_DEFINITION_BOARD},
+               {.eeprom_length = 6, .eeprom_name = "S103EO", .name_length = 7, .model_name = "S103-EO",
+                               .combination_count = 1, .combinations = NEURONSPI_MODEL_S103EO_HW_DEFINITION_BOARD},
+               {.eeprom_length = 4, .eeprom_name = "M103", .name_length = 4, .model_name = "M103",
+                               .combination_count = 2, .combinations = NEURONSPI_MODEL_M103_HW_DEFINITION_BOARD},
+               {.eeprom_length = 4, .eeprom_name = "M203", .name_length = 4, .model_name = "M203",
+                               .combination_count = 2, .combinations = NEURONSPI_MODEL_M203_HW_DEFINITION_BOARD},
+               {.eeprom_length = 4, .eeprom_name = "M303", .name_length = 4, .model_name = "M303",
+                               .combination_count = 2, .combinations = NEURONSPI_MODEL_M303_HW_DEFINITION_BOARD},
+               {.eeprom_length = 4, .eeprom_name = "M403", .name_length = 4, .model_name = "M403",
+                               .combination_count = 2, .combinations = NEURONSPI_MODEL_M403_HW_DEFINITION_BOARD},
+               {.eeprom_length = 4, .eeprom_name = "M503", .name_length = 4, .model_name = "M503",
+                               .combination_count = 2, .combinations = NEURONSPI_MODEL_M503_HW_DEFINITION_BOARD},
+               {.eeprom_length = 4, .eeprom_name = "M603", .name_length = 4, .model_name = "M603",
+                               .combination_count = 2, .combinations = NEURONSPI_MODEL_M603_HW_DEFINITION_BOARD},
+               {.eeprom_length = 4, .eeprom_name = "L203", .name_length = 4, .model_name = "L203",
+                               .combination_count = 3, .combinations = NEURONSPI_MODEL_L203_HW_DEFINITION_BOARD},
+               {.eeprom_length = 4, .eeprom_name = "L303", .name_length = 4, .model_name = "L303",
+                               .combination_count = 3, .combinations = NEURONSPI_MODEL_L303_HW_DEFINITION_BOARD},
+               {.eeprom_length = 4, .eeprom_name = "L403", .name_length = 4, .model_name = "L403",
+                               .combination_count = 3, .combinations = NEURONSPI_MODEL_L403_HW_DEFINITION_BOARD},
+               {.eeprom_length = 4, .eeprom_name = "L503", .name_length = 4, .model_name = "L503",
+                               .combination_count = 3, .combinations = NEURONSPI_MODEL_L503_HW_DEFINITION_BOARD},
+               {.eeprom_length = 4, .eeprom_name = "L513", .name_length = 4, .model_name = "L513",
+                               .combination_count = 3, .combinations = NEURONSPI_MODEL_L513_HW_DEFINITION_BOARD}
+};
+
+int neuronspi_regmap_hw_gather_write(void *context, const void *reg, size_t reg_size, const void *val, size_t val_size);
+int neuronspi_regmap_hw_read(void *context, const void *reg_buf, size_t reg_size, void *val_buf, size_t val_size);
+int neuronspi_regmap_hw_reg_read(void *context, unsigned int reg, unsigned int *val);
+int neuronspi_regmap_hw_reg_write(void *context, unsigned int reg, unsigned int val);
+int neuronspi_regmap_hw_write(void *context, const void *data, size_t count);
+
+void neuronspi_regmap_invalidate_device(struct regmap *reg_map, struct neuronspi_board_combination *device_def, u32 period_counter);
+s32 neuronspi_regmap_invalidate(void *data);
+int neuronspi_create_reg_starts(struct neuronspi_board_regstart_table *out_table, struct neuronspi_board_combination *board);
+s32 neuronspi_find_reg_start(struct neuronspi_board_combination *board, u16 regfun);
+s32 neuronspi_find_model_id(u32 probe_count);
 
 #endif /* MODULES_NEURON_SPI_SRC_UNIPI_PLATFORM_H_ */
index 65e9e41c1f7921bbf892db0b8bf44125aac8fba8..544fa6b3c429b2006466975e58c43e6933365ea9 100644 (file)
@@ -13,13 +13,23 @@ nologies
  *
  */
 
+#include "unipi_common.h"
+#include "unipi_sysfs.h"
+#include "unipi_uart.h"
+#include "unipi_platform.h"
+#include "unipi_gpio.h"
+#include "unipi_iio.h"
+#include "unipi_misc.h"
 #include "unipi_spi.h"
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+MODULE_DEVICE_TABLE(of, neuronspi_id_match);
+
 /***********************
  * End of Data section *
  ***********************/
 
-static int neuronspi_open (struct inode *inode_p, struct file *file_p)
+int neuronspi_open (struct inode *inode_p, struct file *file_p)
 {
        struct neuronspi_file_data *f_internal_data;
        if (neuronspi_s_dev == NULL || file_p == NULL || inode_p == NULL) {
@@ -35,7 +45,7 @@ static int neuronspi_open (struct inode *inode_p, struct file *file_p)
        return 0;
 }
 
-static int neuronspi_release (struct inode *inode_p, struct file *file_p)
+int neuronspi_release (struct inode *inode_p, struct file *file_p)
 {
        struct neuronspi_file_data *f_internal_data;
        if (file_p == NULL) {
@@ -53,7 +63,7 @@ static int neuronspi_release (struct inode *inode_p, struct file *file_p)
        return 0;
 }
 
-static ssize_t neuronspi_read (struct file *file_p, char *buffer, size_t len, loff_t *offset)
+ssize_t neuronspi_read (struct file *file_p, char *buffer, size_t len, loff_t *offset)
 {
 
        s32 result = 0;
@@ -117,7 +127,7 @@ static ssize_t neuronspi_read (struct file *file_p, char *buffer, size_t len, lo
 
 
 
-static ssize_t neuronspi_write (struct file *file_p, const char *buffer, size_t len, loff_t *w_offset)
+ssize_t neuronspi_write (struct file *file_p, const char *buffer, size_t len, loff_t *w_offset)
 {
        u8 device_index = 0;
        s32 result = 0;
@@ -203,7 +213,7 @@ static ssize_t neuronspi_write (struct file *file_p, const char *buffer, size_t
     return len;
 }
 
-static s32 neuronspi_spi_uart_write(struct spi_device *spi, u8 *send_buf, u8 length, u8 uart_index)
+s32 neuronspi_spi_uart_write(struct spi_device *spi, u8 *send_buf, u8 length, u8 uart_index)
 {
        u8 *message_buf;
        u8 *recv_buf;
@@ -390,194 +400,6 @@ u8 neuronspi_spi_uart_get_ldisc(struct spi_device* spi_dev, u8 port)
        return outp;
 }
 
-int neuronspi_gpio_di_direction_input(struct gpio_chip *chip, unsigned offset) {
-       return 0;
-}
-int neuronspi_gpio_di_direction_output(struct gpio_chip *chip, unsigned offset, int value) {
-       return -EINVAL;
-}
-int    neuronspi_gpio_di_get(struct gpio_chip *chip, unsigned offset) {
-       struct neuronspi_di_driver *n_di = gpiochip_get_data(chip);
-       struct spi_device *spi = n_di->spi;
-       return neuronspi_spi_gpio_di_get(spi, n_di->di_index);
-}
-
-int neuronspi_gpio_do_direction_output(struct gpio_chip *chip, unsigned offset, int value) {
-       return 0;
-}
-void neuronspi_gpio_do_set(struct gpio_chip *chip, unsigned offset, int value) {
-       struct neuronspi_do_driver *n_do = gpiochip_get_data(chip);
-       struct spi_device *spi = n_do->spi;
-       neuronspi_spi_gpio_do_set(spi, n_do->do_index, value);
-}
-
-int neuronspi_gpio_ro_direction_output(struct gpio_chip *chip, unsigned offset, int value) {
-       return 0;
-}
-void neuronspi_gpio_ro_set(struct gpio_chip *chip, unsigned offset, int value) {
-       struct neuronspi_ro_driver *n_ro = gpiochip_get_data(chip);
-       struct spi_device *spi = n_ro->spi;
-       neuronspi_spi_gpio_ro_set(spi, n_ro->ro_index, value);
-}
-
-int neuronspi_iio_stm_ai_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *ch, int *val, int *val2, long mask) {
-       struct neuronspi_stm_ai_data *ai_data = iio_priv(indio_dev);
-       struct spi_device *spi = ai_data->parent;
-       struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi);
-       regmap_read(n_spi->reg_map, n_spi->regstart_table->stm_ai_mode_reg, &ai_data->mode);
-       switch(ai_data->mode) {
-       case 0: {
-               if (ch->type == IIO_VOLTAGE) {
-                       neuronspi_spi_iio_stm_ai_read_voltage(indio_dev, ch, val, val2, mask);
-                       return IIO_VAL_INT;
-               } else {
-                       return -EINVAL;
-               }
-               break;
-       }
-       case 1: {
-               if (ch->type == IIO_CURRENT) {
-                       neuronspi_spi_iio_stm_ai_read_current(indio_dev, ch, val, val2, mask);
-                       return IIO_VAL_INT;
-               } else {
-                       return -EINVAL;
-               }
-               break;
-       }
-       default: {
-               return -EINVAL;
-               break;
-       }
-       }
-}
-
-int neuronspi_iio_stm_ao_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *ch, int *val, int *val2, long mask)
-{
-       struct neuronspi_stm_ao_data *ao_data = iio_priv(indio_dev);
-       struct spi_device *spi = ao_data->parent;
-       struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi);
-       regmap_read(n_spi->reg_map, n_spi->regstart_table->stm_ao_mode_reg, &ao_data->mode);
-       switch(ao_data->mode) {
-       case 3: {
-               if (ch->type == IIO_RESISTANCE) {
-                       neuronspi_spi_iio_stm_ao_read_resistance(indio_dev, ch, val, val2, mask);
-                       return IIO_VAL_INT;
-               } else {
-                       return -EINVAL;
-               }
-               break;
-       }
-       default: {
-               return -EINVAL;
-               break;
-       }
-       }
-}
-
-int neuronspi_iio_stm_ao_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *ch, int val, int val2, long mask)
-{
-       struct neuronspi_stm_ao_data *ao_data = iio_priv(indio_dev);
-       struct spi_device *spi = ao_data->parent;
-       struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi);
-       regmap_read(n_spi->reg_map, n_spi->regstart_table->stm_ao_mode_reg, &ao_data->mode);
-       switch(ao_data->mode) {
-       case 0: {
-               if (ch->type == IIO_VOLTAGE) {
-                       neuronspi_spi_iio_stm_ao_set_voltage(indio_dev, ch, val, val2, mask);
-                       return 0;
-               } else {
-                       return -EINVAL;
-               }
-               break;
-       }
-       case 1: {
-               if (ch->type == IIO_CURRENT) {
-                       neuronspi_spi_iio_stm_ao_set_current(indio_dev, ch, val, val2, mask);
-                       return 0;
-               } else {
-                       return -EINVAL;
-               }
-               break;
-       }
-       default: {
-               return -EINVAL;
-               break;
-       }
-       }
-}
-
-int neuronspi_iio_sec_ai_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *ch, int *val, int *val2, long mask)
-{
-       struct neuronspi_sec_ai_data *ai_data = iio_priv(indio_dev);
-       struct spi_device *spi = ai_data->parent;
-       struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi);
-       regmap_read(n_spi->reg_map, n_spi->regstart_table->sec_ai_mode_reg, &ai_data->mode);
-       switch(ai_data->mode) {
-       case 0: {
-               return -EINVAL;
-               break;
-       }
-       case 1: {
-               if (ch->type == IIO_VOLTAGE) {
-                       neuronspi_spi_iio_sec_ai_read_voltage(indio_dev, ch, val, val2, mask);
-                       return IIO_VAL_FRACTIONAL;
-               } else {
-                       return -EINVAL;
-               }
-               break;
-       }
-       case 2: {
-               if (ch->type == IIO_VOLTAGE) {
-                       neuronspi_spi_iio_sec_ai_read_voltage(indio_dev, ch, val, val2, mask);
-                       return IIO_VAL_FRACTIONAL;
-               } else {
-                       return -EINVAL;
-               }
-               break;
-       }
-       case 3: {
-               if (ch->type == IIO_CURRENT) {
-                       neuronspi_spi_iio_sec_ai_read_current(indio_dev, ch, val, val2, mask);
-                       return IIO_VAL_FRACTIONAL;
-               } else {
-                       return -EINVAL;
-               }
-               break;
-       }
-       case 4: {
-               if (ch->type == IIO_RESISTANCE) {
-                       neuronspi_spi_iio_sec_ai_read_resistance(indio_dev, ch, val, val2, mask);
-                       return IIO_VAL_FRACTIONAL;
-               } else {
-                       return -EINVAL;
-               }
-               break;
-       }
-       case 5: {
-               if (ch->type == IIO_RESISTANCE) {
-                       neuronspi_spi_iio_sec_ai_read_resistance(indio_dev, ch, val, val2, mask);
-                       return IIO_VAL_FRACTIONAL;
-               } else {
-                       return -EINVAL;
-               }
-               break;
-       }
-       default: {
-               return -EINVAL;
-               break;
-       }
-       }
-}
-
-int neuronspi_iio_sec_ao_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *ch, int val, int val2, long mask)
-{
-       if (ch->type == IIO_VOLTAGE) {
-               neuronspi_spi_iio_stm_ao_set_voltage(indio_dev, ch, val, val2, mask);
-               return 0;
-       } else {
-               return -EINVAL;
-       }
-}
 
 /*
  * NOTE: This function uses 64-bit fixed-point arithmetic,
@@ -795,118 +617,6 @@ void neuronspi_spi_iio_stm_ao_set_current(struct iio_dev *indio_dev, struct iio_
        regmap_write(n_spi->reg_map, n_spi->regstart_table->stm_ao_val_reg, (unsigned int)stm_true_val);
 }
 
-static ssize_t neuronspi_iio_show_primary_ai_mode(struct device *dev, struct device_attribute *attr, char *buf)
-{
-       int ret = 0;
-       unsigned int val = 0;
-       struct iio_dev *indio_dev = dev_get_drvdata(dev);
-       struct neuronspi_stm_ai_data *ai_data = iio_priv(indio_dev);
-       struct spi_device *spi = ai_data->parent;
-       struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi);
-       regmap_read(n_spi->reg_map, n_spi->regstart_table->stm_ai_mode_reg, &val);
-       ret = scnprintf(buf, 255, "%d\n", val);
-       return ret;
-}
-static ssize_t neuronspi_iio_store_primary_ai_mode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-       ssize_t err = 0;
-       unsigned int val = 0;
-       struct iio_dev *indio_dev = dev_get_drvdata(dev);
-       struct neuronspi_stm_ai_data *ai_data = iio_priv(indio_dev);
-       struct spi_device *spi = ai_data->parent;
-       struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi);
-       err = kstrtouint(buf, 0, &val);
-       if (err < 0) goto err_end;
-       if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) {
-               regmap_write(n_spi->reg_map, n_spi->regstart_table->stm_ai_mode_reg, val);
-       }
-err_end:
-       return count;
-}
-static ssize_t neuronspi_iio_show_primary_ao_mode(struct device *dev, struct device_attribute *attr, char *buf)
-{
-       int ret = 0;
-       unsigned int val = 0;
-       struct iio_dev *indio_dev = dev_get_drvdata(dev);
-       struct neuronspi_stm_ao_data *ao_data = iio_priv(indio_dev);
-       struct spi_device *spi = ao_data->parent;
-       struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi);
-       regmap_read(n_spi->reg_map, n_spi->regstart_table->stm_ao_mode_reg, &val);
-       ret = scnprintf(buf, 255, "%d\n", val);
-       return ret;
-}
-static ssize_t neuronspi_iio_store_primary_ao_mode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-       ssize_t err = 0;
-       unsigned int val = 0;
-       struct iio_dev *indio_dev = dev_get_drvdata(dev);
-       struct neuronspi_stm_ao_data *ao_data = iio_priv(indio_dev);
-       struct spi_device *spi = ao_data->parent;
-       struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi);
-       err = kstrtouint(buf, 0, &val);
-       if (err < 0) goto err_end;
-       if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) {
-               regmap_write(n_spi->reg_map, n_spi->regstart_table->stm_ao_mode_reg, val);
-       }
-err_end:
-       return count;
-}
-static ssize_t neuronspi_iio_show_secondary_ai_mode(struct device *dev, struct device_attribute *attr, char *buf)
-{
-       int ret = 0;
-       unsigned int val = 0;
-       struct iio_dev *indio_dev = dev_get_drvdata(dev);
-       struct neuronspi_sec_ai_data *ai_data = iio_priv(indio_dev);
-       struct spi_device *spi = ai_data->parent;
-       struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi);
-       regmap_read(n_spi->reg_map, n_spi->regstart_table->sec_ai_mode_reg + ai_data->index, &val);
-       ret = scnprintf(buf, 255, "%d\n", val);
-       return ret;
-}
-static ssize_t neuronspi_iio_store_secondary_ai_mode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-       ssize_t err = 0;
-       unsigned int val = 0;
-       struct iio_dev *indio_dev = dev_get_drvdata(dev);
-       struct neuronspi_sec_ai_data *ai_data = iio_priv(indio_dev);
-       struct spi_device *spi = ai_data->parent;
-       struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi);
-       err = kstrtouint(buf, 0, &val);
-       if (err < 0) goto err_end;
-       if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) {
-               regmap_write(n_spi->reg_map, n_spi->regstart_table->sec_ai_mode_reg + ai_data->index, val);
-       }
-err_end:
-       return count;
-}
-static ssize_t neuronspi_iio_show_secondary_ao_mode(struct device *dev, struct device_attribute *attr, char *buf)
-{
-       int ret = 0;
-       unsigned int val = 0;
-       struct iio_dev *indio_dev = dev_get_drvdata(dev);
-       struct neuronspi_sec_ao_data *ao_data = iio_priv(indio_dev);
-       struct spi_device *spi = ao_data->parent;
-       struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi);
-       regmap_read(n_spi->reg_map, n_spi->regstart_table->sec_ao_mode_reg + ao_data->index, &val);
-       ret = scnprintf(buf, 255, "%d\n", val);
-       return ret;
-}
-static ssize_t neuronspi_iio_store_secondary_ao_mode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-       ssize_t err = 0;
-       unsigned int val = 0;
-       struct iio_dev *indio_dev = dev_get_drvdata(dev);
-       struct neuronspi_sec_ao_data *ao_data = iio_priv(indio_dev);
-       struct spi_device *spi = ao_data->parent;
-       struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi);
-       err = kstrtouint(buf, 0, &val);
-       if (err < 0) goto err_end;
-       if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) {
-               regmap_write(n_spi->reg_map, n_spi->regstart_table->sec_ao_mode_reg + ao_data->index, val);
-       }
-err_end:
-       return count;
-}
 /*
 static s32 neuronspi_spi_watchdog(void *data)
 {
@@ -926,34 +636,6 @@ static s32 neuronspi_spi_watchdog(void *data)
 }
 */
 
-u32 neuronspi_spi_uart_get_cflag(struct spi_device* spi_dev, u8 port)
-{
-       u8 *message_buf;
-       u8 *recv_buf;
-       u16 crc1, crc2, ret;
-       struct neuronspi_driver_data *d_data = spi_get_drvdata(spi_dev);
-       s32 frequency = NEURONSPI_COMMON_FREQ;
-       if (d_data->slower_model) {
-               frequency = NEURONSPI_SLOWER_FREQ;
-       }
-       message_buf = kzalloc(NEURONSPI_SPI_UART_GET_CFLAG_MESSAGE_LEN, GFP_KERNEL);
-       recv_buf = kzalloc(NEURONSPI_SPI_UART_GET_CFLAG_MESSAGE_LEN, GFP_KERNEL);
-       memcpy(message_buf, NEURONSPI_SPI_UART_GET_CFLAG_MESSAGE, NEURONSPI_SPI_UART_GET_CFLAG_MESSAGE_LEN);
-       crc1 = neuronspi_spi_crc(message_buf, 4, 0);
-       memcpy(&message_buf[4], &crc1, 2);
-       crc2 = neuronspi_spi_crc(&message_buf[6], NEURONSPI_SPI_UART_GET_CFLAG_MESSAGE_LEN - 8, crc1);
-       memcpy(&message_buf[NEURONSPI_SPI_UART_GET_CFLAG_MESSAGE_LEN - 2], &crc2, 2);
-       if (!d_data->reserved_device) {
-               neuronspi_spi_send_message(spi_dev, message_buf, recv_buf, NEURONSPI_SPI_UART_GET_CFLAG_MESSAGE_LEN, frequency, 65, 1);
-       }
-       ret = ((u32*)recv_buf)[5];
-#if NEURONSPI_DETAILED_DEBUG > 0
-       printk(KERN_INFO "NEURONSPI: SPI TERMIOS Get, Dev-CS:%d, val:%x\n", spi_dev->chip_select, ret);
-#endif
-       kfree(message_buf);
-       kfree(recv_buf);
-       return ret;
-}
 
 
 void neuronspi_spi_send_message(struct spi_device* spi_dev, u8 *send_buf, u8 *recv_buf, s32 len, s32 freq, s32 delay, s32 send_header)
@@ -1086,140 +768,9 @@ void neuronspi_spi_send_message(struct spi_device* spi_dev, u8 *send_buf, u8 *re
     kfree(s_trans);
 }
 
-static void neuronspi_uart_fifo_read(struct uart_port *port, u32 rxlen)
-{
-       struct neuronspi_port *s = to_neuronspi_port(port,port);
-       struct neuronspi_driver_data *d_data = spi_get_drvdata(neuronspi_s_dev[s->dev_index]);
-#if NEURONSPI_DETAILED_DEBUG > 0
-       printk(KERN_INFO "NEURONSPI: FIFO Read len:%d\n", rxlen);
-#endif
-    memcpy(s->buf, d_data->uart_buf, rxlen);
-}
-
-static void neuronspi_uart_fifo_write(struct neuronspi_port *port, u8 to_send)
-{
-       s32 i;
-#if NEURONSPI_DETAILED_DEBUG > 0
-       printk(KERN_INFO "NEURONSPI: FIFO Write to_send:%d\n", to_send);
-#endif
-       for (i = 0; i < to_send; i++) {
-#if NEURONSPI_DETAILED_DEBUG > 0
-               printk(KERN_INFO "NEURONSPI: UART Char Send: %x\n", port->buf[i]);
-#endif
-       }
-    neuronspi_spi_uart_write(neuronspi_s_dev[port->dev_index], port->buf, to_send, port->dev_port);
-}
-
-static s32 neuronspi_uart_alloc_line(void)
-{
-       s32 i;
-       BUILD_BUG_ON(NEURONSPI_MAX_DEVS > BITS_PER_LONG);
-
-       for (i = 0; i < NEURONSPI_MAX_DEVS; i++)
-               if (!test_and_set_bit(i, &neuronspi_lines))
-                       break;
-
-       return i;
-}
-
-static void neuronspi_uart_power(struct uart_port *port, s32 on)
-{
-    /* Do nothing */
-}
-
-static void neuronspi_uart_handle_rx(struct neuronspi_port *port, u32 rxlen, u32 iir)
-{
-       u32 ch, flag, bytes_read, i;
-       while (rxlen) {
-
-               neuronspi_uart_fifo_read(&port->port, rxlen);
-               bytes_read = rxlen;
-
-               port->port.icount.rx++;
-               flag = TTY_NORMAL;
-
-               for (i = 0; i < bytes_read; ++i) {
-#if NEURONSPI_DETAILED_DEBUG > 0
-                       printk(KERN_INFO "NEURONSPI: UART Insert Char:%x\n", port->buf[i]);
-#endif
-                       ch = port->buf[i];
-                       if (uart_handle_sysrq_char(port, ch))
-                               continue;
-
-                       uart_insert_char(&port->port, 0, 0, ch, flag);
-               }
-               rxlen -= bytes_read;
-       }
-
-       tty_flip_buffer_push(&port->port.state->port);
-}
-
-static void neuronspi_uart_handle_tx(struct neuronspi_port *port)
-{
-       u32 txlen, to_send, i;
-       struct spi_device *spi;
-       struct neuronspi_driver_data *d_data;
-       struct circ_buf *xmit;
-
-       spi = neuronspi_s_dev[port->dev_index];
-       d_data = spi_get_drvdata(spi);
-       xmit = &port->port.state->xmit;
-
-       if (unlikely(port->port.x_char)) {
-               neuronspi_spi_uart_write(spi, &port->port.x_char, 1, port->dev_port);
-               port->port.icount.tx++;
-               port->port.x_char = 0;
-               return;
-       }
-
-       if (uart_circ_empty(xmit) || uart_tx_stopped(&port->port)) {
-               return;
-       }
-
-
-       /* Get length of data pending in circular buffer */
-       to_send = uart_circ_chars_pending(xmit);
-       if (likely(to_send)) {
-               /* Limit to size of TX FIFO */
-               txlen = NEURONSPI_FIFO_SIZE;
-               to_send = (to_send > txlen) ? txlen : to_send;
-
-               /* Add data to send */
-               port->port.icount.tx += to_send;
-
-               /* Convert to linear buffer */
-               for (i = 0; i < to_send; ++i) {
-                       port->buf[i] = xmit->buf[xmit->tail];
-                       xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
-               }
-
-               neuronspi_uart_fifo_write(port, to_send);
-       }
-
-
-       if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
-               uart_write_wakeup(&port->port);
-}
-
-static void neuronspi_uart_handle_irq(struct neuronspi_uart_data *uart_data, s32 portno)
-{
-       struct neuronspi_port *n_port = &uart_data->p[portno];
-       struct spi_device *spi = neuronspi_s_dev[n_port->dev_index];
-       u8 *send_buf = kzalloc(NEURONSPI_UART_PROBE_MESSAGE_LEN, GFP_KERNEL);
-       u8 *recv_buf = kzalloc(NEURONSPI_UART_PROBE_MESSAGE_LEN, GFP_KERNEL);
-       memcpy(send_buf, NEURONSPI_UART_PROBE_MESSAGE, NEURONSPI_UART_PROBE_MESSAGE_LEN);
-       neuronspi_spi_send_message(spi, send_buf, recv_buf, NEURONSPI_UART_PROBE_MESSAGE_LEN, NEURONSPI_DEFAULT_FREQ, 25, 1);
-       kfree(send_buf);
-       kfree(recv_buf);
-}
 
-static void neuronspi_uart_ist(struct kthread_work *ws)
-{
-       struct neuronspi_port *p = to_neuronspi_port(ws, irq_work);
-       neuronspi_uart_handle_irq(p->parent, p->line);
-}
 
-static irqreturn_t neuronspi_spi_irq(s32 irq, void *dev_id)
+irqreturn_t neuronspi_spi_irq(s32 irq, void *dev_id)
 {
        s32 i;
        struct spi_device *spi;
@@ -1242,1588 +793,89 @@ static irqreturn_t neuronspi_spi_irq(s32 irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-static void neuronspi_uart_tx_proc(struct kthread_work *ws)
+void neuronspi_spi_led_set_brightness(struct spi_device* spi_dev, enum led_brightness brightness, int id)
 {
-       struct neuronspi_port *port = to_neuronspi_port(ws, tx_work);
-
-       if ((port->port.rs485.flags & SER_RS485_ENABLED) &&
-           (port->port.rs485.delay_rts_before_send > 0)) {
-               msleep(port->port.rs485.delay_rts_before_send);
+       u8 *message_buf;
+       u8 *recv_buf;
+       u16 crc1;
+       struct neuronspi_driver_data *d_data = spi_get_drvdata(spi_dev);
+       s32 frequency = NEURONSPI_COMMON_FREQ;
+       if (d_data->slower_model) {
+               frequency = NEURONSPI_SLOWER_FREQ;
        }
-
-       neuronspi_uart_handle_tx(port);
-}
-
-
-static void neuronspi_led_proc(struct kthread_work *ws)
-{
-       struct neuronspi_led_driver *led = to_led_driver(ws, led_work);
-       printk("NEURONSPI: BRIGHT id:%d\n", led->id);
-       neuronspi_spi_led_set_brightness(led->spi, led->brightness, led->id);
-}
-
-static void neuronspi_uart_rx_proc(struct kthread_work *ws)
-{
-       s32 end_flag = 0;
-       s32 read_count = 0;
-       struct neuronspi_port *n_port = to_neuronspi_port(ws, rx_work);
-       struct spi_device *spi = neuronspi_s_dev[n_port->dev_index];
-       struct neuronspi_driver_data *d_data = spi_get_drvdata(spi);
-
-       u8 *send_buf = kzalloc(NEURONSPI_BUFFER_MAX, GFP_KERNEL);
-       u8 *recv_buf = kzalloc(NEURONSPI_BUFFER_MAX, GFP_KERNEL);
-
-       mutex_lock(&neuronspi_master_mutex);
-       read_count = d_data->uart_read;
-       mutex_unlock(&neuronspi_master_mutex);
-
-       while (!end_flag) {
-               memset(recv_buf, 0, NEURONSPI_BUFFER_MAX);
-               neuronspi_spi_uart_read(spi, send_buf, recv_buf, read_count, n_port->dev_port);
-               if (recv_buf[6] == 0x65 && recv_buf[7] > 0) {
-                       mutex_lock(&neuronspi_master_mutex);
-                       memcpy(&d_data->uart_buf[0], &recv_buf[10], recv_buf[7]);
-                       neuronspi_uart_handle_rx(n_port, recv_buf[7], 1);
-                       read_count = recv_buf[9];
-                       mutex_unlock(&neuronspi_master_mutex);
-               } else if (recv_buf[0] != 0x41) {
-                       mutex_lock(&neuronspi_master_mutex);
-                       d_data->uart_read = 0;
-                       end_flag = 1;
-                       mutex_unlock(&neuronspi_master_mutex);
-               }
+#if NEURONSPI_DETAILED_DEBUG > 0
+       printk(KERN_INFO "NEURONSPI: SPI LED Set, Dev-CS:%d, led id:%d\n", spi_dev->chip_select, id);
+#endif
+       message_buf = kzalloc(NEURONSPI_SPI_LED_SET_MESSAGE_LEN, GFP_KERNEL);
+       recv_buf = kzalloc(NEURONSPI_SPI_LED_SET_MESSAGE_LEN, GFP_KERNEL);
+       memcpy(message_buf, NEURONSPI_SPI_LED_SET_MESSAGE, NEURONSPI_SPI_LED_SET_MESSAGE_LEN);
+       message_buf[2] += id;
+       if (brightness > 0) {
+               message_buf[1] = 0x01;
+       } else {
+               message_buf[1] = 0x00;
+       }
+       crc1 = neuronspi_spi_crc(message_buf, 4, 0);
+       memcpy(&message_buf[4], &crc1, 2);
+       if (!d_data->reserved_device) {
+               neuronspi_spi_send_message(spi_dev, message_buf, recv_buf, NEURONSPI_SPI_LED_SET_MESSAGE_LEN, frequency, 25, 0);
        }
+       printk(KERN_INFO "NEURONSPI: Brightness set to %d on led %d\n", brightness, id);
+       kfree(message_buf);
        kfree(recv_buf);
-       kfree(send_buf);
 }
 
-
-static void neuronspi_uart_stop_tx(struct uart_port *port)
-{
-    // ToDo : create new opcode / coil?
-}
-
-static void neuronspi_uart_stop_rx(struct uart_port *port)
-{
-    // ToDo : create new opcode / coil?
-}
-
-static void neuronspi_uart_start_tx(struct uart_port *port)
-{
-       struct neuronspi_port *n_port = to_neuronspi_port(port,port);
-#if NEURONSPI_DETAILED_DEBUG > 0
-       printk(KERN_INFO "NEURONSPI: Start TX\n");
-#endif
-       kthread_queue_work(&n_port->parent->kworker, &n_port->tx_work);
-}
-
-static s32 neuronspi_uart_poll(void *data)
-{
-       struct neuronspi_driver_data *d_data = (struct neuronspi_driver_data*) data;
-       struct neuronspi_uart_data *u_data;
-       s32 i;
-       while (!kthread_should_stop()) {
-               usleep_range(2000,8000);
-               if (d_data->uart_count) {
-                       u_data = d_data->uart_data;
-                       for (i = 0; i < u_data->p_count; i++) {
-                               if (u_data->p[i].dev_index == d_data->neuron_index) {
-                                       kthread_queue_work(&u_data->kworker, &u_data->p[i].irq_work);
-                               }
-                       }
-               }
-       }
-       return 0;
-}
-
-static s32 neuronspi_regmap_invalidate(void *data)
-{
-       int i;
-       int freq_cnt = 0;
-       while (!kthread_should_stop()) {
-               usleep_range(15000,25000);
-               if (freq_cnt == 450001) freq_cnt = 0;
-               for (i = 0; i < NEURONSPI_MAX_DEVS; i++) {
-                       if (neuronspi_s_dev[i] != NULL) {
-                               struct neuronspi_driver_data *d_data = spi_get_drvdata(neuronspi_s_dev[i]);
-                               if (d_data->combination_id == 0xFF) {
-                                       continue;
-                               }
-                               neuronspi_regmap_invalidate_device(d_data->reg_map, NEURONSPI_BOARDTABLE[d_data->combination_id].definition, freq_cnt);
-                       }
-               }
-               freq_cnt++;
-       }
-       return 0;
-}
-
-static void neuronspi_regmap_invalidate_device(struct regmap *reg_map, struct neuronspi_board_combination *device_def, u32 period_counter)
-{
-       int block_start, block_len, block_counter, current_period, period_len;
-       int i;
-       block_start = -1;
-       block_len = -1;
-       block_counter = 0;
-       period_len = 1;
-
-       for (i = 0; i < device_def->block_count; i++) {
-               if (block_start == -1) {
-                       block_start = device_def->blocks[i];
-                       block_counter = 0;
-               } else if (block_len == -1) {
-                       block_len = device_def->blocks[i];
-               } else if ((block_counter != block_len)) {
-                       current_period = device_def->blocks[i] & 0x00FF0000;
-                       if ((block_counter + 1 != block_len) && ((device_def->blocks[i + 1] & 0x00FF0000) == current_period)) {
-                               period_len++;
-                       } else {
-                               switch (current_period) {
-                               case NEURONSPI_REGFLAG_ACC_AFAP: {
-                                       regcache_drop_region(reg_map, block_start + block_counter - period_len + 1, block_start + block_counter);
-                                       break;
-                               }
-                               case NEURONSPI_REGFLAG_ACC_10HZ: {
-                                       if ((period_counter) % 5) {
-                                               regcache_drop_region(reg_map, block_start + block_counter - period_len + 1, block_start + block_counter);
-                                       }
-                                       break;
-                               }
-                               case NEURONSPI_REGFLAG_ACC_1HZ: {
-                                       if ((period_counter % 50) == 0) {
-                                               regcache_drop_region(reg_map, block_start + block_counter - period_len + 1, block_start + block_counter);
-                                       }
-                                       break;
-                               }
-                               case NEURONSPI_REGFLAG_ACC_6SEC: {
-                                       if ((period_counter % 300) == 0) {
-                                               regcache_drop_region(reg_map, block_start + block_counter - period_len + 1, block_start + block_counter);
-                                       }
-                                       break;
-                               }
-                               case NEURONSPI_REGFLAG_ACC_1MIN: {
-                                       if ((period_counter % 3000) == 0) {
-                                               regcache_drop_region(reg_map, block_start + block_counter - period_len + 1, block_start + block_counter);
-                                       }
-                                       break;
-                               }
-                               case NEURONSPI_REGFLAG_ACC_15MIN: {
-                                       if ((period_counter % 45000) == 0) {
-                                               regcache_drop_region(reg_map, block_start + block_counter - period_len + 1, block_start + block_counter);
-                                       }
-                                       break;
-                               }
-                               default:
-                                       break;
-                               }
-                               period_len = 1;
-                       }
-                       block_counter++;
-               }
-               if (block_counter == block_len) {
-                       block_counter = 0;
-                       block_start = -1;
-                       block_len = -1;
-               }
-       }
-}
-
-static u32 neuronspi_uart_tx_empty(struct uart_port *port)
-{
-#if NEURONSPI_DETAILED_DEBUG > 0
-       printk(KERN_INFO "NEURONSPI: UART TX Empty\n");
-#endif
-       return TIOCSER_TEMT;
-}
-
-static u32 neuronspi_uart_get_mctrl(struct uart_port *port)
-{
-       /* DCD and DSR are not wired and CTS/RTS is handled automatically
-        * so just indicate DSR and CAR asserted
-        */
-#if NEURONSPI_DETAILED_DEBUG > 0
-       printk(KERN_DEBUG "NEURONSPI: UART MCTRL Get\n");
-#endif
-       return TIOCM_DSR | TIOCM_CAR;
-}
-
-static void neuronspi_uart_set_mctrl(struct uart_port *port, u32 mctrl) {}
-
-int    neuronspi_uart_ioctl (struct uart_port *port, unsigned int ioctl_code, unsigned long ioctl_arg)
-{
-       switch (ioctl_code) {
-       case TIOCSETD: {
-               printk(KERN_INFO "NEURONSPI: IOCTL TIOCSETD\n");
-               return 1;
-       }
-       case 0x5480: {
-               printk(KERN_INFO "NEURONSPI: IOCTL 0x5480\n");
-               return 1;
-       }
-       case 0x5481: {
-               printk(KERN_INFO "NEURONSPI: IOCTL 0x5481\n");
-               return 1;
-       }
-       default: {
-               return 0;
-       }
-       }
-}
-
-static void neuronspi_uart_set_parmrk(struct uart_port *port, int to)
-{
-       struct neuronspi_port *n_port;
-       n_port = to_neuronspi_port(port, port);
-}
-
-static void neuronspi_uart_set_ldisc(struct uart_port *port, struct ktermios *kterm)
-{
-       struct neuronspi_port *n_port;
-       n_port = to_neuronspi_port(port, port);
-       if (kterm->c_line == N_PROFIBUS_FDL) {
-               printk(KERN_INFO "NEURONSPI: PROFIBUS discipline set/n");
-       }
-       return;
-}
-
-static void neuronspi_uart_break_ctl(struct uart_port *port, int break_state)
-{
-
-}
-
-static void neuronspi_uart_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old)
-{
-       s32 baud;
-       struct neuronspi_port *n_port;
-       n_port = to_neuronspi_port(port, port);
-       if (old && old->c_iflag && old->c_iflag != termios->c_iflag) {
-               printk(KERN_INFO "NEURONSPI: c_iflag termios:%d\n", termios->c_iflag);
-       }
-#if NEURONSPI_DETAILED_DEBUG > 0
-       printk(KERN_DEBUG "NEURONSPI: TERMIOS Set, p:%d, c_cflag:%x\n", port->line, termios->c_cflag);
-#endif
-       neuronspi_spi_uart_set_cflag(neuronspi_s_dev[n_port->dev_index], n_port->dev_port, termios->c_cflag);
-       if (old && termios && (old->c_iflag & PARMRK) != (termios->c_iflag & PARMRK)) {
-               if (termios->c_iflag & PARMRK) {
-                       neuronspi_uart_set_parmrk(port, 1);             // TODO: Re-enable line discipline once finished
-               } else {
-                       neuronspi_uart_set_parmrk(port, 0);
-               }
-       }
-       if (old && termios && old->c_line != termios->c_line) {
-               if (termios->c_line == N_PROFIBUS_FDL) {
-                       printk(KERN_INFO "NEURONSPI: Line Discipline change/n");
-                       neuronspi_uart_set_ldisc(port, termios);
-               }
-       }
-
-       baud = uart_get_baud_rate(port, termios, old, 2400, 115200);
-       uart_update_timeout(port, termios->c_cflag, baud);
-}
-
-static s32 neuronspi_uart_config_rs485(struct uart_port *port, struct serial_rs485 *rs485)
-{
-       port->rs485 = *rs485;
-       return 0;
-}
-
-// Initialise the module
-static s32 neuronspi_uart_startup(struct uart_port *port)
-{
-       struct neuronspi_port *n_port = to_neuronspi_port(port, port);
-       struct spi_device *spi = neuronspi_s_dev[n_port->dev_index];
-       struct neuronspi_driver_data *d_data = spi_get_drvdata(spi);
-       neuronspi_spi_set_irqs(spi, 0x5);
-       if (d_data->poll_thread != NULL) {
-               wake_up_process(d_data->poll_thread);
-       } else if (d_data->no_irq) {
-               d_data->poll_thread = kthread_create(neuronspi_uart_poll, (void *)d_data, "UART_poll_thread");
-       }
-       neuronspi_uart_power(port, 1);
-       // TODO: /* Reset FIFOs*/
-#if NEURONSPI_DETAILED_DEBUG > 0
-       printk(KERN_DEBUG "NEURONSPI: UART Startup\n");
-#endif
-       return 0;
-}
-
-static void neuronspi_uart_shutdown(struct uart_port *port)
-{
-    neuronspi_uart_power(port, 0);
-}
-
-static const char* neuronspi_uart_type(struct uart_port *port)
-{
-       return port->type == PORT_NEURONSPI ? "NEURONSPI_NAME" : NULL;
-}
-
-static s32 neuronspi_uart_request_port(struct uart_port *port)
-{
-#if NEURONSPI_DETAILED_DEBUG > 0
-       printk(KERN_DEBUG "NEURONSPI: Requested port %d\n", port->line);
-#endif
-       return 0;
-}
-
-static void neuronspi_uart_config_port(struct uart_port *port, int flags)
-{
-       if (flags & UART_CONFIG_TYPE)
-               port->type = PORT_NEURONSPI;
-}
-
-static s32 neuronspi_uart_verify_port(struct uart_port *port,
-                                struct serial_struct *s)
-{
-       if ((s->type != PORT_UNKNOWN) && (s->type != PORT_NEURONSPI))
-               return -EINVAL;
-       if (s->irq != port->irq)
-               return -EINVAL;
-
-       return 0;
-}
-
-static void neuronspi_uart_pm(struct uart_port *port, u32 state, u32 oldstate)
-{
-       neuronspi_uart_power(port, (state == UART_PM_STATE_ON) ? 1 : 0);
-}
-
-static void neuronspi_uart_null_void(struct uart_port *port)
-{
-       /* Do nothing */
-}
-
-static s32 neuronspi_uart_probe(struct spi_device* dev, u8 device_index)
-{
-       struct neuronspi_driver_data* driver_data = spi_get_drvdata(dev);
-       struct sched_param sched_param = { .sched_priority = MAX_RT_PRIO / 2 };
-       s32 i, j, ret, new_uart_count;
-       struct neuronspi_uart_data *uart_data = driver_data->uart_data;
-
-       if (uart_data->p == NULL) {
-               uart_data->p = kzalloc(sizeof(struct neuronspi_port[NEURONSPI_MAX_UART]), GFP_KERNEL);
-               for (i = 0; i < NEURONSPI_MAX_UART; i++) {
-                       uart_data->p[i].parent = uart_data;
-               }
-#if NEURONSPI_DETAILED_DEBUG > 0
-               printk(KERN_DEBUG "NEURONSPI: Allocated port structure for %d potential UART devices\n", NEURONSPI_MAX_UART);
-#endif
-       }
-
-       new_uart_count = driver_data->uart_count + uart_data->p_count;
-
-       // Initialise port data
-       for (i = uart_data->p_count; i < new_uart_count; i++) {
-               uart_data->p[i].dev_index = device_index;
-               uart_data->p[i].dev_port = i - uart_data->p_count;
-               uart_data->p[i].line            = i;
-               uart_data->p[i].port.dev        = &(dev->dev);
-               uart_data->p[i].port.irq        = dev->irq;
-               uart_data->p[i].port.type       = PORT_NEURONSPI;
-               uart_data->p[i].port.fifosize   = NEURONSPI_FIFO_SIZE;
-               uart_data->p[i].port.flags      = UPF_FIXED_TYPE | UPF_LOW_LATENCY;
-               uart_data->p[i].port.iotype     = UPIO_PORT;
-               uart_data->p[i].port.uartclk    = 9600;
-               uart_data->p[i].port.rs485_config = neuronspi_uart_config_rs485;
-               uart_data->p[i].port.ops        = &neuronspi_uart_ops;
-               uart_data->p[i].port.line       = neuronspi_uart_alloc_line();
-               spin_lock_init(&uart_data->p[i].port.lock);
-               if (uart_data->p[i].port.line >= NEURONSPI_MAX_DEVS) {
-                       ret = -ENOMEM;
-               }
-               kthread_init_work(&(uart_data->p[i].tx_work), neuronspi_uart_tx_proc);
-               kthread_init_work(&(uart_data->p[i].rx_work), neuronspi_uart_rx_proc);
-               kthread_init_work(&(uart_data->p[i].irq_work), neuronspi_uart_ist);
-               uart_add_one_port(driver_data->serial_driver, &uart_data->p[i].port);
-               printk(KERN_INFO "NEURONSPI: Added UART port %d\n", i);
-       }
-
-       // For ports on multiple SPI devices renumber the ports to correspond to SPI chip-select numbering
-       if (uart_data->p_count) {
-               // First remove all existing ports
-               for (i = 0; i < new_uart_count; i++) {
-                       uart_remove_one_port(driver_data->serial_driver, &uart_data->p[i].port);
-                       clear_bit(uart_data->p[i].port.line, &neuronspi_lines);
-                       kthread_flush_worker(&uart_data->kworker);
-               }
-               // Now add the ports in the correct order
-               for (i = 0; i < NEURONSPI_MAX_DEVS; i++) {
-                       if (neuronspi_s_dev[i] != NULL) {
-                               driver_data = spi_get_drvdata(neuronspi_s_dev[i]);
-#if NEURONSPI_DETAILED_DEBUG > 0
-                               printk(KERN_DEBUG "NEURONSPI: Renumber not NULL %d UC:%d\n", i, driver_data->uart_count);
-#endif
-                               if (driver_data->uart_count) {
-                                       for (j = 0; j < new_uart_count; j++) {
-                                               if (uart_data->p[j].dev_index == i) {
-                                                       uart_data->p[j].port.dev        = &(neuronspi_s_dev[i]->dev);
-                                                       uart_data->p[j].port.irq        = neuronspi_s_dev[i]->irq;
-                                                       uart_data->p[j].port.type       = PORT_NEURONSPI;
-                                                       uart_data->p[j].port.fifosize   = NEURONSPI_FIFO_SIZE;
-                                                       uart_data->p[j].port.flags      = UPF_FIXED_TYPE | UPF_LOW_LATENCY;
-                                                       uart_data->p[j].port.iotype     = UPIO_PORT;
-                                                       uart_data->p[j].port.uartclk    = 9800;
-                                                       uart_data->p[j].port.rs485_config = neuronspi_uart_config_rs485;
-                                                       uart_data->p[j].port.ops        = &neuronspi_uart_ops;
-                                                       uart_data->p[j].port.line       = neuronspi_uart_alloc_line();
-                                                       uart_add_one_port(driver_data->serial_driver, &uart_data->p[j].port);
-#if NEURONSPI_DETAILED_DEBUG > 0
-                                                       printk(KERN_DEBUG "NEURONSPI: Added UART port %d\n", j);
-#endif
-                                               }
-                                       }
-                               }
-                       }
-               }
-       }
-
-       uart_data->p_count = new_uart_count;
-       if (uart_data->kworker_task == NULL) {
-#if NEURONSPI_DETAILED_DEBUG > 0
-               printk(KERN_DEBUG "NEURONSPI: KWorker Task is NULL\n");
-#endif
-
-               kthread_init_worker(&uart_data->kworker);
-
-               uart_data->kworker_task = kthread_run(kthread_worker_fn, &uart_data->kworker,
-                                                 "neuronspi");
-               if (IS_ERR(uart_data->kworker_task)) {
-                       ret = PTR_ERR(uart_data->kworker_task);
-               }
-               sched_setscheduler(uart_data->kworker_task, SCHED_FIFO, &sched_param);
-       }
-       return ret;
-}
-
-static s32 neuronspi_uart_remove(struct neuronspi_uart_data *u_data)
-{
-       struct neuronspi_driver_data *d_data;
-       struct spi_device *spi;
-       s32 i;
-
-       for (i = 0; i < NEURONSPI_MAX_DEVS; i++) {
-               if (!(neuronspi_s_dev[i] == NULL)) {
-                       spi = neuronspi_s_dev[i];
-                       d_data = spi_get_drvdata(spi);
-                       if (d_data->poll_thread != NULL) {
-                               kthread_stop(d_data->poll_thread);
-                       }
-               }
-       }
-       for (i = 0; i < u_data->p_count; i++) {
-               uart_remove_one_port(neuronspi_uart, &u_data->p[i].port);
-               clear_bit(u_data->p[i].port.line, &neuronspi_lines);
-               neuronspi_uart_power(&u_data->p[i].port, 0);
-       }
-
-       kthread_flush_worker(&u_data->kworker);
-       return 0;
-}
-
-void neuronspi_spi_led_set_brightness(struct spi_device* spi_dev, enum led_brightness brightness, int id)
-{
-       u8 *message_buf;
-       u8 *recv_buf;
-       u16 crc1;
-       struct neuronspi_driver_data *d_data = spi_get_drvdata(spi_dev);
-       s32 frequency = NEURONSPI_COMMON_FREQ;
-       if (d_data->slower_model) {
-               frequency = NEURONSPI_SLOWER_FREQ;
-       }
-#if NEURONSPI_DETAILED_DEBUG > 0
-       printk(KERN_INFO "NEURONSPI: SPI LED Set, Dev-CS:%d, led id:%d\n", spi_dev->chip_select, id);
-#endif
-       message_buf = kzalloc(NEURONSPI_SPI_LED_SET_MESSAGE_LEN, GFP_KERNEL);
-       recv_buf = kzalloc(NEURONSPI_SPI_LED_SET_MESSAGE_LEN, GFP_KERNEL);
-       memcpy(message_buf, NEURONSPI_SPI_LED_SET_MESSAGE, NEURONSPI_SPI_LED_SET_MESSAGE_LEN);
-       message_buf[2] += id;
-       if (brightness > 0) {
-               message_buf[1] = 0x01;
-       } else {
-               message_buf[1] = 0x00;
-       }
-       crc1 = neuronspi_spi_crc(message_buf, 4, 0);
-       memcpy(&message_buf[4], &crc1, 2);
-       if (!d_data->reserved_device) {
-               neuronspi_spi_send_message(spi_dev, message_buf, recv_buf, NEURONSPI_SPI_LED_SET_MESSAGE_LEN, frequency, 25, 0);
-       }
-       printk(KERN_INFO "NEURONSPI: Brightness set to %d on led %d\n", brightness, id);
-       kfree(message_buf);
-       kfree(recv_buf);
-       recv_buf = kzalloc(8, GFP_KERNEL);
-       printk(KERN_INFO "NEURONSPI: REGMAP TEST: %d\n", regmap_bulk_read(d_data->reg_map, 1000, (void*)recv_buf, 4));
-       printk(KERN_INFO "NEURONSPI: REGMAP TEST OUT: %d %d %d %d\n", recv_buf[0], recv_buf[1], recv_buf[2], recv_buf[3]);
-       kfree(recv_buf);
-       recv_buf = kzalloc(8, GFP_KERNEL);
-       printk(KERN_INFO "NEURONSPI: REGMAP TEST: %d\n", regmap_bulk_read(d_data->reg_map, 1000, (void*)recv_buf, 4));
-       printk(KERN_INFO "NEURONSPI: REGMAP TEST OUT: %d %d %d %d\n", recv_buf[0], recv_buf[1], recv_buf[2], recv_buf[3]);
-       kfree(recv_buf);
-       recv_buf = kzalloc(8, GFP_KERNEL);
-       printk(KERN_INFO "NEURONSPI: REGMAP TEST: %d\n", regmap_bulk_read(d_data->reg_map, 1000, (void*)recv_buf, 4));
-       printk(KERN_INFO "NEURONSPI: REGMAP TEST OUT: %d %d %d %d\n", recv_buf[0], recv_buf[1], recv_buf[2], recv_buf[3]);
-       kfree(recv_buf);
-}
-
-int neuronspi_spi_gpio_di_get(struct spi_device* spi_dev, u32 id)
-{
-       u8 *recv_buf;
-       bool ret = 0;
-       u32 offset = id / 16;
-       struct neuronspi_driver_data *d_data = spi_get_drvdata(spi_dev);
-       recv_buf = kzalloc(4, GFP_KERNEL);
-       printk(KERN_INFO "NEURONSPI: REGMAP TEST: %d\n", regmap_read(d_data->reg_map, d_data->regstart_table->di_val_reg + offset, (void*)recv_buf));
-       if (*recv_buf & (0x1 << offset)) {
-               ret = 1;
-       }
-       kfree(recv_buf);
-       printk(KERN_INFO "NEURONSPI: GPIO DI %d get %d\n", id, ret);
-       return ret;
-}
-
-int neuronspi_spi_gpio_do_set(struct spi_device* spi_dev, u32 id, int value)
-{
-       u32 current_value = 0;
-       bool ret = 0;
-       u32 offset = id / 16;
-       u16 off_val = value << (id % 16);
-       u16 mask = ~(1 << (id % 16));
-       struct neuronspi_driver_data *d_data = spi_get_drvdata(spi_dev);
-       regmap_read(d_data->reg_map, d_data->regstart_table->do_val_reg + offset, &current_value);
-       current_value&= mask;
-       current_value|= off_val;
-       regmap_write(d_data->reg_map, d_data->regstart_table->do_val_reg + offset, current_value);
-       printk(KERN_INFO "NEURONSPI: GPIO DO %d set %d\n", id, value);
-       return ret;
-}
-
-int neuronspi_spi_gpio_ro_set(struct spi_device* spi_dev, u32 id, int value)
-{
-       u32 current_value = 0;
-       bool ret = 0;
-       u32 offset = id / 16;
-       u16 off_val = value << (id % 16);
-       u16 mask = ~(1 << (id % 16));
-       struct neuronspi_driver_data *d_data = spi_get_drvdata(spi_dev);
-       regmap_read(d_data->reg_map, d_data->regstart_table->ro_val_reg + offset, &current_value);
-       current_value&= mask;
-       current_value|= off_val;
-       regmap_write(d_data->reg_map, d_data->regstart_table->ro_val_reg + offset, current_value);
-       printk(KERN_INFO "NEURONSPI: GPIO RO %d set %d\n", id, value);
-       return ret;
-}
-
-
-static void neuronspi_led_set_brightness(struct led_classdev *ldev, enum led_brightness brightness)
-{
-       struct neuronspi_led_driver *led = container_of(ldev, struct neuronspi_led_driver, ldev);
-       struct neuronspi_driver_data *n_spi = spi_get_drvdata(led->spi);
-       spin_lock(&led->lock);
-       led->brightness = brightness;
-       kthread_queue_work(&n_spi->primary_worker, &led->led_work);
-       spin_unlock(&led->lock);
-}
-
-int neuronspi_regmap_hw_read(void *context, const void *reg_buf, size_t reg_size, void *val_buf, size_t val_size) {
-       const u16 *mb_reg_buf = reg_buf;
-       u16 *mb_val_buf = val_buf;
-       struct spi_device *spi;
-       struct neuronspi_driver_data *n_spi;
-       u8 *inp_buf;
-       u8 *outp_buf;
-       int i, write_length;
-       int block_counter = 0;
-       if (context == NULL) {
-               return 0;
-       }
-       spi = context;
-       n_spi = spi_get_drvdata(spi);
-       if (n_spi == NULL) {
-               return 0;
-       }
-       for (i = 0; i < (reg_size / 2); i++) {
-               // Check for continuity and read the largest possible continuous block
-               if (block_counter == ((reg_size / 2) - 1) || ((mb_reg_buf[i] + 1) != mb_reg_buf[i + 1])) {
-                       write_length = neuronspi_spi_compose_multiple_register_read(block_counter + 1, mb_reg_buf[i - block_counter], &inp_buf, &outp_buf);
-                       neuronspi_spi_send_message(spi, inp_buf, outp_buf, write_length, n_spi->ideal_frequency, 125, 1);
-                       memcpy(&mb_val_buf[i - block_counter], &outp_buf[NEURONSPI_HEADER_LENGTH], (block_counter + 1) * 2);
-                       kfree(inp_buf);
-                       kfree(outp_buf);
-                       block_counter = 0;
-               } else {
-                       block_counter++;
-               }
-       }
-       printk(KERN_INFO "NEURONSPI: RM_READ %d %x %d %x\n", reg_size, mb_reg_buf[0], val_size, mb_val_buf[0]);
-       return 0;
-}
-
-int neuronspi_regmap_hw_reg_read(void *context, unsigned int reg, unsigned int *val) {
-       struct spi_device *spi = context;
-       struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi);
-       u8 *inp_buf;
-       u8 *outp_buf;
-       int write_length;
-       printk(KERN_INFO "NEURONSPI: RM_REG_READ\n");
-       write_length = neuronspi_spi_compose_single_register_read(reg, &inp_buf, &outp_buf);
-       neuronspi_spi_send_message(spi, inp_buf, outp_buf, write_length, n_spi->ideal_frequency, 25, 1);
-       memcpy(val, &outp_buf[NEURONSPI_HEADER_LENGTH], sizeof(u16));
-       kfree(inp_buf);
-       kfree(outp_buf);
-       return 0;
-}
-
-int neuronspi_regmap_hw_write(void *context, const void *data, size_t count) {
-       BUG_ON(count < 1);
-       return neuronspi_regmap_hw_gather_write(context, data, 1, data + 1, count - 1);
-}
-
-int neuronspi_regmap_hw_reg_write(void *context, unsigned int reg, unsigned int val) {
-       struct spi_device *spi = context;
-       struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi);
-       u8 *inp_buf;
-       u8 *outp_buf;
-       int write_length;
-       write_length = neuronspi_spi_compose_single_register_write(reg, &inp_buf, &outp_buf, (val >> 8));
-       printk(KERN_INFO "HW_REG_WRITE l:%d, r:%d, v:%d\n", write_length, reg, (val >> 8));
-       neuronspi_spi_send_message(spi, inp_buf, outp_buf, write_length, n_spi->ideal_frequency, 25, 1);
-       memcpy(&val, &outp_buf[NEURONSPI_HEADER_LENGTH], sizeof(u16));
-       kfree(inp_buf);
-       kfree(outp_buf);
-       return 0;
-}
-
-int neuronspi_regmap_hw_gather_write(void *context, const void *reg, size_t reg_size, const void *val, size_t val_size) {
-       u16 *mb_reg_buf = (u16*)reg;
-       u32 *mb_val_buf = (u32*)val;
-       struct spi_device *spi = context;
-       struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi);
-       u8 *inp_buf;
-       u8 *outp_buf;
-       int i, write_length;
-       int block_counter = 0;
-       printk(KERN_INFO "HW_REG_GATHER_WRITE:%d, %d, %x, %x\n", val_size, reg_size, mb_reg_buf[0], mb_val_buf[0]);
-       if (reg_size == 1) {
-               neuronspi_regmap_hw_reg_write(context,mb_reg_buf[0],mb_val_buf[0]);
-       } else {
-               for (i = 0; i < reg_size; i++) {
-                       // Swap endianness
-                       cpu_to_be16s((u16*)&(mb_val_buf[i]));
-                       // Check for continuity and read the largest possible continuous block
-                       if (block_counter == (reg_size - 1) || ((mb_reg_buf[i] + 1) != mb_reg_buf[i + 1]))  {
-                               write_length = neuronspi_spi_compose_multiple_register_write(block_counter, mb_reg_buf[i - block_counter], &inp_buf, &outp_buf,
-                                                                                                    (u8*)(&mb_val_buf[i - block_counter]));
-                               neuronspi_spi_send_message(spi, inp_buf, outp_buf, write_length, n_spi->ideal_frequency, 125, 1);
-                               block_counter = 0;
-                               kfree(inp_buf);
-                               kfree(outp_buf);
-                       } else {
-                               block_counter++;
-                       }
-               }
-       }
-       return 0;
-}
-
-static int neuronspi_create_reg_starts(struct neuronspi_board_regstart_table *out_table, struct neuronspi_board_combination *board) {
-       if (board->features.di_count > 0) {
-               out_table->di_val_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_DI_READ);
-               out_table->di_counter_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_DI_COUNTER_UPPER);
-               out_table->di_deboun_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_DI_DEBOUNCE);
-               out_table->di_direct_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_DS_ENABLE);
-               out_table->di_polar_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_DS_POLARITY);
-               out_table->di_toggle_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_DS_TOGGLE);
-       }
-       if (board->features.do_count > 0) {
-               out_table->do_val_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_DO_RW);
-               out_table->do_pwm_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_PWM_DUTY);
-               out_table->do_pwm_c_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_PWM_CYCLE);
-               out_table->do_pwm_ps_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_PWM_PRESCALE);
-       }
-       if (board->features.led_count > 0) {
-               out_table->led_val_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_LED_RW);
-       }
-       if (board->features.light_count > 0) {
-               // TODO: Fill in light bus registers
-       }
-       if (board->features.ro_count > 0) {
-               out_table->ro_val_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_DO_RW);
-       }
-       if (board->features.sec_ai_count > 0) {
-               out_table->sec_ai_val_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_AI_VER2_READ_LOWER);
-               out_table->sec_ai_mode_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_AI_VER2_MODE);
-       }
-       if (board->features.sec_ao_count > 0) {
-               out_table->sec_ao_val_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_AO_VER2_RW);
-       }
-       if (board->features.stm_ao_count > 0) {
-               out_table->stm_ao_val_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_AO_BRAIN);
-               out_table->stm_ao_mode_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_AO_BRAIN_MODE);
-               out_table->stm_ao_vol_err = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_AO_BRAIN_V_ERR);
-               out_table->stm_ao_vol_off = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_AO_BRAIN_V_OFF);
-               out_table->stm_ao_curr_err = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_AO_BRAIN_I_ERR);
-               out_table->stm_ao_curr_off = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_AO_BRAIN_I_OFF);
-       }
-       if (board->features.stm_ai_count > 0) {
-               out_table->stm_ai_val_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_AI_BRAIN);
-               out_table->stm_ai_mode_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_AI_BRAIN_MODE);
-               out_table->stm_ai_vol_err = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_AI_BRAIN_V_ERR);
-               out_table->stm_ai_vol_off = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_AI_BRAIN_V_OFF);
-               out_table->stm_ai_curr_err = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_AI_BRAIN_I_ERR);
-               out_table->stm_ai_curr_off = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_AI_BRAIN_I_OFF);
-               out_table->stm_aio_val_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_AIO_BRAIN);
-               out_table->stm_aio_vol_err = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_AIO_BRAIN_ERR);
-               out_table->stm_aio_vol_off = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_AIO_BRAIN_OFF);
-               out_table->vref_inp = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_V_REF_INP);
-       }
-       out_table->uart_queue_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_TX_QUEUE_LEN);
-       out_table->uart_conf_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_RS485_CONFIG);
-       out_table->vref_int = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_V_REF_INT);
-       out_table->wd_timeout_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_MWD_TO);
-       out_table->sys_serial_num = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_SERIAL_NR_LOWER);
-       out_table->sys_sw_ver = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_SW_VER);
-       out_table->sys_hw_ver = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_HW_VER);
-       out_table->sys_hw_flash_ver = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_FLASH_HW_VER);
-       return 0;
-}
-
-static s32 neuronspi_find_reg_start(struct neuronspi_board_combination *board, u16 regfun) {
-       int i;
-       int block_start = -1;
-       int block_len = -1;
-       int block_counter = 0;
-       for (i = 0; i < board->block_count; i++) {
-               if (block_start == -1) {
-                       block_start = board->blocks[i];
-               } else if (block_len == -1) {
-                       block_len = board->blocks[i];
-               } else if ((board->blocks[i] & 0xFFFF) == regfun) {
-                       //printk(KERN_INFO "NEURONSPI: Reg Start Fun: %x RegS: %d", regfun, block_start + block_counter);
-                       return block_start + block_counter;
-               } else {
-                       block_counter++;
-               }
-               if (block_counter == block_len) {
-                       block_counter = 0;
-                       block_start = -1;
-                       block_len = -1;
-               }
-       }
-       return -1;
-}
-
-static s32 neuronspi_find_model_id(u32 probe_count)
-{
-       struct neuronspi_driver_data *n_spi;
-       int i,j, ret = -1;
-       u8 *inv = kzalloc(sizeof(*inv) * NEURONSPI_MODELTABLE_LEN, GFP_KERNEL);
-       for (i = 0; i < probe_count; i++) {
-               if (neuronspi_s_dev[i]) {
-                       n_spi = spi_get_drvdata(neuronspi_s_dev[i]);
-                       for (j = 0; j < NEURONSPI_MODELTABLE_LEN; j++) {
-                               if (i + 1 > NEURONSPI_MODELTABLE[j].combination_count) {
-                                       inv[j] = 1;
-                               } else if (NEURONSPI_MODELTABLE[j].combinations[i].combination_board_id != n_spi->combination_id) {
-                                       inv[j] = 1;
-                               }
-                       }
-               } else {
-                       for (j = 0; j < NEURONSPI_MODELTABLE_LEN; j++) {
-                               if (i + 1 < NEURONSPI_MODELTABLE[j].combination_count) {
-                                       inv[j] = 1;
-                               }
-                       }
-               }
-       }
-       for (i = 0; i < NEURONSPI_MODELTABLE_LEN; i++) {
-               if (inv[i] != 1) {
-                       ret = i;
-                       break;
-               }
-       }
-       kfree(inv);
-       return ret;
-}
-
-static ssize_t neuronspi_show_model(struct device *dev, struct device_attribute *attr, char *buf)
-{
-       ssize_t ret = 0;
-       if (neuronspi_model_id != -1) {
-               ret = scnprintf(buf, 255, "%s\n", NEURONSPI_MODELTABLE[neuronspi_model_id].model_name);
-       }
-       return ret;
-}
-
-static ssize_t neuronspi_show_eeprom(struct device *dev, struct device_attribute *attr, char *buf)
-{
-       ssize_t ret = 0;
-       if (neuronspi_model_id != -1) {
-               ret = scnprintf(buf, 255, "%s\n", NEURONSPI_MODELTABLE[neuronspi_model_id].eeprom_name);
-       }
-       return ret;
-}
-
-
-
-static ssize_t neuronspi_spi_show_serial(struct device *dev, struct device_attribute *attr, char *buf)
-{
-       ssize_t ret = 0;
-       u32 val[2] = {0, 0};
-       struct neuronspi_driver_data *n_spi;
-       struct platform_device *plat = to_platform_device(dev);
-       n_spi = platform_get_drvdata(plat);
-       if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) {
-               regmap_read(n_spi->reg_map, n_spi->regstart_table->sys_serial_num, val);
-               regmap_read(n_spi->reg_map, n_spi->regstart_table->sys_serial_num + 1, &(val[1]));
-               ret = scnprintf(buf, 255, "%d\n", val[0]);
-       }
-       return ret;
-}
-
-static ssize_t neuronspi_spi_show_hw_version(struct device *dev, struct device_attribute *attr, char *buf)
-{
-       ssize_t ret = 0;
-       u32 val = 0;
-       struct neuronspi_driver_data *n_spi;
-       struct platform_device *plat = to_platform_device(dev);
-       n_spi = platform_get_drvdata(plat);
-       if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) {
-               regmap_read(n_spi->reg_map, n_spi->regstart_table->sys_hw_ver, &val);
-               ret = scnprintf(buf, 255, "%x.%x\n", (val & 0xF0) >> 4, val & 0xF);
-       }
-       return ret;
-}
-
-static ssize_t neuronspi_spi_show_hw_flash_version(struct device *dev, struct device_attribute *attr, char *buf)
-{
-       ssize_t ret = 0;
-       u32 val = 0;
-       struct neuronspi_driver_data *n_spi;
-       struct platform_device *plat = to_platform_device(dev);
-       n_spi = platform_get_drvdata(plat);
-       if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) {
-               regmap_read(n_spi->reg_map, n_spi->regstart_table->sys_hw_flash_ver, &val);
-               ret = scnprintf(buf, 255, "%x.%x\n", (val & 0xF0) >> 4, val & 0xF);
-       }
-       return ret;
-}
-
-static ssize_t neuronspi_spi_show_fw_version(struct device *dev, struct device_attribute *attr, char *buf)
-{
-       ssize_t ret = 0;
-       u32 val = 0;
-       struct neuronspi_driver_data *n_spi;
-       struct platform_device *plat = to_platform_device(dev);
-       n_spi = platform_get_drvdata(plat);
-       if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) {
-               regmap_read(n_spi->reg_map, n_spi->regstart_table->sys_sw_ver, &val);
-               ret = scnprintf(buf, 255, "%x.%x%x\n", (val & 0xF00) >> 8, (val & 0xF0) >> 4, val & 0xF);
-       }
-       return ret;
-}
-
-static ssize_t neuronspi_spi_show_uart_queue_length(struct device *dev, struct device_attribute *attr, char *buf)
-{
-       ssize_t ret = 0;
-       u32 val = 0;
-       struct neuronspi_driver_data *n_spi;
-       struct platform_device *plat = to_platform_device(dev);
-       n_spi = platform_get_drvdata(plat);
-       if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map && n_spi->regstart_table->uart_queue_reg) {
-               regmap_read(n_spi->reg_map, n_spi->regstart_table->uart_queue_reg, &val);
-               ret = scnprintf(buf, 255, "%d\n", val);
-       }
-       return ret;
-}
-
-static ssize_t neuronspi_spi_show_uart_config(struct device *dev, struct device_attribute *attr, char *buf)
-{
-       ssize_t ret = 0;
-       u32 val = 0;
-       struct neuronspi_driver_data *n_spi;
-       struct platform_device *plat = to_platform_device(dev);
-       n_spi = platform_get_drvdata(plat);
-       if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map && n_spi->regstart_table->uart_conf_reg) {
-               regmap_read(n_spi->reg_map, n_spi->regstart_table->uart_conf_reg, &val);
-               ret = scnprintf(buf, 255, "%x\n", val);
-       }
-       return ret;
-}
-
-static ssize_t neuronspi_spi_store_uart_config(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-       ssize_t err = 0;
-       unsigned int val = 0;
-       struct neuronspi_driver_data *n_spi;
-       struct platform_device *plat = to_platform_device(dev);
-       n_spi = platform_get_drvdata(plat);
-       err = kstrtouint(buf, 0, &val);
-       if (err < 0) goto err_end;
-       if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map && n_spi->regstart_table->uart_conf_reg) {
-               regmap_write(n_spi->reg_map, n_spi->regstart_table->uart_conf_reg, val);
-       }
-err_end:
-       return count;
-}
-
-static ssize_t neuronspi_spi_show_watchdog_status(struct device *dev, struct device_attribute *attr, char *buf)
-{
-       ssize_t ret = 0;
-       u32 val = 0;
-       struct neuronspi_driver_data *n_spi;
-       struct platform_device *plat = to_platform_device(dev);
-       n_spi = platform_get_drvdata(plat);
-       if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) {
-               regmap_read(n_spi->reg_map, n_spi->regstart_table->wd_val_reg, &val);
-               ret = scnprintf(buf, 255, "%x\n", val);
-       }
-       return ret;
-}
-
-static ssize_t neuronspi_spi_store_watchdog_status(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-       ssize_t err = 0;
-       unsigned int val = 0;
-       struct neuronspi_driver_data *n_spi;
-       struct platform_device *plat = to_platform_device(dev);
-       n_spi = platform_get_drvdata(plat);
-       err = kstrtouint(buf, 0, &val);
-       if (err < 0) goto err_end;
-       if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) {
-               regmap_write(n_spi->reg_map, n_spi->regstart_table->wd_val_reg, val);
-       }
-err_end:
-       return count;
-}
-
-static ssize_t neuronspi_spi_show_watchdog_timeout(struct device *dev, struct device_attribute *attr, char *buf)
-{
-       ssize_t ret = 0;
-       u32 val = 0;
-       struct neuronspi_driver_data *n_spi;
-       struct platform_device *plat = to_platform_device(dev);
-       n_spi = platform_get_drvdata(plat);
-       if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) {
-               regmap_read(n_spi->reg_map, n_spi->regstart_table->wd_timeout_reg, &val);
-               ret = scnprintf(buf, 255, "%d\n", val);
-       }
-       return ret;
-}
-
-static ssize_t neuronspi_spi_store_watchdog_timeout(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-       ssize_t err = 0;
-       unsigned int val = 0;
-       struct neuronspi_driver_data *n_spi;
-       struct platform_device *plat = to_platform_device(dev);
-       n_spi = platform_get_drvdata(plat);
-       err = kstrtouint(buf, 0, &val);
-       if (err < 0) goto err_end;
-       if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) {
-               regmap_write(n_spi->reg_map, n_spi->regstart_table->wd_timeout_reg, val);
-       }
-err_end:
-       return count;
-}
-
-static ssize_t neuronspi_spi_gpio_show_pwm_presc(struct device *dev, struct device_attribute *attr, char *buf)
-{
-       ssize_t ret = 0;
-       u32 val = 0;
-       struct neuronspi_do_driver *n_do;
-       struct neuronspi_driver_data *n_spi;
-       struct platform_device *plat = to_platform_device(dev);
-       n_do = platform_get_drvdata(plat);
-       n_spi = spi_get_drvdata(n_do->spi);
-       if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) {
-               regmap_read(n_spi->reg_map, n_spi->regstart_table->do_pwm_ps_reg, &val);
-               ret = scnprintf(buf, 255, "%d\n", val);
-       }
-       return ret;
-}
-
-static ssize_t neuronspi_spi_gpio_store_pwm_presc(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-       ssize_t err = 0;
-       unsigned int val = 0;
-       struct neuronspi_do_driver *n_do;
-       struct neuronspi_driver_data *n_spi;
-       struct platform_device *plat = to_platform_device(dev);
-       n_do = platform_get_drvdata(plat);
-       n_spi = spi_get_drvdata(n_do->spi);
-       err = kstrtouint(buf, 0, &val);
-       if (err < 0) goto err_end;
-       if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) {
-               regmap_write(n_spi->reg_map, n_spi->regstart_table->do_pwm_ps_reg, val);
-       }
-err_end:
-       return count;
-}
-
-static ssize_t neuronspi_spi_gpio_show_pwm_freq(struct device *dev, struct device_attribute *attr, char *buf)
-{
-       ssize_t ret = 0;
-       u32 val = 0;
-       struct neuronspi_do_driver *n_do;
-       struct neuronspi_driver_data *n_spi;
-       struct platform_device *plat = to_platform_device(dev);
-       n_do = platform_get_drvdata(plat);
-       n_spi = spi_get_drvdata(n_do->spi);
-       if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) {
-               regmap_read(n_spi->reg_map, n_spi->regstart_table->do_pwm_c_reg, &val);
-               ret = scnprintf(buf, 255, "%d\n", val);
-       }
-       return ret;
-}
-
-static ssize_t neuronspi_spi_gpio_store_pwm_freq(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-       ssize_t err = 0;
-       unsigned int val = 0;
-       struct neuronspi_do_driver *n_do;
-       struct neuronspi_driver_data *n_spi;
-       struct platform_device *plat = to_platform_device(dev);
-       n_do = platform_get_drvdata(plat);
-       n_spi = spi_get_drvdata(n_do->spi);
-       err = kstrtouint(buf, 0, &val);
-       if (err < 0) goto err_end;
-       if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) {
-               regmap_write(n_spi->reg_map, n_spi->regstart_table->do_pwm_c_reg, val);
-       }
-err_end:
-       return count;
-}
-
-static ssize_t neuronspi_spi_gpio_show_pwm_cycle(struct device *dev, struct device_attribute *attr, char *buf)
-{
-       ssize_t ret = 0;
-       u32 val = 0;
-       struct neuronspi_do_driver *n_do;
-       struct neuronspi_driver_data *n_spi;
-       struct platform_device *plat = to_platform_device(dev);
-       n_do = platform_get_drvdata(plat);
-       n_spi = spi_get_drvdata(n_do->spi);
-       if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) {
-               regmap_read(n_spi->reg_map, n_spi->regstart_table->do_pwm_reg + n_do->do_index, &val);
-               ret = scnprintf(buf, 255, "%d\n", val);
-       }
-       return ret;
-}
-
-static ssize_t neuronspi_spi_gpio_store_pwm_cycle(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-       ssize_t err = 0;
-       unsigned int val = 0;
-       struct neuronspi_do_driver *n_do;
-       struct neuronspi_driver_data *n_spi;
-       struct platform_device *plat = to_platform_device(dev);
-       n_do = platform_get_drvdata(plat);
-       n_spi = spi_get_drvdata(n_do->spi);
-       err = kstrtouint(buf, 0, &val);
-       if (err < 0) goto err_end;
-       if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) {
-               regmap_write(n_spi->reg_map, n_spi->regstart_table->do_pwm_reg + n_do->do_index, val);
-       }
-err_end:
-       return count;
-}
-
-static ssize_t neuronspi_spi_gpio_di_show_counter(struct device *dev, struct device_attribute *attr, char *buf)
-{
-       ssize_t ret = 0;
-       u32 val = 0;
-       struct neuronspi_di_driver *n_di;
-       struct neuronspi_driver_data *n_spi;
-       struct platform_device *plat = to_platform_device(dev);
-       n_di = platform_get_drvdata(plat);
-       n_spi = spi_get_drvdata(n_di->spi);
-       if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) {
-               regmap_read(n_spi->reg_map, n_spi->regstart_table->di_counter_reg + (2 * n_di->di_index), &val);
-               ret = scnprintf(buf, 255, "%d\n", val);
-       }
-       return ret;
-}
-
-static ssize_t neuronspi_spi_gpio_di_store_counter(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-       ssize_t err = 0;
-       unsigned int val = 0;
-       struct neuronspi_di_driver *n_di;
-       struct neuronspi_driver_data *n_spi;
-       struct platform_device *plat = to_platform_device(dev);
-       n_di = platform_get_drvdata(plat);
-       n_spi = spi_get_drvdata(n_di->spi);
-       err = kstrtouint(buf, 0, &val);
-       if (err < 0) goto err_end;
-       if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) {
-               regmap_write(n_spi->reg_map, n_spi->regstart_table->di_counter_reg + (2 * n_di->di_index), val);
-       }
-err_end:
-       return count;
-}
-
-static ssize_t neuronspi_spi_gpio_di_show_debounce(struct device *dev, struct device_attribute *attr, char *buf)
-{
-       ssize_t ret = 0;
-       u32 val = 0;
-       struct neuronspi_di_driver *n_di;
-       struct neuronspi_driver_data *n_spi;
-       struct platform_device *plat = to_platform_device(dev);
-       n_di = platform_get_drvdata(plat);
-       n_spi = spi_get_drvdata(n_di->spi);
-       if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map && n_spi->features && n_spi->features->di_count > n_di->di_index) {
-               regmap_read(n_spi->reg_map, n_spi->regstart_table->di_deboun_reg + n_di->di_index, &val);
-               ret = scnprintf(buf, 255, "%d\n", val);
-       }
-       return ret;
-}
-
-static ssize_t neuronspi_spi_gpio_di_store_debounce(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-       ssize_t err = 0;
-       unsigned int val = 0;
-       struct neuronspi_di_driver *n_di;
-       struct neuronspi_driver_data *n_spi;
-       struct platform_device *plat = to_platform_device(dev);
-       n_di = platform_get_drvdata(plat);
-       n_spi = spi_get_drvdata(n_di->spi);
-       err = kstrtouint(buf, 0, &val);
-       if (err < 0) goto err_end;
-       if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map && n_spi->features && n_spi->features->di_count > n_di->di_index) {
-               regmap_write(n_spi->reg_map, n_spi->regstart_table->di_deboun_reg + n_di->di_index, val);
-       }
-err_end:
-       return count;
-}
-
-static ssize_t neuronspi_spi_gpio_di_show_value(struct device *dev, struct device_attribute *attr, char *buf)
-{
-       ssize_t ret = 0;
-       int val;
-       struct neuronspi_di_driver *n_di;
-       struct neuronspi_driver_data *n_spi;
-       struct platform_device *plat = to_platform_device(dev);
-       n_di = platform_get_drvdata(plat);
-       n_spi = spi_get_drvdata(n_di->spi);
-       if (n_spi && n_spi->combination_id != -1 && n_spi->features && n_spi->features->di_count > n_di->di_index) {
-               regmap_read(n_spi->reg_map, n_spi->regstart_table->di_val_reg + (n_di->di_index / 16), &val);
-               val &= 0x1 << (n_di->di_index % 15);
-               val = val >> (n_di->di_index % 15);
-               ret = scnprintf(buf, 255, "%d\n", val);
-       }
-       return ret;
-}
-
-static ssize_t neuronspi_spi_gpio_do_show_value(struct device *dev, struct device_attribute *attr, char *buf)
-{
-       ssize_t ret = 0;
-       int val;
-       struct neuronspi_do_driver *n_do;
-       struct neuronspi_driver_data *n_spi;
-       struct platform_device *plat = to_platform_device(dev);
-       n_do = platform_get_drvdata(plat);
-       n_spi = spi_get_drvdata(n_do->spi);
-       if (n_spi && n_spi->combination_id != -1 && n_spi->features && n_spi->features->do_count > n_do->do_index) {
-               regmap_read(n_spi->reg_map, n_spi->regstart_table->do_val_reg + (n_do->do_index / 16), &val);
-               val &= 0x1 << (n_do->do_index % 15);
-               val = val >> (n_do->do_index % 15);
-               ret = scnprintf(buf, 255, "%d\n", val);
-       }
-       return ret;
-}
-
-static ssize_t neuronspi_spi_gpio_do_store_value(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-       ssize_t err = 0;
-       int inp = 0;
-       unsigned int val;
-       struct neuronspi_do_driver *n_do;
-       struct neuronspi_driver_data *n_spi;
-       struct platform_device *plat = to_platform_device(dev);
-       n_do = platform_get_drvdata(plat);
-       n_spi = spi_get_drvdata(n_do->spi);
-       err = kstrtoint(buf, 0, &inp);
-       if (err < 0) goto err_end;
-       if (inp > 1 || inp < 0) {
-               goto err_end;
-       }
-       if (n_spi && n_spi->combination_id != -1 && n_spi->features && n_spi->features->do_count > n_do->do_index) {
-               regmap_read(n_spi->reg_map, n_spi->regstart_table->do_val_reg + (n_do->do_index / 16), &val);
-               val &= ~(0x1 << (n_do->do_index % 15));
-               val |= inp << (n_do->do_index % 15);
-               regmap_write(n_spi->reg_map, n_spi->regstart_table->do_val_reg + (n_do->do_index / 16), val);
-       }
-err_end:
-       return count;
-}
-
-static ssize_t neuronspi_spi_gpio_ro_show_value(struct device *dev, struct device_attribute *attr, char *buf)
-{
-       ssize_t ret = 0;
-       int val;
-       struct neuronspi_ro_driver *n_ro;
-       struct neuronspi_driver_data *n_spi;
-       struct platform_device *plat = to_platform_device(dev);
-       n_ro = platform_get_drvdata(plat);
-       n_spi = spi_get_drvdata(n_ro->spi);
-       if (n_spi && n_spi->combination_id != -1 && n_spi->features && n_spi->features->ro_count > n_ro->ro_index) {
-               regmap_read(n_spi->reg_map, n_spi->regstart_table->ro_val_reg + (n_ro->ro_index / 16), &val);
-               val &= 0x1 << (n_ro->ro_index % 15);
-               val = val >> (n_ro->ro_index % 15);
-               ret = scnprintf(buf, 255, "%d\n", val);
-       }
-       return ret;
-}
-
-static ssize_t neuronspi_spi_gpio_ro_store_value(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-       ssize_t err = 0;
-       int inp = 0;
-       unsigned int val;
-       struct neuronspi_ro_driver *n_ro;
-       struct neuronspi_driver_data *n_spi;
-       struct platform_device *plat = to_platform_device(dev);
-       n_ro = platform_get_drvdata(plat);
-       n_spi = spi_get_drvdata(n_ro->spi);
-       err = kstrtoint(buf, 0, &inp);
-       if (err < 0) goto err_end;
-       if (inp > 1 || inp < 0) {
-               goto err_end;
-       }
-       if (n_spi && n_spi->combination_id != -1 && n_spi->features && n_spi->features->ro_count > n_ro->ro_index) {
-               regmap_read(n_spi->reg_map, n_spi->regstart_table->ro_val_reg + (n_ro->ro_index / 16), &val);
-               val &= ~(0x1 << (n_ro->ro_index % 15));
-               val |= inp << (n_ro->ro_index % 15);
-               regmap_write(n_spi->reg_map, n_spi->regstart_table->ro_val_reg + (n_ro->ro_index / 16), val);
-       }
-err_end:
-       return count;
-}
-
-
-static ssize_t neuronspi_spi_gpio_show_ds_enable(struct device *dev, struct device_attribute *attr, char *buf)
-{
-       ssize_t ret = 0;
-       int val;
-       struct neuronspi_di_driver *n_di;
-       struct neuronspi_driver_data *n_spi;
-       struct platform_device *plat = to_platform_device(dev);
-       n_di = platform_get_drvdata(plat);
-       n_spi = spi_get_drvdata(n_di->spi);
-       if (n_spi && n_spi->combination_id != -1 && n_spi->features && n_spi->features->ds_count) {
-               regmap_read(n_spi->reg_map, n_spi->regstart_table->di_direct_reg + (n_di->di_index / 16), &val);
-               val &= 0x1 << (n_di->di_index % 15);
-               val = val >> (n_di->di_index % 15);
-               ret = scnprintf(buf, 255, "%d\n", val);
-       }
-       return ret;
-}
-
-static ssize_t neuronspi_spi_gpio_show_ds_toggle(struct device *dev, struct device_attribute *attr, char *buf)
-{
-       ssize_t ret = 0;
-       int val;
-       struct neuronspi_di_driver *n_di;
-       struct neuronspi_driver_data *n_spi;
-       struct platform_device *plat = to_platform_device(dev);
-       n_di = platform_get_drvdata(plat);
-       n_spi = spi_get_drvdata(n_di->spi);
-       if (n_spi && n_spi->combination_id != -1 && n_spi->features && n_spi->features->ds_count) {
-               regmap_read(n_spi->reg_map, n_spi->regstart_table->di_toggle_reg + (n_di->di_index / 16), &val);
-               val &= 0x1 << (n_di->di_index % 15);
-               val = val >> (n_di->di_index % 15);
-               ret = scnprintf(buf, 255, "%d\n", val);
-       }
-       return ret;
-}
-
-static ssize_t neuronspi_spi_gpio_show_ds_polarity(struct device *dev, struct device_attribute *attr, char *buf)
-{
-       ssize_t ret = 0;
-       int val;
-       struct neuronspi_di_driver *n_di;
-       struct neuronspi_driver_data *n_spi;
-       struct platform_device *plat = to_platform_device(dev);
-       n_di = platform_get_drvdata(plat);
-       n_spi = spi_get_drvdata(n_di->spi);
-       if (n_spi && n_spi->combination_id != -1 && n_spi->features && n_spi->features->ds_count) {
-               regmap_read(n_spi->reg_map, n_spi->regstart_table->di_polar_reg + (n_di->di_index / 16), &val);
-               val &= 0x1 << (n_di->di_index % 15);
-               val = val >> (n_di->di_index % 15);
-               ret = scnprintf(buf, 255, "%d\n", val);
-       }
-       return ret;
-}
-
-static ssize_t neuronspi_spi_gpio_store_ds_enable(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-       ssize_t err = 0;
-       int inp = 0;
-       unsigned int val;
-       struct neuronspi_di_driver *n_di;
-       struct neuronspi_driver_data *n_spi;
-       struct platform_device *plat = to_platform_device(dev);
-       n_di = platform_get_drvdata(plat);
-       n_spi = spi_get_drvdata(n_di->spi);
-       err = kstrtoint(buf, 0, &inp);
-       if (err < 0) goto err_end;
-       if (inp > 1 || inp < 0) {
-               goto err_end;
-       }
-       if (n_spi && n_spi->combination_id != -1 && n_spi->features && n_spi->features->ds_count) {
-               regmap_read(n_spi->reg_map, n_spi->regstart_table->di_direct_reg + (n_di->di_index / 16), &val);
-               val &= ~(0x1 << (n_di->di_index % 15));
-               val |= inp << (n_di->di_index % 15);
-               regmap_write(n_spi->reg_map, n_spi->regstart_table->di_direct_reg + (n_di->di_index / 16), val);
-       }
-err_end:
-       return count;
-}
-
-static ssize_t neuronspi_spi_gpio_store_ds_toggle(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-       ssize_t err = 0;
-       int inp = 0;
-       unsigned int val;
-       struct neuronspi_di_driver *n_di;
-       struct neuronspi_driver_data *n_spi;
-       struct platform_device *plat = to_platform_device(dev);
-       n_di = platform_get_drvdata(plat);
-       n_spi = spi_get_drvdata(n_di->spi);
-       err = kstrtoint(buf, 0, &inp);
-       if (err < 0) goto err_end;
-       if (inp > 1 || inp < 0) {
-               goto err_end;
-       }
-       if (n_spi && n_spi->combination_id != -1 && n_spi->features && n_spi->features->ds_count) {
-               regmap_read(n_spi->reg_map, n_spi->regstart_table->di_toggle_reg + (n_di->di_index / 16), &val);
-               val &= ~(0x1 << (n_di->di_index % 15));
-               val |= inp << (n_di->di_index % 15);
-               regmap_write(n_spi->reg_map, n_spi->regstart_table->di_toggle_reg + (n_di->di_index / 16), val);
-       }
-err_end:
-       return count;
-}
-
-static ssize_t neuronspi_spi_gpio_store_ds_polarity(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-       ssize_t err = 0;
-       int inp = 0;
-       unsigned int val;
-       struct neuronspi_di_driver *n_di;
-       struct neuronspi_driver_data *n_spi;
-       struct platform_device *plat = to_platform_device(dev);
-       n_di = platform_get_drvdata(plat);
-       n_spi = spi_get_drvdata(n_di->spi);
-       err = kstrtoint(buf, 0, &inp);
-       if (err < 0) goto err_end;
-       if (inp > 1 || inp < 0) {
-               goto err_end;
-       }
-       if (n_spi && n_spi->combination_id != -1 && n_spi->features && n_spi->features->ds_count) {
-               regmap_read(n_spi->reg_map, n_spi->regstart_table->di_polar_reg + (n_di->di_index / 16), &val);
-               val &= ~(0x1 << (n_di->di_index % 15));
-               val |= inp << (n_di->di_index % 15);
-               regmap_write(n_spi->reg_map, n_spi->regstart_table->di_polar_reg + (n_di->di_index / 16), val);
-       }
-err_end:
-       return count;
-}
-
-static ssize_t neuronspi_show_regmap(struct device *dev, struct device_attribute *attr, char *buf)
-{
-       ssize_t ret = 0;
-       u32 val = 0;
-       struct neuronspi_driver_data *n_spi;
-       struct platform_device *plat = to_platform_device(dev);
-       n_spi = platform_get_drvdata(plat);
-       if (n_spi && n_spi->reg_map) {
-               spin_lock(&n_spi->sysfs_regmap_lock);
-               regmap_read(n_spi->reg_map, n_spi->sysfs_regmap_target, &val);
-               ret = scnprintf(buf, 255, "%x\n", val);
-               spin_unlock(&n_spi->sysfs_regmap_lock);
-       }
-       return ret;
-}
-
-static ssize_t neuronspi_store_regmap(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-       ssize_t err = 0;
-       unsigned int val = 0;
-       struct neuronspi_driver_data *n_spi;
-       struct platform_device *plat = to_platform_device(dev);
-       n_spi = platform_get_drvdata(plat);
-       err = kstrtouint(buf, 0, &val);
-       if (err < 0) goto err_end;
-       if (n_spi && n_spi->reg_map && val < 65536) {
-               spin_lock(&n_spi->sysfs_regmap_lock);
-               n_spi->sysfs_regmap_target = val;
-               spin_unlock(&n_spi->sysfs_regmap_lock);
-       }
-err_end:
-       return count;
-}
-
-static ssize_t neuronspi_spi_show_board(struct device *dev, struct device_attribute *attr, char *buf)
-{
-       ssize_t ret = 0;
-       struct neuronspi_driver_data *n_spi;
-       struct platform_device *plat = to_platform_device(dev);
-       n_spi = platform_get_drvdata(plat);
-       if (n_spi->combination_id != -1 && n_spi->combination_id < NEURONSPI_BOARDTABLE_LEN) {
-               ret = scnprintf(buf, 255, "%s\n", NEURONSPI_BOARDTABLE[n_spi->combination_id].definition->combination_name);
-       }
-       return ret;
-}
-
-static ssize_t neuronspi_spi_show_lboard_id(struct device *dev, struct device_attribute *attr, char *buf)
-{
-       ssize_t ret = 0;
-       struct neuronspi_driver_data *n_spi;
-       struct platform_device *plat = to_platform_device(dev);
-       n_spi = platform_get_drvdata(plat);
-       if (n_spi->combination_id != -1 && n_spi->combination_id < NEURONSPI_BOARDTABLE_LEN) {
-               ret = scnprintf(buf, 255, "%d\n", NEURONSPI_BOARDTABLE[n_spi->combination_id].definition->lower_board_id);
-       }
-       return ret;
-}
-
-static ssize_t neuronspi_spi_show_uboard_id(struct device *dev, struct device_attribute *attr, char *buf)
-{
-       ssize_t ret = 0;
-       struct neuronspi_driver_data *n_spi;
-       struct platform_device *plat = to_platform_device(dev);
-       n_spi = platform_get_drvdata(plat);
-       if (n_spi->combination_id != -1 && n_spi->combination_id < NEURONSPI_BOARDTABLE_LEN) {
-               ret = scnprintf(buf, 255, "%d\n", NEURONSPI_BOARDTABLE[n_spi->combination_id].definition->upper_board_id);
-       }
-       return ret;
-}
-
-static ssize_t neuronspi_spi_gpio_show_do_prefix(struct device *dev, struct device_attribute *attr, char *buf)
-{
-       ssize_t ret = 0;
-       struct neuronspi_do_driver *n_do;
-       struct neuronspi_driver_data *n_spi;
-       struct platform_device *plat = to_platform_device(dev);
-       n_do = platform_get_drvdata(plat);
-       n_spi = spi_get_drvdata(n_do->spi);
-       if (n_spi->features && n_spi->features->do_count > 0 && n_spi->do_driver) {
-               ret = scnprintf(buf, 255, "%s_%d\n", n_spi->do_driver[n_do->do_index]->gpio_c.label, n_spi->neuron_index + 1);
-       }
-       return ret;
-}
-
-static ssize_t neuronspi_spi_gpio_show_di_prefix(struct device *dev, struct device_attribute *attr, char *buf)
-{
-       ssize_t ret = 0;
-       struct neuronspi_di_driver *n_di;
-       struct neuronspi_driver_data *n_spi;
-       struct platform_device *plat = to_platform_device(dev);
-       n_di = platform_get_drvdata(plat);
-       n_spi = spi_get_drvdata(n_di->spi);
-       if (n_spi->features && n_spi->features->di_count > 0 && n_spi->di_driver) {
-               ret = scnprintf(buf, 255, "%s_%d\n", n_spi->di_driver[n_di->di_index]->gpio_c.label, n_spi->neuron_index + 1);
-       }
-       return ret;
-}
-
-static ssize_t neuronspi_spi_gpio_show_ro_prefix(struct device *dev, struct device_attribute *attr, char *buf)
-{
-       ssize_t ret = 0;
-       struct neuronspi_ro_driver *n_ro;
-       struct neuronspi_driver_data *n_spi;
-       struct platform_device *plat = to_platform_device(dev);
-       n_ro = platform_get_drvdata(plat);
-       n_spi = spi_get_drvdata(n_ro->spi);
-       if (n_spi->features && n_spi->features->ro_count > 0 && n_spi->ro_driver) {
-               ret = scnprintf(buf, 255, "%s_%d\n", n_spi->ro_driver[n_ro->ro_index]->gpio_c.label, n_spi->neuron_index + 1);
-       }
-       return ret;
-}
-
-static ssize_t neuronspi_spi_gpio_show_do_base(struct device *dev, struct device_attribute *attr, char *buf)
-{
-       ssize_t ret = 0;
-       struct neuronspi_do_driver *n_do;
-       struct neuronspi_driver_data *n_spi;
-       struct platform_device *plat = to_platform_device(dev);
-       n_do = platform_get_drvdata(plat);
-       n_spi = spi_get_drvdata(n_do->spi);
-       if (n_spi->features && n_spi->features->do_count > 0 && n_spi->do_driver) {
-               ret = scnprintf(buf, 255, "%d\n", n_spi->do_driver[n_do->do_index]->gpio_c.base);
-       }
-       return ret;
-}
-
-static ssize_t neuronspi_spi_gpio_show_di_base(struct device *dev, struct device_attribute *attr, char *buf)
+int neuronspi_spi_gpio_di_get(struct spi_device* spi_dev, u32 id)
 {
-       ssize_t ret = 0;
-       struct neuronspi_di_driver *n_di;
-       struct neuronspi_driver_data *n_spi;
-       struct platform_device *plat = to_platform_device(dev);
-       n_di = platform_get_drvdata(plat);
-       n_spi = spi_get_drvdata(n_di->spi);
-       if (n_spi->features && n_spi->features->di_count > 0 && n_spi->di_driver) {
-               ret = scnprintf(buf, 255, "%d\n", n_spi->di_driver[n_di->di_index]->gpio_c.base);
+       u8 *recv_buf;
+       bool ret = 0;
+       u32 offset = id / 16;
+       struct neuronspi_driver_data *d_data = spi_get_drvdata(spi_dev);
+       recv_buf = kzalloc(4, GFP_KERNEL);
+       printk(KERN_INFO "NEURONSPI: REGMAP TEST: %d\n", regmap_read(d_data->reg_map, d_data->regstart_table->di_val_reg + offset, (void*)recv_buf));
+       if (*recv_buf & (0x1 << offset)) {
+               ret = 1;
        }
+       kfree(recv_buf);
+       printk(KERN_INFO "NEURONSPI: GPIO DI %d get %d\n", id, ret);
        return ret;
 }
 
-static ssize_t neuronspi_spi_gpio_show_ro_base(struct device *dev, struct device_attribute *attr, char *buf)
+int neuronspi_spi_gpio_do_set(struct spi_device* spi_dev, u32 id, int value)
 {
-       ssize_t ret = 0;
-       struct neuronspi_ro_driver *n_ro;
-       struct neuronspi_driver_data *n_spi;
-       struct platform_device *plat = to_platform_device(dev);
-       n_ro = platform_get_drvdata(plat);
-       n_spi = spi_get_drvdata(n_ro->spi);
-       if (n_spi->features && n_spi->features->ro_count > 0 && n_spi->ro_driver) {
-               ret = scnprintf(buf, 255, "%d\n", n_spi->ro_driver[n_ro->ro_index]->gpio_c.base);
-       }
+       u32 current_value = 0;
+       bool ret = 0;
+       u32 offset = id / 16;
+       u16 off_val = value << (id % 16);
+       u16 mask = ~(1 << (id % 16));
+       struct neuronspi_driver_data *d_data = spi_get_drvdata(spi_dev);
+       regmap_read(d_data->reg_map, d_data->regstart_table->do_val_reg + offset, &current_value);
+       current_value&= mask;
+       current_value|= off_val;
+       regmap_write(d_data->reg_map, d_data->regstart_table->do_val_reg + offset, current_value);
+       printk(KERN_INFO "NEURONSPI: GPIO DO %d set %d\n", id, value);
        return ret;
 }
 
-static ssize_t neuronspi_spi_gpio_show_do_count(struct device *dev, struct device_attribute *attr, char *buf)
+int neuronspi_spi_gpio_ro_set(struct spi_device* spi_dev, u32 id, int value)
 {
-       ssize_t ret = 0;
-       struct neuronspi_do_driver *n_do;
-       struct neuronspi_driver_data *n_spi;
-       struct platform_device *plat = to_platform_device(dev);
-       n_do = platform_get_drvdata(plat);
-       n_spi = spi_get_drvdata(n_do->spi);
-       if (n_spi->features && n_spi->features->do_count > 0 && n_spi->do_driver) {
-               ret = scnprintf(buf, 255, "%d\n", n_spi->do_driver[n_do->do_index]->gpio_c.ngpio);
-       }
+       u32 current_value = 0;
+       bool ret = 0;
+       u32 offset = id / 16;
+       u16 off_val = value << (id % 16);
+       u16 mask = ~(1 << (id % 16));
+       struct neuronspi_driver_data *d_data = spi_get_drvdata(spi_dev);
+       regmap_read(d_data->reg_map, d_data->regstart_table->ro_val_reg + offset, &current_value);
+       current_value&= mask;
+       current_value|= off_val;
+       regmap_write(d_data->reg_map, d_data->regstart_table->ro_val_reg + offset, current_value);
+       printk(KERN_INFO "NEURONSPI: GPIO RO %d set %d\n", id, value);
        return ret;
 }
 
-static ssize_t neuronspi_spi_gpio_show_di_count(struct device *dev, struct device_attribute *attr, char *buf)
-{
-       ssize_t ret = 0;
-       struct neuronspi_di_driver *n_di;
-       struct neuronspi_driver_data *n_spi;
-       struct platform_device *plat = to_platform_device(dev);
-       n_di = platform_get_drvdata(plat);
-       n_spi = spi_get_drvdata(n_di->spi);
-       if (n_spi->features && n_spi->features->di_count > 0 && n_spi->di_driver) {
-               ret = scnprintf(buf, 255, "%d\n", n_spi->di_driver[n_di->di_index]->gpio_c.ngpio);
-       }
-       return ret;
-}
 
-static ssize_t neuronspi_spi_gpio_show_ro_count(struct device *dev, struct device_attribute *attr, char *buf)
-{
-       ssize_t ret = 0;
-       struct neuronspi_ro_driver *n_ro;
-       struct neuronspi_driver_data *n_spi;
-       struct platform_device *plat = to_platform_device(dev);
-       n_ro = platform_get_drvdata(plat);
-       n_spi = spi_get_drvdata(n_ro->spi);
-       if (n_spi->features && n_spi->features->ro_count > 0 && n_spi->ro_driver) {
-               ret = scnprintf(buf, 255, "%d\n", n_spi->ro_driver[n_ro->ro_index]->gpio_c.ngpio);
-       }
-       return ret;
-}
 
-static s32 neuronspi_spi_probe(struct spi_device *spi)
+s32 neuronspi_spi_probe(struct spi_device *spi)
 {
        const struct neuronspi_devtype *devtype;
        struct sched_param sched_param = { .sched_priority = MAX_RT_PRIO / 2 };
@@ -3005,7 +1057,6 @@ reg1001: %x, reg1002: %x, reg1003: %x, reg1004: %x\n",
                for (i = 0; i < n_spi->features->led_count; i++) {
                        kthread_init_work(&(n_spi->led_driver[i].led_work), neuronspi_led_proc);
                }
-
        }
 
 
@@ -3277,7 +1328,36 @@ reg1001: %x, reg1002: %x, reg1003: %x, reg1004: %x\n",
        return ret;
 }
 
-static s32 neuronspi_spi_remove(struct spi_device *spi)
+u32 neuronspi_spi_uart_get_cflag(struct spi_device* spi_dev, u8 port)
+{
+       u8 *message_buf;
+       u8 *recv_buf;
+       u16 crc1, crc2, ret;
+       struct neuronspi_driver_data *d_data = spi_get_drvdata(spi_dev);
+       s32 frequency = NEURONSPI_COMMON_FREQ;
+       if (d_data->slower_model) {
+               frequency = NEURONSPI_SLOWER_FREQ;
+       }
+       message_buf = kzalloc(NEURONSPI_SPI_UART_GET_CFLAG_MESSAGE_LEN, GFP_KERNEL);
+       recv_buf = kzalloc(NEURONSPI_SPI_UART_GET_CFLAG_MESSAGE_LEN, GFP_KERNEL);
+       memcpy(message_buf, NEURONSPI_SPI_UART_GET_CFLAG_MESSAGE, NEURONSPI_SPI_UART_GET_CFLAG_MESSAGE_LEN);
+       crc1 = neuronspi_spi_crc(message_buf, 4, 0);
+       memcpy(&message_buf[4], &crc1, 2);
+       crc2 = neuronspi_spi_crc(&message_buf[6], NEURONSPI_SPI_UART_GET_CFLAG_MESSAGE_LEN - 8, crc1);
+       memcpy(&message_buf[NEURONSPI_SPI_UART_GET_CFLAG_MESSAGE_LEN - 2], &crc2, 2);
+       if (!d_data->reserved_device) {
+               neuronspi_spi_send_message(spi_dev, message_buf, recv_buf, NEURONSPI_SPI_UART_GET_CFLAG_MESSAGE_LEN, frequency, 65, 1);
+       }
+       ret = ((u32*)recv_buf)[5];
+#if NEURONSPI_DETAILED_DEBUG > 0
+       printk(KERN_INFO "NEURONSPI: SPI TERMIOS Get, Dev-CS:%d, val:%x\n", spi_dev->chip_select, ret);
+#endif
+       kfree(message_buf);
+       kfree(recv_buf);
+       return ret;
+}
+
+s32 neuronspi_spi_remove(struct spi_device *spi)
 {
        int i;
        struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi);
@@ -3362,7 +1442,7 @@ static s32 neuronspi_spi_remove(struct spi_device *spi)
        return 0;
 }
 
-static s32 char_register_driver(void)
+s32 char_register_driver(void)
 {
        s32 ret = 0;
 
@@ -3404,7 +1484,7 @@ static s32 char_register_driver(void)
        return ret;
 }
 
-static s32 char_unregister_driver(void)
+s32 char_unregister_driver(void)
 {
        device_destroy(neuronspi_cdrv.driver_class, MKDEV(neuronspi_cdrv.major_number, 0));     // Destroy the device
        class_unregister(neuronspi_cdrv.driver_class);                                                          // Unregister the class
index fddc04eaa6afbc4e7566a54e2dbb897a984b4df5..3f73461c3dd62b5f9cd3d6b601dbdb70f5dfd8f5 100644 (file)
  *
  */
 
-#ifndef NEURONSPI_H_
-#define NEURONSPI_H_
+#ifndef MODULES_NEURON_SPI_SRC_UNIPI_SPI_H_
+#define MODULES_NEURON_SPI_SRC_UNIPI_SPI_H_
+
 
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 #define NEURONSPI_SCHED_REQUIRED 0 // Older kernels do not require sched/types to be specifically imported
 
 #define NEURONSPI_MAJOR_VERSIONSTRING "Development Beta Version 0.02:12:02:2018"
 #include <asm/termbits.h>
 #include <asm/gpio.h>
 
-/********************************
- * HW Constants Data Structures *
- ********************************/
-
-struct neuronspi_board_entry {
-       u16             index;
-       u16             lower_board_id;
-       u16             upper_board_id;
-       u16             data_register_count;
-       u16             config_register_count;
-       struct neuronspi_board_combination *definition;
-};
-
-struct neuronspi_register_block
-{
-       u32     starting_register;
-       u32     register_count;
-       u32             *register_flags;
-};
-
-struct neuronspi_board_features
-{
-       u32             do_count;
-       u32             ro_count;
-       u32             ds_count;
-       u32             di_count;
-       u32             led_count;
-       u32             stm_ai_count;
-       u32             stm_ao_count;
-       u32             sec_ai_count;
-       u32             sec_ao_count;
-       u32             uart_master_count;
-       u32             uart_slave_count;
-       u32             pwm_channel_count;
-       u32             wd_count;
-       u32             extension_sys_count;
-       u32             light_count;
-       u32             owire_count;
-};
-
-struct neuronspi_board_regstart_table
-{
-       u32             do_val_reg;
-       u32             do_val_coil;
-       u32             do_pwm_reg;
-       u32             do_pwm_ps_reg;
-       u32             do_pwm_c_reg;
-       u32             di_val_reg;
-       u32             di_counter_reg;
-       u32             di_direct_reg;
-       u32             di_deboun_reg;
-       u32             di_polar_reg;
-       u32             di_toggle_reg;
-       u32             uart_queue_reg;
-       u32             uart_conf_reg;
-       u32             uart_address_reg;
-       u32             led_val_coil;
-       u32             led_val_reg;
-       u32             wd_val_reg;
-       u32             wd_timeout_reg;
-       u32             wd_nv_sav_coil;
-       u32             wd_reset_coil;
-       u32             reg_start_reg;
-       u32             ro_val_reg;
-       u32             ro_val_coil;
-       u32             vref_inp;
-       u32             vref_int;
-       u32             stm_ao_val_reg;
-       u32             stm_ao_mode_reg;
-       u32             stm_ao_vol_err;
-       u32             stm_ao_vol_off;
-       u32             stm_ao_curr_err;
-       u32             stm_ao_curr_off;
-       u32             stm_ai_val_reg;
-       u32             stm_ai_mode_reg;
-       u32             stm_ai_curr_err;
-       u32             stm_ai_curr_off;
-       u32             stm_ai_vol_err;
-       u32             stm_ai_vol_off;
-       u32             stm_aio_val_reg;
-       u32             stm_aio_vol_err;
-       u32             stm_aio_vol_off;
-       u32             sec_ao_val_reg;
-       u32             sec_ao_mode_reg;
-       u32             sec_ai_val_reg;
-       u32             sec_ai_mode_reg;
-       u32             sys_serial_num;
-       u32             sys_hw_ver;
-       u32             sys_hw_flash_ver;
-       u32             sys_sw_ver;
-};
-
-struct neuronspi_board_combination
-{
-       u32                                                                     combination_board_id;
-       uint16_t                                                        lower_board_id;
-       uint16_t                                                        upper_board_id;
-       u32                                                             block_count;
-       size_t                                                          name_length;
-       const char*                                                     combination_name;
-       struct neuronspi_board_features         features;
-       u32                                                                     *blocks;
-};
-
-struct neuronspi_model_definition
-{
-       size_t                                                          eeprom_length;
-       const char*                                             eeprom_name;
-       size_t                                                          name_length;
-       const char*                                                     model_name;
-       u32                                                                     combination_count;
-       struct neuronspi_board_combination *combinations;
-};
-
-/***************
- * Definitions *
- ***************/
-
-#define NEURONSPI_MAX_DEVS                             3
-#define NEURONSPI_MAX_UART                             128
-#define NEURONSPI_BUFFER_MAX                   1152
-#define NEURONSPI_HEADER_LENGTH                10
-#define NEURONSPI_FIRST_MESSAGE_LENGTH 6
-#define NEURONSPI_EDGE_DELAY                   10
-#define NEURONSPI_B_PER_WORD                   8
-#define NEURONSPI_DEFAULT_FREQ                 600000
-#define NEURONSPI_COMMON_FREQ                  12000000
-#define NEURONSPI_SLOWER_FREQ                  8000000
-#define NEURONSPI_MAX_TX                               62
-#define NEURONSPI_MAX_BAUD                             115200
-#define NEURONSPI_FIFO_SIZE                            256
-#define NEURONSPI_DETAILED_DEBUG               0
-#define NEURONSPI_LAST_TRANSFER_DELAY  40
-
-
-#define NEURON_DEVICE_NAME                             "neuronspi"
-#define NEURON_DEVICE_CLASS                    "modbus_spi"
-#define NEURON_DRIVER_NAME                             "NEURONSPI"
-#define PORT_NEURONSPI                                 184
-
-#define STRICT_RESERVING
-#define NEURONSPI_ALWAYS_EXPORT
-
-#define NEURONSPI_GET_COIL_READ_PHASE2_BYTE_LENGTH(X)  ((((X) + 15) >> 4) << 1)
-
-#define NEURONSPI_NO_INTERRUPT_MODELS_LEN                              3
-const uint16_t NEURONSPI_NO_INTERRUPT_MODELS[NEURONSPI_NO_INTERRUPT_MODELS_LEN] = {
-               0xb10, 0xc10, 0xf10
-};
+#include "unipi_common.h"
+#include "unipi_platform.h"
+#include "unipi_sysfs.h"
+#include "unipi_iio.h"
 
 #define NEURONSPI_SLOWER_MODELS_LEN                                    3
-const uint16_t NEURONSPI_SLOWER_MODELS[NEURONSPI_SLOWER_MODELS_LEN] = {
+static const uint16_t NEURONSPI_SLOWER_MODELS[NEURONSPI_SLOWER_MODELS_LEN] = {
                0xb10, 0xc10, 0xf10
 };
 
 #define NEURONSPI_PROBE_MESSAGE_LEN                                            22
-const u8 NEURONSPI_PROBE_MESSAGE[NEURONSPI_PROBE_MESSAGE_LEN] = {
+static const u8 NEURONSPI_PROBE_MESSAGE[NEURONSPI_PROBE_MESSAGE_LEN] = {
                0x04, 0x0e, 0xe8, 0x03, 0xa0, 0xdd,
                0x04, 0x00, 0xe8, 0x03, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -208,63 +63,63 @@ const u8 NEURONSPI_PROBE_MESSAGE[NEURONSPI_PROBE_MESSAGE_LEN] = {
 };
 
 #define NEURONSPI_UART_PROBE_MESSAGE_LEN                               6
-const u8 NEURONSPI_UART_PROBE_MESSAGE[NEURONSPI_UART_PROBE_MESSAGE_LEN] = {
+static const u8 NEURONSPI_UART_PROBE_MESSAGE[NEURONSPI_UART_PROBE_MESSAGE_LEN] = {
                0xfa, 0x00, 0x55, 0x0e, 0xb6, 0x0a
 };
 
 #define NEURONSPI_SPI_UART_SHORT_MESSAGE_LEN                   6
-const u8 NEURONSPI_SPI_UART_SHORT_MESSAGE[NEURONSPI_SPI_UART_SHORT_MESSAGE_LEN] = {
+static const u8 NEURONSPI_SPI_UART_SHORT_MESSAGE[NEURONSPI_SPI_UART_SHORT_MESSAGE_LEN] = {
                0x41, 0x00, 0x00, 0x00, 0x00, 0x00
 };
 
 #define NEURONSPI_SPI_UART_LONG_MESSAGE_LEN                            8
-const u8 NEURONSPI_SPI_UART_LONG_MESSAGE[NEURONSPI_SPI_UART_LONG_MESSAGE_LEN] = {
+static const u8 NEURONSPI_SPI_UART_LONG_MESSAGE[NEURONSPI_SPI_UART_LONG_MESSAGE_LEN] = {
                0x64, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00
 };
 
 #define NEURONSPI_SPI_UART_READ_MESSAGE_LEN                            14
-const u8 NEURONSPI_SPI_UART_READ_MESSAGE[NEURONSPI_SPI_UART_READ_MESSAGE_LEN] = {
+static const u8 NEURONSPI_SPI_UART_READ_MESSAGE[NEURONSPI_SPI_UART_READ_MESSAGE_LEN] = {
                0x65, 0x06, 0x00, 0x00, 0x44, 0x69,
                0x65, 0x03, 0x00, 0x00, 0x00, 0x05,
                0x6a, 0x0c
 };
 
 #define NEURONSPI_SPI_IRQ_SET_MESSAGE_LEN                              14
-const u8 NEURONSPI_SPI_IRQ_SET_MESSAGE[NEURONSPI_SPI_UART_READ_MESSAGE_LEN] = {
+static const u8 NEURONSPI_SPI_IRQ_SET_MESSAGE[NEURONSPI_SPI_UART_READ_MESSAGE_LEN] = {
                0x06, 0x06, 0xef, 0x03, 0x00, 0x00,
                0x06, 0x01, 0xef, 0x03, 0x05, 0x00,
                0x00, 0x00
 };
 
 #define NEURONSPI_SPI_UART_GET_CFLAG_MESSAGE_LEN               16
-const u8 NEURONSPI_SPI_UART_GET_CFLAG_MESSAGE[NEURONSPI_SPI_UART_GET_CFLAG_MESSAGE_LEN] = {
+static const u8 NEURONSPI_SPI_UART_GET_CFLAG_MESSAGE[NEURONSPI_SPI_UART_GET_CFLAG_MESSAGE_LEN] = {
                0x04, 0x08, 0xf4, 0x01, 0x00, 0x00,
                0x04, 0x02, 0xf4, 0x01, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00
 };
 
 #define NEURONSPI_SPI_UART_GET_LDISC_MESSAGE_LEN               16
-const u8 NEURONSPI_SPI_UART_GET_LDISC_MESSAGE[NEURONSPI_SPI_UART_GET_LDISC_MESSAGE_LEN] = {
+static const u8 NEURONSPI_SPI_UART_GET_LDISC_MESSAGE[NEURONSPI_SPI_UART_GET_LDISC_MESSAGE_LEN] = {
                0x04, 0x08, 0xf6, 0x01, 0x00, 0x00,
                0x04, 0x02, 0xf6, 0x01, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00
 };
 
 #define NEURONSPI_SPI_UART_SET_CFLAG_MESSAGE_LEN               16
-const u8 NEURONSPI_SPI_UART_SET_CFLAG_MESSAGE[NEURONSPI_SPI_UART_SET_CFLAG_MESSAGE_LEN] = {
+static const u8 NEURONSPI_SPI_UART_SET_CFLAG_MESSAGE[NEURONSPI_SPI_UART_SET_CFLAG_MESSAGE_LEN] = {
                0x06, 0x08, 0xf4, 0x01, 0x00, 0x00,
                0x06, 0x02, 0xf4, 0x01, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00
 };
 
 #define NEURONSPI_SPI_LED_SET_MESSAGE_LEN                              6
-const u8 NEURONSPI_SPI_LED_SET_MESSAGE[NEURONSPI_SPI_LED_SET_MESSAGE_LEN] = {
+static const u8 NEURONSPI_SPI_LED_SET_MESSAGE[NEURONSPI_SPI_LED_SET_MESSAGE_LEN] = {
                0x05, 0x00, 0x08, 0x00, 0x00, 0x00
 };
 
 #define NEURONSPI_CRC16TABLE_LEN                                               256
-const uint16_t NEURONSPI_CRC16TABLE[NEURONSPI_CRC16TABLE_LEN] = {
+static const uint16_t NEURONSPI_CRC16TABLE[NEURONSPI_CRC16TABLE_LEN] = {
     0,  1408,  3968,  2560,  7040,  7680,  5120,  4480, 13184, 13824, 15360,
 14720, 10240, 11648, 10112,  8704, 25472, 26112, 27648, 27008, 30720, 32128,
 30592, 29184, 20480, 21888, 24448, 23040, 19328, 19968, 17408, 16768, 50048,
@@ -291,1587 +146,6 @@ const uint16_t NEURONSPI_CRC16TABLE[NEURONSPI_CRC16TABLE_LEN] = {
  3458,  1922,   514
 };
 
-/******************
- * HW Definitions *
- ******************/
-// Lower Boards:
-#define NEURONSPI_BOARD_LOWER_B1000_ID         0
-#define NEURONSPI_BOARD_LOWER_E8DI8RO_ID       1
-#define NEURONSPI_BOARD_LOWER_E14RO_ID         2
-#define NEURONSPI_BOARD_LOWER_E16DI_ID         3
-#define NEURONSPI_BOARD_LOWER_E4AI4AO_ID       11
-#define NEURONSPI_BOARD_LOWER_B485_ID          13
-#define NEURONSPI_BOARD_LOWER_E4LIGHT_ID       14
-
-
-// Upper Boards:
-#define NEURONSPI_BOARD_UPPER_NONE_ID          0
-#define NEURONSPI_BOARD_UPPER_P11DIR485_ID     1
-#define NEURONSPI_BOARD_UPPER_U14RO_ID         2
-#define NEURONSPI_BOARD_UPPER_U14DI_ID         3
-#define NEURONSPI_BOARD_UPPER_P6DI5RO_ID       4
-#define NEURONSPI_BOARD_UPPER_U6DI5RO_ID       5
-
-// Register function codes:
-#define NEURONSPI_FUNGROUP_DI                                  0
-#define NEURONSPI_REGFUN_DI_READ                       0 | NEURONSPI_FUNGROUP_DI << 8
-#define NEURONSPI_REGFUN_DI_COUNTER_LOWER      1 | NEURONSPI_FUNGROUP_DI << 8
-#define NEURONSPI_REGFUN_DI_COUNTER_UPPER      2 | NEURONSPI_FUNGROUP_DI << 8
-#define NEURONSPI_REGFUN_DI_DEBOUNCE           3 | NEURONSPI_FUNGROUP_DI << 8
-#define NEURONSPI_REGFUN_DS_ENABLE                     4 | NEURONSPI_FUNGROUP_DI << 8
-#define NEURONSPI_REGFUN_DS_POLARITY           5 | NEURONSPI_FUNGROUP_DI << 8
-#define NEURONSPI_REGFUN_DS_TOGGLE                     6 | NEURONSPI_FUNGROUP_DI << 8
-
-#define NEURONSPI_FUNGROUP_DO                                  1
-#define NEURONSPI_REGFUN_DO_RW                         0 | NEURONSPI_FUNGROUP_DO << 8
-
-#define NEURONSPI_FUNGROUP_AO_BRAIN                            2
-#define NEURONSPI_REGFUN_AO_BRAIN                      0 | NEURONSPI_FUNGROUP_AO_BRAIN << 8
-#define NEURONSPI_REGFUN_AO_BRAIN_MODE         1 | NEURONSPI_FUNGROUP_AO_BRAIN << 8
-#define NEURONSPI_REGFUN_AO_BRAIN_V_ERR                2 | NEURONSPI_FUNGROUP_AO_BRAIN << 8
-#define NEURONSPI_REGFUN_AO_BRAIN_V_OFF                3 | NEURONSPI_FUNGROUP_AO_BRAIN << 8
-#define NEURONSPI_REGFUN_AO_BRAIN_I_ERR        4 | NEURONSPI_FUNGROUP_AO_BRAIN << 8
-#define NEURONSPI_REGFUN_AO_BRAIN_I_OFF        5 | NEURONSPI_FUNGROUP_AO_BRAIN << 8
-
-#define NEURONSPI_FUNGROUP_AI_BRAIN                            3
-#define NEURONSPI_REGFUN_AI_BRAIN                      0 | NEURONSPI_FUNGROUP_AI_BRAIN << 8
-#define NEURONSPI_REGFUN_AIO_BRAIN                     1 | NEURONSPI_FUNGROUP_AI_BRAIN << 8
-#define NEURONSPI_REGFUN_AI_BRAIN_MODE         2 | NEURONSPI_FUNGROUP_AI_BRAIN << 8
-#define NEURONSPI_REGFUN_AI_BRAIN_V_ERR                3 | NEURONSPI_FUNGROUP_AI_BRAIN << 8
-#define NEURONSPI_REGFUN_AI_BRAIN_V_OFF                4 | NEURONSPI_FUNGROUP_AI_BRAIN << 8
-#define NEURONSPI_REGFUN_AI_BRAIN_I_ERR                5 | NEURONSPI_FUNGROUP_AI_BRAIN << 8
-#define NEURONSPI_REGFUN_AI_BRAIN_I_OFF                6 | NEURONSPI_FUNGROUP_AI_BRAIN << 8
-#define NEURONSPI_REGFUN_AIO_BRAIN_ERR         7 | NEURONSPI_FUNGROUP_AI_BRAIN << 8
-#define NEURONSPI_REGFUN_AIO_BRAIN_OFF         8 | NEURONSPI_FUNGROUP_AI_BRAIN << 8
-
-#define NEURONSPI_FUNGROUP_SYSTEM                              4
-#define NEURONSPI_REGFUN_V_REF_INT                     0 | NEURONSPI_FUNGROUP_SYSTEM << 8
-#define NEURONSPI_REGFUN_V_REF_INP                     1 | NEURONSPI_FUNGROUP_SYSTEM << 8
-#define NEURONSPI_REGFUN_LED_RW                                2 | NEURONSPI_FUNGROUP_SYSTEM << 8
-#define NEURONSPI_REGFUN_SW_VER                        3 | NEURONSPI_FUNGROUP_SYSTEM << 8
-#define NEURONSPI_REGFUN_DIDO_COUNT                    4 | NEURONSPI_FUNGROUP_SYSTEM << 8
-#define NEURONSPI_REGFUN_UAIO_COUNT                    5 | NEURONSPI_FUNGROUP_SYSTEM << 8
-#define NEURONSPI_REGFUN_HW_VER                                6 | NEURONSPI_FUNGROUP_SYSTEM << 8
-#define NEURONSPI_REGFUN_FLASH_HW_VER          7 | NEURONSPI_FUNGROUP_SYSTEM << 8
-#define NEURONSPI_REGFUN_SERIAL_NR_LOWER       8 | NEURONSPI_FUNGROUP_SYSTEM << 8
-#define NEURONSPI_REGFUN_SERIAL_NR_UPPER       9 | NEURONSPI_FUNGROUP_SYSTEM << 8
-#define NEURONSPI_REGFUN_INTERRUPTS                    10 | NEURONSPI_FUNGROUP_SYSTEM << 8
-#define NEURONSPI_REGFUN_NONE_TEST                     11 | NEURONSPI_FUNGROUP_SYSTEM << 8
-
-#define NEURONSPI_FUNGROUP_MWD                                 5
-#define NEURONSPI_REGFUN_MWD_TO                                0 | NEURONSPI_FUNGROUP_MWD << 8
-#define NEURONSPI_REGFUN_MWD_STATUS                    1 | NEURONSPI_FUNGROUP_MWD << 8
-
-#define NEURONSPI_FUNGROUP_PWM                                 6
-#define NEURONSPI_REGFUN_PWM_DUTY                      0 | NEURONSPI_FUNGROUP_PWM << 8
-#define NEURONSPI_REGFUN_PWM_PRESCALE          1 | NEURONSPI_FUNGROUP_PWM << 8
-#define NEURONSPI_REGFUN_PWM_CYCLE                     2 | NEURONSPI_FUNGROUP_PWM << 8
-
-
-#define NEURONSPI_FUNGROUP_RS485                               7
-#define NEURONSPI_REGFUN_TX_QUEUE_LEN          0 | NEURONSPI_FUNGROUP_RS485 << 8
-#define NEURONSPI_REGFUN_RS485_CONFIG          1 | NEURONSPI_FUNGROUP_RS485 << 8
-#define NEURONSPI_REGFUN_RS485_ADDRESS         2 | NEURONSPI_FUNGROUP_RS485 << 8
-
-#define NEURONSPI_FUNGROUP_AO_VER2                             8
-#define NEURONSPI_REGFUN_AO_VER2_RW                    0 | NEURONSPI_FUNGROUP_AO_VER2 << 8
-
-#define NEURONSPI_FUNGROUP_AI_VER2                             9
-#define NEURONSPI_REGFUN_AI_VER2_READ_LOWER    0 | NEURONSPI_FUNGROUP_AI_VER2 << 8
-#define NEURONSPI_REGFUN_AI_VER2_READ_UPPER    0 | NEURONSPI_FUNGROUP_AI_VER2 << 8
-#define NEURONSPI_REGFUN_AI_VER2_MODE          1 | NEURONSPI_FUNGROUP_AI_VER2 << 8
-
-// Register access flags:
-#define NEURONSPI_REGFLAG_ACC_NEVER    0
-#define NEURONSPI_REGFLAG_ACC_AFAP     0x1 << 16
-#define NEURONSPI_REGFLAG_ACC_10HZ     0x2 << 16
-#define NEURONSPI_REGFLAG_ACC_1HZ   0x3 << 16
-#define NEURONSPI_REGFLAG_ACC_6SEC  0x4 << 16
-#define NEURONSPI_REGFLAG_ACC_1MIN  0x5 << 16
-#define NEURONSPI_REGFLAG_ACC_15MIN 0x6 << 16
-#define NEURONSPI_REGFLAG_ACC_ONCE     0x7 << 16
-
-// Register system flags:
-#define NEURONSPI_REGFLAG_SYS_READ_ONLY        0x10 << 24
-
-#define NEURONSPI_IIO_AI_STM_MODE_VOLTAGE 0x0
-#define NEURONSPI_IIO_AI_STM_MODE_CURRENT 0x1
-#define NEURONSPI_IIO_AI_STM_MODE_RESISTANCE 0x3
-
-/*********************
- * Board Definitions *
- *********************/
-
-// B_1000 (S103)
-#define NEURONSPI_BOARD_B1000_HW_DEFINITION_BLOCK_SIZE 57
-static u32 NEURONSPI_BOARD_B1000_HW_DEFINITION_BLOCK[NEURONSPI_BOARD_B1000_HW_DEFINITION_BLOCK_SIZE] = {
-               0, 21,  // Register block beginning and size
-               NEURONSPI_REGFUN_DI_READ | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY,                // 0
-               NEURONSPI_REGFUN_DO_RW | NEURONSPI_REGFLAG_ACC_10HZ,                                                                                    // 1
-               NEURONSPI_REGFUN_AO_BRAIN | NEURONSPI_REGFLAG_ACC_AFAP,                                                                                 // 2
-               NEURONSPI_REGFUN_AI_BRAIN | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY,       // 3
-               NEURONSPI_REGFUN_AIO_BRAIN | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY,              // 4
-               NEURONSPI_REGFUN_V_REF_INP | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY,              // 5
-               NEURONSPI_REGFUN_MWD_STATUS | NEURONSPI_REGFLAG_ACC_6SEC | NEURONSPI_REGFLAG_SYS_READ_ONLY,     // 6
-               NEURONSPI_REGFUN_TX_QUEUE_LEN | NEURONSPI_REGFLAG_ACC_10HZ,                                                                             // 7
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 8
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 9
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 10
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 11
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 12
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 13
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 14
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 15
-               NEURONSPI_REGFUN_PWM_DUTY | NEURONSPI_REGFLAG_ACC_6SEC,                                                                                 // 16
-               NEURONSPI_REGFUN_PWM_DUTY | NEURONSPI_REGFLAG_ACC_6SEC,                                                                                 // 17
-               NEURONSPI_REGFUN_PWM_DUTY | NEURONSPI_REGFLAG_ACC_6SEC,                                                                                 // 18
-               NEURONSPI_REGFUN_PWM_DUTY | NEURONSPI_REGFLAG_ACC_6SEC,                                                                                 // 19
-               NEURONSPI_REGFUN_LED_RW | NEURONSPI_REGFLAG_ACC_AFAP,                                                                                   // 20
-               1000, 32, // Register block beginning and size
-               NEURONSPI_REGFUN_SW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,                 // 1000
-               NEURONSPI_REGFUN_DIDO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,             // 1001
-               NEURONSPI_REGFUN_UAIO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,     // 1002
-               NEURONSPI_REGFUN_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE  | NEURONSPI_REGFLAG_SYS_READ_ONLY,                // 1003
-               NEURONSPI_REGFUN_FLASH_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,   // 1004
-               NEURONSPI_REGFUN_SERIAL_NR_LOWER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1005
-               NEURONSPI_REGFUN_SERIAL_NR_UPPER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1006
-               NEURONSPI_REGFUN_INTERRUPTS | NEURONSPI_REGFLAG_ACC_AFAP,                                                                               // 1007
-               NEURONSPI_REGFUN_MWD_TO | NEURONSPI_REGFLAG_ACC_6SEC | NEURONSPI_REGFLAG_SYS_READ_ONLY,                 // 1008
-               NEURONSPI_REGFUN_V_REF_INT | NEURONSPI_REGFLAG_ACC_ONCE,                                                                                // 1009
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1010
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1011
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1012
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1013
-               NEURONSPI_REGFUN_DS_ENABLE | NEURONSPI_REGFLAG_ACC_1HZ,                                                                                 // 1014
-               NEURONSPI_REGFUN_DS_POLARITY | NEURONSPI_REGFLAG_ACC_1HZ,                                                                               // 1015
-               NEURONSPI_REGFUN_DS_TOGGLE | NEURONSPI_REGFLAG_ACC_1HZ,                                                                                 // 1016
-               NEURONSPI_REGFUN_PWM_PRESCALE | NEURONSPI_REGFLAG_ACC_1HZ,                                                                      // 1017
-               NEURONSPI_REGFUN_PWM_CYCLE | NEURONSPI_REGFLAG_ACC_1HZ,                                                                         // 1018
-               NEURONSPI_REGFUN_AO_BRAIN_MODE | NEURONSPI_REGFLAG_ACC_1HZ,                                                                             // 1019
-               NEURONSPI_REGFUN_AO_BRAIN_V_ERR | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1020
-               NEURONSPI_REGFUN_AO_BRAIN_V_OFF | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1021
-               NEURONSPI_REGFUN_AO_BRAIN_I_ERR | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1022
-               NEURONSPI_REGFUN_AO_BRAIN_I_OFF | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1023
-               NEURONSPI_REGFUN_AI_BRAIN_MODE | NEURONSPI_REGFLAG_ACC_1HZ,                                                                             // 1024
-               NEURONSPI_REGFUN_AI_BRAIN_V_ERR | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1025
-               NEURONSPI_REGFUN_AI_BRAIN_V_OFF | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1026
-               NEURONSPI_REGFUN_AI_BRAIN_I_ERR | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1027
-               NEURONSPI_REGFUN_AI_BRAIN_I_OFF | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1028
-               NEURONSPI_REGFUN_AIO_BRAIN_OFF | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,  // 1029
-               NEURONSPI_REGFUN_AIO_BRAIN_ERR | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,  // 1030
-               NEURONSPI_REGFUN_RS485_CONFIG | NEURONSPI_REGFLAG_ACC_6SEC                                                                              // 1031
-};
-
-#define NEURONSPI_BOARD_B1000_HW_FEATURES {    \
-               .do_count =                                       4,    \
-               .ro_count =                                       0,    \
-               .ds_count =                                       4,    \
-               .di_count =                                       4,    \
-               .led_count =                              4,    \
-               .stm_ai_count =                           1,    \
-               .stm_ao_count =                           1,    \
-               .sec_ai_count =                           0,    \
-               .sec_ao_count =                           0,    \
-               .uart_master_count =              1,    \
-               .uart_slave_count =               0,    \
-               .pwm_channel_count =              4,    \
-               .wd_count =                               1,    \
-               .extension_sys_count =            0,    \
-               .light_count =                            0,    \
-               .owire_count =                            1,    \
-}
-
-#define NEURONSPI_BOARD_B1000_HW_DEFINITION { \
-               .combination_board_id =         0, \
-               .lower_board_id =                       NEURONSPI_BOARD_LOWER_B1000_ID, \
-               .upper_board_id =                       NEURONSPI_BOARD_UPPER_NONE_ID, \
-               .block_count =                          NEURONSPI_BOARD_B1000_HW_DEFINITION_BLOCK_SIZE, \
-               .name_length =                          6, \
-               .combination_name =                     "B_1000", \
-               .features =                                     NEURONSPI_BOARD_B1000_HW_FEATURES, \
-               .blocks =                                       NEURONSPI_BOARD_B1000_HW_DEFINITION_BLOCK \
-}
-static struct neuronspi_board_combination NEURONSPI_BOARD_B1000_HW_COMBINATION[] = {NEURONSPI_BOARD_B1000_HW_DEFINITION};
-
-// E-8Di8Ro (M103)
-#define NEURONSPI_BOARD_E8DI8RO_HW_DEFINITION_BLOCK_SIZE 44
-static u32 NEURONSPI_BOARD_E8DI8RO_HW_DEFINITION_BLOCK[NEURONSPI_BOARD_E8DI8RO_HW_DEFINITION_BLOCK_SIZE] = {
-               0, 19,  // Register block beginning and size
-               NEURONSPI_REGFUN_DI_READ | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY,                // 0
-               NEURONSPI_REGFUN_DO_RW | NEURONSPI_REGFLAG_ACC_10HZ,                                                                                    // 1
-               NEURONSPI_REGFUN_MWD_STATUS | NEURONSPI_REGFLAG_ACC_6SEC | NEURONSPI_REGFLAG_SYS_READ_ONLY,     // 2
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 3
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 4
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 5
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 6
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 7
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 8
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 9
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 10
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 11
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 12
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 13
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 14
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 15
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 16
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 17
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 18
-               1000, 17, // Register block beginning and size
-               NEURONSPI_REGFUN_SW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,                 // 1000
-               NEURONSPI_REGFUN_DIDO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,             // 1001
-               NEURONSPI_REGFUN_UAIO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,             // 1002
-               NEURONSPI_REGFUN_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,                 // 1003
-               NEURONSPI_REGFUN_FLASH_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,   // 1004
-               NEURONSPI_REGFUN_SERIAL_NR_LOWER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1005
-               NEURONSPI_REGFUN_SERIAL_NR_UPPER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1006
-               NEURONSPI_REGFUN_INTERRUPTS | NEURONSPI_REGFLAG_ACC_AFAP,                                                                               // 1007
-               NEURONSPI_REGFUN_MWD_TO | NEURONSPI_REGFLAG_ACC_6SEC,                                                                                   // 1008
-               NEURONSPI_REGFUN_V_REF_INT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,              // 1009
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1010
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1011
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1012
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1013
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1014
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1015
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1016
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1017
-               NEURONSPI_REGFUN_DS_ENABLE | NEURONSPI_REGFLAG_ACC_1HZ,                                                                                 // 1018
-               NEURONSPI_REGFUN_DS_POLARITY | NEURONSPI_REGFLAG_ACC_1HZ,                                                                               // 1019
-               NEURONSPI_REGFUN_DS_TOGGLE | NEURONSPI_REGFLAG_ACC_1HZ,                                                                                 // 1020
-};
-
-#define NEURONSPI_BOARD_E8DI8RO_HW_FEATURES {  \
-               .do_count =                                       0,    \
-               .ro_count =                                       8,    \
-               .ds_count =                                       8,    \
-               .di_count =                                       8,    \
-               .led_count =                              0,    \
-               .stm_ai_count =                           0,    \
-               .stm_ao_count =                           0,    \
-               .sec_ai_count =                           0,    \
-               .sec_ao_count =                           0,    \
-               .uart_master_count =              0,    \
-               .uart_slave_count =               0,    \
-               .pwm_channel_count =              0,    \
-               .wd_count =                               1,    \
-               .extension_sys_count =            0,    \
-               .light_count =                            0,    \
-               .owire_count =                            0,    \
-}
-
-#define NEURONSPI_BOARD_E8DI8RO_HW_DEFINITION { \
-               .combination_board_id =         1, \
-               .lower_board_id =                       NEURONSPI_BOARD_LOWER_E8DI8RO_ID, \
-               .upper_board_id =                       NEURONSPI_BOARD_UPPER_NONE_ID, \
-               .block_count =                          NEURONSPI_BOARD_E8DI8RO_HW_DEFINITION_BLOCK_SIZE, \
-               .name_length =                          8, \
-               .combination_name =                     "E_8Di8Ro", \
-               .blocks =                                       NEURONSPI_BOARD_E8DI8RO_HW_DEFINITION_BLOCK, \
-               .features =                                     NEURONSPI_BOARD_E8DI8RO_HW_FEATURES     \
-}
-static struct neuronspi_board_combination NEURONSPI_BOARD_E8DI8RO_HW_COMBINATION[] = {NEURONSPI_BOARD_E8DI8RO_HW_DEFINITION};
-
-// E-14Ro
-#define NEURONSPI_BOARD_E14RO_HW_DEFINITION_BLOCK_SIZE 15
-static u32 NEURONSPI_BOARD_E14RO_HW_DEFINITION_BLOCK[NEURONSPI_BOARD_E14RO_HW_DEFINITION_BLOCK_SIZE] = {
-               0, 1,   // Register block beginning and size
-               NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE,                                                                                // 0
-               1000, 10,
-               NEURONSPI_REGFUN_SW_VER | NEURONSPI_REGFLAG_ACC_ONCE,                                                                                   // 1000
-               NEURONSPI_REGFUN_DIDO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE,                                                                               // 1001
-               NEURONSPI_REGFUN_UAIO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE,                                                                               // 1002
-               NEURONSPI_REGFUN_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE,                                                                                   // 1003
-               NEURONSPI_REGFUN_FLASH_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE,                                                                     // 1004
-               NEURONSPI_REGFUN_SERIAL_NR_LOWER | NEURONSPI_REGFLAG_ACC_ONCE,                                                                  // 1005
-               NEURONSPI_REGFUN_SERIAL_NR_UPPER | NEURONSPI_REGFLAG_ACC_ONCE,                                                                  // 1006
-               NEURONSPI_REGFUN_INTERRUPTS | NEURONSPI_REGFLAG_ACC_AFAP,                                                                               // 1007
-               NEURONSPI_REGFUN_MWD_TO | NEURONSPI_REGFLAG_ACC_6SEC,                                                                                   // 1008
-               NEURONSPI_REGFUN_V_REF_INT | NEURONSPI_REGFLAG_ACC_ONCE,                                                                                // 1009
-};
-
-#define NEURONSPI_BOARD_E14RO_HW_FEATURES {    \
-               .do_count =                                       0,    \
-               .ro_count =                                       14,   \
-               .ds_count =                                       0,    \
-               .di_count =                                       0,    \
-               .led_count =                              0,    \
-               .stm_ai_count =                           0,    \
-               .stm_ao_count =                           0,    \
-               .sec_ai_count =                           0,    \
-               .sec_ao_count =                           0,    \
-               .uart_master_count =              0,    \
-               .uart_slave_count =               0,    \
-               .pwm_channel_count =              0,    \
-               .wd_count =                               1,    \
-               .extension_sys_count =            0,    \
-               .light_count =                            0,    \
-               .owire_count =                            0,    \
-}
-
-#define NEURONSPI_BOARD_E14RO_HW_DEFINITION { \
-               .combination_board_id =         2, \
-               .lower_board_id =                       NEURONSPI_BOARD_LOWER_E14RO_ID, \
-               .upper_board_id =                       NEURONSPI_BOARD_UPPER_NONE_ID, \
-               .block_count =                          NEURONSPI_BOARD_E14RO_HW_DEFINITION_BLOCK_SIZE, \
-               .name_length =                          6, \
-               .combination_name =                     "E_14Ro", \
-               .blocks =                                       NEURONSPI_BOARD_E14RO_HW_DEFINITION_BLOCK, \
-               .features =                             NEURONSPI_BOARD_E14RO_HW_FEATURES \
-}
-static struct neuronspi_board_combination NEURONSPI_BOARD_E14RO_HW_COMBINATION[] = {NEURONSPI_BOARD_E14RO_HW_DEFINITION};
-
-// E-16Di
-#define NEURONSPI_BOARD_E16DI_HW_DEFINITION_BLOCK_SIZE 15
-static u32 NEURONSPI_BOARD_E16DI_HW_DEFINITION_BLOCK[NEURONSPI_BOARD_E16DI_HW_DEFINITION_BLOCK_SIZE] = {
-               0, 1,   // Register block beginning and size
-               NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE,                                                                                // 0
-               1000, 10,
-               NEURONSPI_REGFUN_SW_VER | NEURONSPI_REGFLAG_ACC_ONCE,                                                                                   // 1000
-               NEURONSPI_REGFUN_DIDO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE,                                                                               // 1001
-               NEURONSPI_REGFUN_UAIO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE,                                                                               // 1002
-               NEURONSPI_REGFUN_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE,                                                                                   // 1003
-               NEURONSPI_REGFUN_FLASH_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE,                                                                     // 1004
-               NEURONSPI_REGFUN_SERIAL_NR_LOWER | NEURONSPI_REGFLAG_ACC_ONCE,                                                                  // 1005
-               NEURONSPI_REGFUN_SERIAL_NR_UPPER | NEURONSPI_REGFLAG_ACC_ONCE,                                                                  // 1006
-               NEURONSPI_REGFUN_INTERRUPTS | NEURONSPI_REGFLAG_ACC_AFAP,                                                                               // 1007
-               NEURONSPI_REGFUN_MWD_TO | NEURONSPI_REGFLAG_ACC_6SEC,                                                                                   // 1008
-               NEURONSPI_REGFUN_V_REF_INT | NEURONSPI_REGFLAG_ACC_ONCE,                                                                                // 1009
-};
-
-#define NEURONSPI_BOARD_E16DI_HW_FEATURES {    \
-               .do_count =                                       0,    \
-               .ro_count =                                       0,    \
-               .ds_count =                                       0,    \
-               .di_count =                                       16,   \
-               .led_count =                              0,    \
-               .stm_ai_count =                           0,    \
-               .stm_ao_count =                           0,    \
-               .sec_ai_count =                           0,    \
-               .sec_ao_count =                           0,    \
-               .uart_master_count =              0,    \
-               .uart_slave_count =               0,    \
-               .pwm_channel_count =              0,    \
-               .wd_count =                               1,    \
-               .extension_sys_count =            0,    \
-               .light_count =                            0,    \
-               .owire_count =                            0,    \
-}
-
-#define NEURONSPI_BOARD_E16DI_HW_DEFINITION { \
-               .combination_board_id =         3, \
-               .lower_board_id =                       NEURONSPI_BOARD_LOWER_E16DI_ID, \
-               .upper_board_id =                       NEURONSPI_BOARD_UPPER_NONE_ID, \
-               .block_count =                          NEURONSPI_BOARD_E16DI_HW_DEFINITION_BLOCK_SIZE, \
-               .name_length =                          6, \
-               .combination_name =                     "E_16Di", \
-               .blocks =                                       NEURONSPI_BOARD_E16DI_HW_DEFINITION_BLOCK, \
-               .features =                             NEURONSPI_BOARD_E16DI_HW_FEATURES \
-}
-
-static struct neuronspi_board_combination NEURONSPI_BOARD_E16DI_HW_COMBINATION[] = {NEURONSPI_BOARD_E16DI_HW_DEFINITION};
-
-// E-8Di8Ro_P-11DiR485 (xS10)
-#define NEURONSPI_BOARD_E8DI8ROP11DIR485_HW_DEFINITION_BLOCK_SIZE 47
-static u32 NEURONSPI_BOARD_E8DI8ROP11DIR485_HW_DEFINITION_BLOCK[NEURONSPI_BOARD_E8DI8ROP11DIR485_HW_DEFINITION_BLOCK_SIZE] = {
-               0, 20,  // Register block beginning and size
-               NEURONSPI_REGFUN_DI_READ | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY,                // 0
-               NEURONSPI_REGFUN_DO_RW | NEURONSPI_REGFLAG_ACC_10HZ,                                                                                    // 1
-               NEURONSPI_REGFUN_MWD_STATUS | NEURONSPI_REGFLAG_ACC_6SEC | NEURONSPI_REGFLAG_SYS_READ_ONLY,     // 2
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 3
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 4
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 5
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 6
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 7
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 8
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 9
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 10
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 11
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 12
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 13
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 14
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 15
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 16
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 17
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 18
-               NEURONSPI_REGFUN_LED_RW | NEURONSPI_REGFLAG_ACC_1HZ,                                                                                    // 19
-               1000, 23, // Register block beginning and size
-               NEURONSPI_REGFUN_SW_VER | NEURONSPI_REGFLAG_ACC_ONCE,                                                                                   // 1000
-               NEURONSPI_REGFUN_DIDO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE,                                                                               // 1001
-               NEURONSPI_REGFUN_UAIO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE,                                                                               // 1002
-               NEURONSPI_REGFUN_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE,                                                                                   // 1003
-               NEURONSPI_REGFUN_FLASH_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE,                                                                     // 1004
-               NEURONSPI_REGFUN_SERIAL_NR_LOWER | NEURONSPI_REGFLAG_ACC_ONCE,                                                                  // 1005
-               NEURONSPI_REGFUN_SERIAL_NR_UPPER | NEURONSPI_REGFLAG_ACC_ONCE,                                                                  // 1006
-               NEURONSPI_REGFUN_INTERRUPTS | NEURONSPI_REGFLAG_ACC_AFAP,                                                                               // 1007
-               NEURONSPI_REGFUN_MWD_TO | NEURONSPI_REGFLAG_ACC_6SEC,                                                                                   // 1008
-               NEURONSPI_REGFUN_V_REF_INT | NEURONSPI_REGFLAG_ACC_ONCE,                                                                                // 1009
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1010
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1011
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1012
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1013
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1014
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1015
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1016
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1017
-               NEURONSPI_REGFUN_DS_ENABLE   | NEURONSPI_REGFLAG_ACC_1HZ,                                                                               // 1018
-               NEURONSPI_REGFUN_DS_POLARITY | NEURONSPI_REGFLAG_ACC_1HZ,                                                                               // 1019
-               NEURONSPI_REGFUN_DS_TOGGLE   | NEURONSPI_REGFLAG_ACC_1HZ,                                                                               // 1020
-               NEURONSPI_REGFUN_RS485_CONFIG | NEURONSPI_REGFLAG_ACC_6SEC,                                                                             // 1021
-               NEURONSPI_REGFUN_RS485_ADDRESS | NEURONSPI_REGFLAG_ACC_6SEC                                                                             // 1022
-};
-
-#define NEURONSPI_BOARD_E8DI8ROP11DIR485_HW_FEATURES { \
-               .do_count =                                       0,    \
-               .ro_count =                                       8,    \
-               .ds_count =                                       8,    \
-               .di_count =                                       8,    \
-               .led_count =                              0,    \
-               .stm_ai_count =                           0,    \
-               .stm_ao_count =                           0,    \
-               .sec_ai_count =                           0,    \
-               .sec_ao_count =                           0,    \
-               .uart_master_count =              0,    \
-               .uart_slave_count =               1,    \
-               .pwm_channel_count =              0,    \
-               .wd_count =                               1,    \
-               .extension_sys_count =            1,    \
-               .light_count =                            0,    \
-               .owire_count =                            0,    \
-}
-
-#define NEURONSPI_BOARD_E8DI8ROP11DIR485_HW_DEFINITION { \
-               .combination_board_id =         4, \
-               .lower_board_id =                       NEURONSPI_BOARD_LOWER_E8DI8RO_ID, \
-               .upper_board_id =                       NEURONSPI_BOARD_UPPER_P11DIR485_ID, \
-               .block_count =                          NEURONSPI_BOARD_E8DI8ROP11DIR485_HW_DEFINITION_BLOCK_SIZE, \
-               .name_length =                          19, \
-               .combination_name =                     "E_8Di8Ro_P_11DiR485", \
-               .blocks =                                       NEURONSPI_BOARD_E8DI8ROP11DIR485_HW_DEFINITION_BLOCK, \
-               .features =                                     NEURONSPI_BOARD_E8DI8ROP11DIR485_HW_FEATURES \
-}
-static struct neuronspi_board_combination NEURONSPI_BOARD_E8DI8ROP11DIR485_HW_COMBINATION[] = {NEURONSPI_BOARD_E8DI8ROP11DIR485_HW_DEFINITION};
-
-// E-14Ro_P-11DiR485 (xS40)
-#define NEURONSPI_BOARD_E14ROP11DIR485_HW_DEFINITION_BLOCK_SIZE 71
-static u32 NEURONSPI_BOARD_E14ROP11DIR485_HW_DEFINITION_BLOCK[NEURONSPI_BOARD_E14ROP11DIR485_HW_DEFINITION_BLOCK_SIZE] = {
-               0, 36,  // Register block beginning and size
-               NEURONSPI_REGFUN_DI_READ | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY,                // 0
-               NEURONSPI_REGFUN_DO_RW | NEURONSPI_REGFLAG_ACC_10HZ,                                                                                    // 1
-               NEURONSPI_REGFUN_MWD_STATUS | NEURONSPI_REGFLAG_ACC_6SEC | NEURONSPI_REGFLAG_SYS_READ_ONLY,     // 2
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 3
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 4
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 5
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 6
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 7
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 8
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 9
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 10
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 11
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 12
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 13
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 14
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 15
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 16
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 17
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 18
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 19
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 20
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 21
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 22
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 23
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 24
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 25
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 26
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 27
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 28
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 29
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 30
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 31
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 32
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 33
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 34
-               NEURONSPI_REGFUN_LED_RW | NEURONSPI_REGFLAG_ACC_1HZ,                                                                    // 35
-               1000, 31, // Register block beginning and size
-               NEURONSPI_REGFUN_SW_VER | NEURONSPI_REGFLAG_ACC_ONCE,                                                                                   // 1000
-               NEURONSPI_REGFUN_DIDO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE,                                                                               // 1001
-               NEURONSPI_REGFUN_UAIO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE,                                                                               // 1002
-               NEURONSPI_REGFUN_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE,                                                                                   // 1003
-               NEURONSPI_REGFUN_FLASH_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE,                                                                     // 1004
-               NEURONSPI_REGFUN_SERIAL_NR_LOWER | NEURONSPI_REGFLAG_ACC_ONCE,                                                                  // 1005
-               NEURONSPI_REGFUN_SERIAL_NR_UPPER | NEURONSPI_REGFLAG_ACC_ONCE,                                                                  // 1006
-               NEURONSPI_REGFUN_INTERRUPTS | NEURONSPI_REGFLAG_ACC_AFAP,                                                                               // 1007
-               NEURONSPI_REGFUN_MWD_TO | NEURONSPI_REGFLAG_ACC_6SEC,                                                                                   // 1008
-               NEURONSPI_REGFUN_V_REF_INT | NEURONSPI_REGFLAG_ACC_ONCE,                                                                                // 1009
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1010
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1011
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1012
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1013
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1014
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1015
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1016
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1017
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1018
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1019
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1020
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1021
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1022
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1023
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1024
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1025
-               NEURONSPI_REGFUN_DS_ENABLE | NEURONSPI_REGFLAG_ACC_1HZ,                                                                                 // 1026
-               NEURONSPI_REGFUN_DS_POLARITY | NEURONSPI_REGFLAG_ACC_1HZ,                                                                               // 1027
-               NEURONSPI_REGFUN_DS_TOGGLE | NEURONSPI_REGFLAG_ACC_1HZ,                                                                                 // 1028
-               NEURONSPI_REGFUN_RS485_CONFIG | NEURONSPI_REGFLAG_ACC_6SEC,                                                                             // 1029
-               NEURONSPI_REGFUN_RS485_ADDRESS | NEURONSPI_REGFLAG_ACC_6SEC                                                                             // 1030
-};
-
-#define NEURONSPI_BOARD_E14ROP11DIR485_HW_FEATURES {   \
-               .do_count =                                       0,    \
-               .ro_count =                                       14,   \
-               .ds_count =                                       8,    \
-               .di_count =                                       8,    \
-               .led_count =                              0,    \
-               .stm_ai_count =                           0,    \
-               .stm_ao_count =                           0,    \
-               .sec_ai_count =                           0,    \
-               .sec_ao_count =                           0,    \
-               .uart_master_count =              0,    \
-               .uart_slave_count =               1,    \
-               .pwm_channel_count =              0,    \
-               .wd_count =                               1,    \
-               .extension_sys_count =            1,    \
-               .light_count =                            0,    \
-               .owire_count =                            0,    \
-}
-
-#define NEURONSPI_BOARD_E14ROP11DIR485_HW_DEFINITION { \
-               .combination_board_id =         5, \
-               .lower_board_id =                       NEURONSPI_BOARD_LOWER_E14RO_ID, \
-               .upper_board_id =                       NEURONSPI_BOARD_UPPER_P11DIR485_ID, \
-               .name_length =                          17, \
-               .combination_name =                     "E_14Ro_P_11DiR485", \
-               .block_count =                          NEURONSPI_BOARD_E14ROP11DIR485_HW_DEFINITION_BLOCK_SIZE, \
-               .blocks =                                       NEURONSPI_BOARD_E14ROP11DIR485_HW_DEFINITION_BLOCK, \
-               .features =                                     NEURONSPI_BOARD_E14ROP11DIR485_HW_FEATURES \
-}
-static struct neuronspi_board_combination NEURONSPI_BOARD_E14ROP11DIR485_HW_COMBINATION[] = {NEURONSPI_BOARD_E14ROP11DIR485_HW_DEFINITION};
-
-// E-16Di_P-11DiR485 (xS30)
-#define NEURONSPI_BOARD_E16DIP11DIR485_HW_DEFINITION_BLOCK_SIZE 92
-static u32 NEURONSPI_BOARD_E16DIP11DIR485_HW_DEFINITION_BLOCK[NEURONSPI_BOARD_E16DIP11DIR485_HW_DEFINITION_BLOCK_SIZE] = {
-               0, 52,  // Register block beginning and size
-               NEURONSPI_REGFUN_DI_READ | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY,                // 0
-               NEURONSPI_REGFUN_DI_READ | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY,                // 1
-               NEURONSPI_REGFUN_MWD_STATUS | NEURONSPI_REGFLAG_ACC_6SEC,                                                                               // 2
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 3
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 4
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 5
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 6
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 7
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 8
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 9
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 10
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 11
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 12
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 13
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 14
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 15
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 16
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 17
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 18
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 19
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 20
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 21
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 22
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 23
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 24
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 25
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 26
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 27
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 28
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 29
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 30
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 31
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 32
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 33
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 34
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 35
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 36
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 37
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 38
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 39
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 40
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 41
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 42
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 43
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 44
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 45
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 46
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 47
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 48
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 49
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 50
-               NEURONSPI_REGFUN_LED_RW | NEURONSPI_REGFLAG_ACC_1HZ,                                                                                    // 51
-               1000, 36, // Register block beginning and size
-               NEURONSPI_REGFUN_SW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,                 // 1000
-               NEURONSPI_REGFUN_DIDO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,             // 1001
-               NEURONSPI_REGFUN_UAIO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,             // 1002
-               NEURONSPI_REGFUN_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,                 // 1003
-               NEURONSPI_REGFUN_FLASH_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,   // 1004
-               NEURONSPI_REGFUN_SERIAL_NR_LOWER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1005
-               NEURONSPI_REGFUN_SERIAL_NR_UPPER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1006
-               NEURONSPI_REGFUN_INTERRUPTS | NEURONSPI_REGFLAG_ACC_AFAP,                                                                               // 1007
-               NEURONSPI_REGFUN_MWD_TO | NEURONSPI_REGFLAG_ACC_6SEC,                                                                                   // 1008
-               NEURONSPI_REGFUN_V_REF_INT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,              // 1009
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1010
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1011
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1012
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1013
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1014
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1015
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1016
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1017
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1018
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1019
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1020
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1021
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1022
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1023
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1024
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1025
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1026
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1027
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1028
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1029
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1030
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1031
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1032
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1033
-               NEURONSPI_REGFUN_RS485_CONFIG | NEURONSPI_REGFLAG_ACC_6SEC,                                                                             // 1034
-               NEURONSPI_REGFUN_RS485_ADDRESS | NEURONSPI_REGFLAG_ACC_6SEC                                                                             // 1035
-};
-
-#define NEURONSPI_BOARD_E16DIP11DIR485_HW_FEATURES {   \
-               .do_count =                                       0,    \
-               .ro_count =                                       0,    \
-               .ds_count =                                       0,    \
-               .di_count =                                       23,   \
-               .led_count =                              0,    \
-               .stm_ai_count =                           0,    \
-               .stm_ao_count =                           0,    \
-               .sec_ai_count =                           0,    \
-               .sec_ao_count =                           0,    \
-               .uart_master_count =              0,    \
-               .uart_slave_count =               1,    \
-               .pwm_channel_count =              0,    \
-               .wd_count =                               1,    \
-               .extension_sys_count =            1,    \
-               .light_count =                            0,    \
-               .owire_count =                            0,    \
-}
-
-#define NEURONSPI_BOARD_E16DIP11DIR485_HW_DEFINITION { \
-               .combination_board_id =         6, \
-               .lower_board_id =                       NEURONSPI_BOARD_LOWER_E16DI_ID, \
-               .upper_board_id =                       NEURONSPI_BOARD_UPPER_P11DIR485_ID, \
-               .name_length =                          17, \
-               .combination_name =                     "E_16Di_P_11DiR485", \
-               .block_count =                          NEURONSPI_BOARD_E16DIP11DIR485_HW_DEFINITION_BLOCK_SIZE, \
-               .blocks =                                       NEURONSPI_BOARD_E16DIP11DIR485_HW_DEFINITION_BLOCK, \
-               .features =                                     NEURONSPI_BOARD_E16DIP11DIR485_HW_FEATURES \
-}
-static struct neuronspi_board_combination NEURONSPI_BOARD_E16DIP11DIR485_HW_COMBINATION[] = {NEURONSPI_BOARD_E16DIP11DIR485_HW_DEFINITION};
-
-// E-14Ro_U-14Ro (M403)
-#define NEURONSPI_BOARD_E14ROU14RO_HW_DEFINITION_BLOCK_SIZE 17
-static u32 NEURONSPI_BOARD_E14ROU14RO_HW_DEFINITION_BLOCK[NEURONSPI_BOARD_E14ROU14RO_HW_DEFINITION_BLOCK_SIZE] = {
-               0, 3,   // Register block beginning and size
-               NEURONSPI_REGFUN_DO_RW | NEURONSPI_REGFLAG_ACC_10HZ,                                                                                    // 0
-               NEURONSPI_REGFUN_DO_RW | NEURONSPI_REGFLAG_ACC_10HZ,                                                                                    // 1
-               NEURONSPI_REGFUN_MWD_STATUS | NEURONSPI_REGFLAG_ACC_6SEC | NEURONSPI_REGFLAG_SYS_READ_ONLY,     // 2
-               1000, 10, // Register block beginning and size
-               NEURONSPI_REGFUN_SW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,                 // 1000
-               NEURONSPI_REGFUN_DIDO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,             // 1001
-               NEURONSPI_REGFUN_UAIO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,             // 1002
-               NEURONSPI_REGFUN_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,                 // 1003
-               NEURONSPI_REGFUN_FLASH_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,   // 1004
-               NEURONSPI_REGFUN_SERIAL_NR_LOWER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1005
-               NEURONSPI_REGFUN_SERIAL_NR_UPPER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1006
-               NEURONSPI_REGFUN_INTERRUPTS | NEURONSPI_REGFLAG_ACC_AFAP,                                                                               // 1007
-               NEURONSPI_REGFUN_MWD_TO | NEURONSPI_REGFLAG_ACC_6SEC,                                                                                   // 1008
-               NEURONSPI_REGFUN_V_REF_INT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,              // 1009
-};
-
-#define NEURONSPI_BOARD_E14ROU14RO_HW_FEATURES {       \
-               .do_count =                                       0,    \
-               .ro_count =                                       28,   \
-               .ds_count =                                       0,    \
-               .di_count =                                       0,    \
-               .led_count =                              0,    \
-               .stm_ai_count =                           0,    \
-               .stm_ao_count =                           0,    \
-               .sec_ai_count =                           0,    \
-               .sec_ao_count =                           0,    \
-               .uart_master_count =              0,    \
-               .uart_slave_count =               0,    \
-               .pwm_channel_count =              0,    \
-               .wd_count =                               1,    \
-               .extension_sys_count =            1,    \
-               .light_count =                            0,    \
-               .owire_count =                            0,    \
-}
-
-#define NEURONSPI_BOARD_E14ROU14RO_HW_DEFINITION { \
-               .combination_board_id =         7, \
-               .lower_board_id =                       NEURONSPI_BOARD_LOWER_E14RO_ID, \
-               .upper_board_id =                       NEURONSPI_BOARD_UPPER_U14RO_ID, \
-               .name_length =                          13, \
-               .combination_name =                     "E_14Ro_U_14Ro", \
-               .block_count =                          NEURONSPI_BOARD_E14ROU14RO_HW_DEFINITION_BLOCK_SIZE, \
-               .blocks =                                       NEURONSPI_BOARD_E14ROU14RO_HW_DEFINITION_BLOCK, \
-               .features =                             NEURONSPI_BOARD_E14ROU14RO_HW_FEATURES \
-}
-static struct neuronspi_board_combination NEURONSPI_BOARD_E14ROU14RO_HW_COMBINATION[] = {NEURONSPI_BOARD_E14ROU14RO_HW_DEFINITION};
-
-// E-16Di_U-14Ro (M203)
-#define NEURONSPI_BOARD_E16DIU14RO_HW_DEFINITION_BLOCK_SIZE 68
-static u32 NEURONSPI_BOARD_E16DIU14RO_HW_DEFINITION_BLOCK[NEURONSPI_BOARD_E16DIU14RO_HW_DEFINITION_BLOCK_SIZE] = {
-               0, 35,  // Register block beginning and size
-               NEURONSPI_REGFUN_DI_READ | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY,                // 0
-               NEURONSPI_REGFUN_DO_RW | NEURONSPI_REGFLAG_ACC_10HZ,                                                                                    // 1
-               NEURONSPI_REGFUN_MWD_STATUS | NEURONSPI_REGFLAG_ACC_6SEC | NEURONSPI_REGFLAG_SYS_READ_ONLY,     // 2
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 3
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 4
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 5
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 6
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 7
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 8
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 9
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 10
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 11
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 12
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 13
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 14
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 15
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 16
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 17
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 18
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 19
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 20
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 21
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 22
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 23
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 24
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 25
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 26
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 27
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 28
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 29
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 30
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 31
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 32
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 33
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 34
-               1000, 29, // Register block beginning and size
-               NEURONSPI_REGFUN_SW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,                 // 1000
-               NEURONSPI_REGFUN_DIDO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,             // 1001
-               NEURONSPI_REGFUN_UAIO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,             // 1002
-               NEURONSPI_REGFUN_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,                 // 1003
-               NEURONSPI_REGFUN_FLASH_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,   // 1004
-               NEURONSPI_REGFUN_SERIAL_NR_LOWER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1005
-               NEURONSPI_REGFUN_SERIAL_NR_UPPER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1006
-               NEURONSPI_REGFUN_INTERRUPTS | NEURONSPI_REGFLAG_ACC_AFAP,                                                                               // 1007
-               NEURONSPI_REGFUN_MWD_TO | NEURONSPI_REGFLAG_ACC_6SEC,                                                                                   // 1008
-               NEURONSPI_REGFUN_V_REF_INT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,              // 1009
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1010
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1011
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1012
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1013
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1014
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1015
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1016
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1017
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1018
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1019
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1020
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1021
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1022
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1023
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1024
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1025
-               NEURONSPI_REGFUN_DS_ENABLE | NEURONSPI_REGFLAG_ACC_1HZ,                                                                                 // 1026
-               NEURONSPI_REGFUN_DS_POLARITY | NEURONSPI_REGFLAG_ACC_1HZ,                                                                               // 1027
-               NEURONSPI_REGFUN_DS_TOGGLE | NEURONSPI_REGFLAG_ACC_1HZ,                                                                                 // 1028
-};
-
-#define NEURONSPI_BOARD_E16DIU14RO_HW_FEATURES {       \
-               .do_count =                                       0,    \
-               .ro_count =                                       14,   \
-               .ds_count =                                       14,   \
-               .di_count =                                       16,   \
-               .led_count =                              0,    \
-               .stm_ai_count =                           0,    \
-               .stm_ao_count =                           0,    \
-               .sec_ai_count =                           0,    \
-               .sec_ao_count =                           0,    \
-               .uart_master_count =              0,    \
-               .uart_slave_count =               0,    \
-               .pwm_channel_count =              0,    \
-               .wd_count =                               1,    \
-               .extension_sys_count =            0,    \
-               .light_count =                            0,    \
-               .owire_count =                            0,    \
-}
-
-#define NEURONSPI_BOARD_E16DIU14RO_HW_DEFINITION { \
-               .combination_board_id =         8, \
-               .lower_board_id =                       NEURONSPI_BOARD_LOWER_E16DI_ID, \
-               .upper_board_id =                       NEURONSPI_BOARD_UPPER_U14RO_ID, \
-               .name_length =                          13, \
-               .combination_name =                     "E_16Di_U_14Ro", \
-               .block_count =                          NEURONSPI_BOARD_E16DIU14RO_HW_DEFINITION_BLOCK_SIZE, \
-               .blocks =                                       NEURONSPI_BOARD_E16DIU14RO_HW_DEFINITION_BLOCK, \
-               .features =                                     NEURONSPI_BOARD_E16DIU14RO_HW_FEATURES \
-}
-static struct neuronspi_board_combination NEURONSPI_BOARD_E16DIU14RO_HW_COMBINATION[] = {NEURONSPI_BOARD_E16DIU14RO_HW_DEFINITION};
-
-// E-14Ro_U-14Di (L503)
-#define NEURONSPI_BOARD_E14ROU14DI_HW_DEFINITION_BLOCK_SIZE 62
-static u32 NEURONSPI_BOARD_E14ROU14DI_HW_DEFINITION_BLOCK[NEURONSPI_BOARD_E14ROU14DI_HW_DEFINITION_BLOCK_SIZE] = {
-               0, 31,  // Register block beginning and size
-               NEURONSPI_REGFUN_DI_READ | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY,                // 0
-               NEURONSPI_REGFUN_DO_RW | NEURONSPI_REGFLAG_ACC_10HZ,                                                                                    // 1
-               NEURONSPI_REGFUN_MWD_STATUS | NEURONSPI_REGFLAG_ACC_6SEC | NEURONSPI_REGFLAG_SYS_READ_ONLY,     // 2
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 3
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 4
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 5
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 6
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 7
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 8
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 9
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 10
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 11
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 12
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 13
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 14
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 15
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 16
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 17
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 18
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 19
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 20
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 21
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 22
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 23
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 24
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 25
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 26
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 27
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 28
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 29
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 30
-               1000, 27, // Register block beginning and size
-               NEURONSPI_REGFUN_SW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,                 // 1000
-               NEURONSPI_REGFUN_DIDO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,             // 1001
-               NEURONSPI_REGFUN_UAIO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,             // 1002
-               NEURONSPI_REGFUN_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,                 // 1003
-               NEURONSPI_REGFUN_FLASH_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,   // 1004
-               NEURONSPI_REGFUN_SERIAL_NR_LOWER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1005
-               NEURONSPI_REGFUN_SERIAL_NR_UPPER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1006
-               NEURONSPI_REGFUN_INTERRUPTS | NEURONSPI_REGFLAG_ACC_AFAP,                                                                               // 1007
-               NEURONSPI_REGFUN_MWD_TO | NEURONSPI_REGFLAG_ACC_6SEC,                                                                                   // 1008
-               NEURONSPI_REGFUN_V_REF_INT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,              // 1009
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1010
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1011
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1012
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1013
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1014
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1015
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1016
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1017
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1018
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1019
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1020
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1021
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1022
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1023
-               NEURONSPI_REGFUN_DS_ENABLE | NEURONSPI_REGFLAG_ACC_1HZ,                                                                                 // 1024
-               NEURONSPI_REGFUN_DS_POLARITY | NEURONSPI_REGFLAG_ACC_1HZ,                                                                               // 1025
-               NEURONSPI_REGFUN_DS_TOGGLE | NEURONSPI_REGFLAG_ACC_1HZ                                                                                  // 1026
-};
-
-#define NEURONSPI_BOARD_E14ROU14DI_HW_FEATURES {       \
-               .do_count =                                       0,    \
-               .ro_count =                                       14,   \
-               .ds_count =                                       14,   \
-               .di_count =                                       14,   \
-               .led_count =                              0,    \
-               .stm_ai_count =                           0,    \
-               .stm_ao_count =                           0,    \
-               .sec_ai_count =                           0,    \
-               .sec_ao_count =                           0,    \
-               .uart_master_count =              0,    \
-               .uart_slave_count =               0,    \
-               .pwm_channel_count =              0,    \
-               .wd_count =                               1,    \
-               .extension_sys_count =            0,    \
-               .light_count =                            0,    \
-               .owire_count =                            0,    \
-}
-
-#define NEURONSPI_BOARD_E14ROU14DI_HW_DEFINITION { \
-               .combination_board_id =         9, \
-               .lower_board_id =                       NEURONSPI_BOARD_LOWER_E14RO_ID, \
-               .upper_board_id =                       NEURONSPI_BOARD_UPPER_U14DI_ID, \
-               .name_length =                          13, \
-               .combination_name =                     "E_14Ro_U_14Di", \
-               .block_count =                          NEURONSPI_BOARD_E14ROU14DI_HW_DEFINITION_BLOCK_SIZE, \
-               .blocks =                                       NEURONSPI_BOARD_E14ROU14DI_HW_DEFINITION_BLOCK, \
-               .features =                                     NEURONSPI_BOARD_E14ROU14DI_HW_FEATURES \
-}
-static struct neuronspi_board_combination NEURONSPI_BOARD_E14ROU14DI_HW_COMBINATION[] = {NEURONSPI_BOARD_E14ROU14DI_HW_DEFINITION};
-
-
-// E-16Di_U-14Di (M303)
-#define NEURONSPI_BOARD_E16DIU14DI_HW_DEFINITION_BLOCK_SIZE 107
-static u32 NEURONSPI_BOARD_E16DIU14DI_HW_DEFINITION_BLOCK[NEURONSPI_BOARD_E16DIU14DI_HW_DEFINITION_BLOCK_SIZE] = {
-               0, 63,  // Register block beginning and size
-               NEURONSPI_REGFUN_DI_READ | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY,                // 0
-               NEURONSPI_REGFUN_DO_RW | NEURONSPI_REGFLAG_ACC_10HZ,                                                                                    // 1
-               NEURONSPI_REGFUN_MWD_STATUS | NEURONSPI_REGFLAG_ACC_6SEC | NEURONSPI_REGFLAG_SYS_READ_ONLY,     // 2
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 3
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 4
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 5
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 6
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 7
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 8
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 9
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 10
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 11
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 12
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 13
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 14
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 15
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 16
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 17
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 18
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 19
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 20
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 21
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 22
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 23
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 24
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 25
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 26
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 27
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 28
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 29
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 30
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 31
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 32
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 33
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 34
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 35
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 36
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 37
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 38
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 39
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 40
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 41
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 42
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 43
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 44
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 45
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 46
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 47
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 48
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 49
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 50
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 51
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 52
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 53
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 54
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 55
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 56
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 57
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 58
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 59
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 60
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 61
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                 // 62
-               1000, 40, // Register block beginning and size
-               NEURONSPI_REGFUN_SW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,                 // 1000
-               NEURONSPI_REGFUN_DIDO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,             // 1001
-               NEURONSPI_REGFUN_UAIO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,             // 1002
-               NEURONSPI_REGFUN_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,                 // 1003
-               NEURONSPI_REGFUN_FLASH_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,   // 1004
-               NEURONSPI_REGFUN_SERIAL_NR_LOWER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1005
-               NEURONSPI_REGFUN_SERIAL_NR_UPPER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1006
-               NEURONSPI_REGFUN_INTERRUPTS | NEURONSPI_REGFLAG_ACC_AFAP,                                                                               // 1007
-               NEURONSPI_REGFUN_MWD_TO | NEURONSPI_REGFLAG_ACC_6SEC,                                                                                   // 1008
-               NEURONSPI_REGFUN_V_REF_INT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,              // 1009
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1010
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1011
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1012
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1013
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1014
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1015
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1016
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1017
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1018
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1019
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1020
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1021
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1022
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1023
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1024
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1025
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1026
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1027
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1028
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1029
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1030
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1031
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1032
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1033
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1034
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1035
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1036
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1037
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1038
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1039
-};
-
-#define NEURONSPI_BOARD_E16DIU14DI_HW_FEATURES {       \
-               .do_count =                                       0,    \
-               .ro_count =                                       0,    \
-               .ds_count =                                       0,    \
-               .di_count =                                       30,   \
-               .led_count =                              0,    \
-               .stm_ai_count =                           0,    \
-               .stm_ao_count =                           0,    \
-               .sec_ai_count =                           0,    \
-               .sec_ao_count =                           0,    \
-               .uart_master_count =              0,    \
-               .uart_slave_count =               0,    \
-               .pwm_channel_count =              0,    \
-               .wd_count =                               1,    \
-               .extension_sys_count =            0,    \
-               .light_count =                            0,    \
-               .owire_count =                            0,    \
-}
-
-#define NEURONSPI_BOARD_E16DIU14DI_HW_DEFINITION { \
-               .combination_board_id =         10, \
-               .lower_board_id =                       NEURONSPI_BOARD_LOWER_E16DI_ID, \
-               .upper_board_id =                       NEURONSPI_BOARD_UPPER_U14DI_ID, \
-               .name_length =                          13, \
-               .combination_name =                     "E_16Di_U_14Di", \
-               .block_count =                          NEURONSPI_BOARD_E16DIU14DI_HW_DEFINITION_BLOCK_SIZE, \
-               .blocks =                                       NEURONSPI_BOARD_E16DIU14DI_HW_DEFINITION_BLOCK, \
-               .features =                                     NEURONSPI_BOARD_E16DIU14DI_HW_FEATURES \
-}
-static struct neuronspi_board_combination NEURONSPI_BOARD_E16DIU14DI_HW_COMBINATION[] = {NEURONSPI_BOARD_E16DIU14DI_HW_DEFINITION};
-
-// E-4Ai4Ao
-#define NEURONSPI_BOARD_E4AI4AO_HW_DEFINITION_BLOCK_SIZE 15
-static u32 NEURONSPI_BOARD_E4AI4AO_HW_DEFINITION_BLOCK[NEURONSPI_BOARD_E4AI4AO_HW_DEFINITION_BLOCK_SIZE] = {
-               0, 1,   // Register block beginning and size
-               NEURONSPI_REGFUN_DO_RW | NEURONSPI_REGFLAG_ACC_10HZ | NEURONSPI_REGFLAG_SYS_READ_ONLY,                  // 0
-               1000, 10, // Register block beginning and size
-               NEURONSPI_REGFUN_SW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,                 // 1000
-               NEURONSPI_REGFUN_DIDO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,             // 1001
-               NEURONSPI_REGFUN_UAIO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,             // 1002
-               NEURONSPI_REGFUN_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,                 // 1003
-               NEURONSPI_REGFUN_FLASH_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,   // 1004
-               NEURONSPI_REGFUN_SERIAL_NR_LOWER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1005
-               NEURONSPI_REGFUN_SERIAL_NR_UPPER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1006
-               NEURONSPI_REGFUN_INTERRUPTS | NEURONSPI_REGFLAG_ACC_AFAP,                                                                               // 1007
-               NEURONSPI_REGFUN_MWD_TO | NEURONSPI_REGFLAG_ACC_6SEC,                                                                                   // 1008
-               NEURONSPI_REGFUN_V_REF_INT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,              // 1009
-};
-
-#define NEURONSPI_BOARD_E4AI4AO_HW_FEATURES {  \
-               .do_count =                                       0,    \
-               .ro_count =                                       0,    \
-               .ds_count =                                       0,    \
-               .di_count =                                       0,    \
-               .led_count =                              0,    \
-               .stm_ai_count =                           0,    \
-               .stm_ao_count =                           0,    \
-               .sec_ai_count =                           4,    \
-               .sec_ao_count =                           4,    \
-               .uart_master_count =              0,    \
-               .uart_slave_count =               0,    \
-               .pwm_channel_count =              0,    \
-               .wd_count =                               1,    \
-               .extension_sys_count =            0,    \
-               .light_count =                            0,    \
-               .owire_count =                            0,    \
-}
-
-
-#define NEURONSPI_BOARD_E4AI4AO_HW_DEFINITION { \
-               .combination_board_id =         11, \
-               .lower_board_id =                       NEURONSPI_BOARD_LOWER_E4AI4AO_ID, \
-               .upper_board_id =                       NEURONSPI_BOARD_UPPER_NONE_ID, \
-               .name_length =                          8, \
-               .combination_name =                     "E_4Ai4Ao", \
-               .block_count =                          NEURONSPI_BOARD_E4AI4AO_HW_DEFINITION_BLOCK_SIZE, \
-               .blocks =                                       NEURONSPI_BOARD_E4AI4AO_HW_DEFINITION_BLOCK, \
-               .features =                                     NEURONSPI_BOARD_E4AI4AO_HW_FEATURES \
-}
-static struct neuronspi_board_combination NEURONSPI_BOARD_E4AI4AO_HW_COMBINATION[] = {NEURONSPI_BOARD_E4AI4AO_HW_DEFINITION};
-
-// E-4Ai4Ao_P-6Di5Ro (xS50)
-#define NEURONSPI_BOARD_E4AI4AOP6DI5RO_HW_DEFINITION_BLOCK_SIZE 56
-static u32 NEURONSPI_BOARD_E4AI4AOP6DI5RO_HW_DEFINITION_BLOCK[NEURONSPI_BOARD_E4AI4AOP6DI5RO_HW_DEFINITION_BLOCK_SIZE] = {
-               0, 27,  // Register block beginning and size
-               NEURONSPI_REGFUN_DI_READ | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY,                        // 0
-               NEURONSPI_REGFUN_DO_RW | NEURONSPI_REGFLAG_ACC_10HZ,                                                                                            // 1
-               NEURONSPI_REGFUN_AO_VER2_RW | NEURONSPI_REGFLAG_ACC_10HZ,                                                                                       // 2
-               NEURONSPI_REGFUN_AO_VER2_RW | NEURONSPI_REGFLAG_ACC_10HZ,                                                                                       // 3
-               NEURONSPI_REGFUN_AO_VER2_RW | NEURONSPI_REGFLAG_ACC_10HZ,                                                                                       // 4
-               NEURONSPI_REGFUN_AO_VER2_RW | NEURONSPI_REGFLAG_ACC_10HZ,                                                                                       // 5
-               NEURONSPI_REGFUN_AI_VER2_READ_LOWER | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY,     // 6
-               NEURONSPI_REGFUN_AI_VER2_READ_UPPER | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY,     // 7
-               NEURONSPI_REGFUN_AI_VER2_READ_LOWER | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY,     // 8
-               NEURONSPI_REGFUN_AI_VER2_READ_UPPER | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY,     // 9
-               NEURONSPI_REGFUN_AI_VER2_READ_LOWER | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY,     // 10
-               NEURONSPI_REGFUN_AI_VER2_READ_UPPER | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY,     // 11
-               NEURONSPI_REGFUN_AI_VER2_READ_LOWER | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY,     // 12
-               NEURONSPI_REGFUN_AI_VER2_READ_UPPER | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY,     // 13
-               NEURONSPI_REGFUN_MWD_STATUS | NEURONSPI_REGFLAG_ACC_6SEC,                                                                                       // 14
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                         // 15
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                         // 16
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                         // 17
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                         // 18
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                         // 19
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                         // 20
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                         // 21
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                         // 22
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                         // 23
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                         // 24
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                         // 25
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                         // 26
-               1000, 25, // Register block beginning and size
-               NEURONSPI_REGFUN_SW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,                 // 1000
-               NEURONSPI_REGFUN_DIDO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,             // 1001
-               NEURONSPI_REGFUN_UAIO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,             // 1002
-               NEURONSPI_REGFUN_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,                 // 1003
-               NEURONSPI_REGFUN_FLASH_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,   // 1004
-               NEURONSPI_REGFUN_SERIAL_NR_LOWER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1005
-               NEURONSPI_REGFUN_SERIAL_NR_UPPER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1006
-               NEURONSPI_REGFUN_INTERRUPTS | NEURONSPI_REGFLAG_ACC_AFAP,                                                                               // 1007
-               NEURONSPI_REGFUN_MWD_TO | NEURONSPI_REGFLAG_ACC_6SEC,                                                                                   // 1008
-               NEURONSPI_REGFUN_V_REF_INT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,              // 1009
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1010
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1011
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1012
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1013
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1014
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                              // 1015
-               NEURONSPI_REGFUN_DS_ENABLE   | NEURONSPI_REGFLAG_ACC_1HZ,                                                                               // 1016
-               NEURONSPI_REGFUN_DS_POLARITY | NEURONSPI_REGFLAG_ACC_1HZ,                                                                               // 1017
-               NEURONSPI_REGFUN_DS_TOGGLE   | NEURONSPI_REGFLAG_ACC_1HZ,                                                                               // 1018
-               NEURONSPI_REGFUN_AI_VER2_MODE | NEURONSPI_REGFLAG_ACC_1HZ,                                                                              // 1019
-               NEURONSPI_REGFUN_AI_VER2_MODE | NEURONSPI_REGFLAG_ACC_1HZ,                                                                              // 1020
-               NEURONSPI_REGFUN_AI_VER2_MODE | NEURONSPI_REGFLAG_ACC_1HZ,                                                                              // 1021
-               NEURONSPI_REGFUN_AI_VER2_MODE | NEURONSPI_REGFLAG_ACC_1HZ,                                                                              // 1022
-               NEURONSPI_REGFUN_RS485_CONFIG | NEURONSPI_REGFLAG_ACC_6SEC,                                                                             // 1023
-               NEURONSPI_REGFUN_RS485_ADDRESS | NEURONSPI_REGFLAG_ACC_6SEC                                                                             // 1024
-};
-
-#define NEURONSPI_BOARD_E4AI4AOP6DI5RO_HW_FEATURES {   \
-               .do_count =                                       0,    \
-               .ro_count =                                       6,    \
-               .ds_count =                                       5,    \
-               .di_count =                                       5,    \
-               .led_count =                              0,    \
-               .stm_ai_count =                           0,    \
-               .stm_ao_count =                           0,    \
-               .sec_ai_count =                           4,    \
-               .sec_ao_count =                           4,    \
-               .uart_master_count =              0,    \
-               .uart_slave_count =               1,    \
-               .pwm_channel_count =              0,    \
-               .wd_count =                               1,    \
-               .extension_sys_count =            1,    \
-               .light_count =                            0,    \
-               .owire_count =                            0,    \
-}
-
-#define NEURONSPI_BOARD_E4AI4AOP6DI5RO_HW_DEFINITION { \
-               .combination_board_id =         12, \
-               .lower_board_id =                       NEURONSPI_BOARD_LOWER_E4AI4AO_ID, \
-               .upper_board_id =                       NEURONSPI_BOARD_UPPER_P6DI5RO_ID, \
-               .name_length =                          17, \
-               .combination_name =                     "E_4Ai4Ao_P_6Di5Ro", \
-               .block_count =                          NEURONSPI_BOARD_E4AI4AOP6DI5RO_HW_DEFINITION_BLOCK_SIZE, \
-               .blocks =                                       NEURONSPI_BOARD_E4AI4AOP6DI5RO_HW_DEFINITION_BLOCK, \
-               .features =                                     NEURONSPI_BOARD_E4AI4AOP6DI5RO_HW_FEATURES \
-}
-static struct neuronspi_board_combination NEURONSPI_BOARD_E4AI4AOP6DI5RO_HW_COMBINATION[] = {NEURONSPI_BOARD_E4AI4AOP6DI5RO_HW_DEFINITION};
-
-// B-485
-#define NEURONSPI_BOARD_B485_HW_DEFINITION_BLOCK_SIZE 15
-static u32 NEURONSPI_BOARD_B485_HW_DEFINITION_BLOCK[NEURONSPI_BOARD_B485_HW_DEFINITION_BLOCK_SIZE] = {
-               0, 1,   // Register block beginning and size
-               NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE,                                                                                // 0
-               1000, 10,
-               NEURONSPI_REGFUN_SW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,                 // 1000
-               NEURONSPI_REGFUN_DIDO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,             // 1001
-               NEURONSPI_REGFUN_UAIO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,             // 1002
-               NEURONSPI_REGFUN_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,                 // 1003
-               NEURONSPI_REGFUN_FLASH_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,   // 1004
-               NEURONSPI_REGFUN_SERIAL_NR_LOWER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1005
-               NEURONSPI_REGFUN_SERIAL_NR_UPPER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1006
-               NEURONSPI_REGFUN_INTERRUPTS | NEURONSPI_REGFLAG_ACC_AFAP,                                                                               // 1007
-               NEURONSPI_REGFUN_MWD_TO | NEURONSPI_REGFLAG_ACC_6SEC,                                                                                   // 1008
-               NEURONSPI_REGFUN_V_REF_INT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,              // 1009
-};
-
-#define NEURONSPI_BOARD_B485_HW_FEATURES {     \
-       .do_count =                                       0,    \
-       .ro_count =                                       0,    \
-       .ds_count =                                       0,    \
-       .di_count =                                       0,    \
-       .led_count =                              0,    \
-       .stm_ai_count =                           0,    \
-       .stm_ao_count =                           0,    \
-       .sec_ai_count =                           4,    \
-       .sec_ao_count =                           4,    \
-       .uart_master_count =              1,    \
-       .uart_slave_count =               0,    \
-       .pwm_channel_count =              0,    \
-       .wd_count =                               1,    \
-       .extension_sys_count =            0,    \
-       .light_count =                            0,    \
-       .owire_count =                            0,    \
-}
-
-#define NEURONSPI_BOARD_B485_HW_DEFINITION { \
-               .combination_board_id =         13, \
-               .lower_board_id =                       NEURONSPI_BOARD_LOWER_B485_ID, \
-               .upper_board_id =                       NEURONSPI_BOARD_UPPER_NONE_ID, \
-               .name_length =                          5, \
-               .combination_name =                     "B_485", \
-               .block_count =                          NEURONSPI_BOARD_B485_HW_DEFINITION_BLOCK_SIZE, \
-               .blocks =                                       NEURONSPI_BOARD_B485_HW_DEFINITION_BLOCK, \
-               .features =                                     NEURONSPI_BOARD_B485_HW_FEATURES \
-}
-static struct neuronspi_board_combination NEURONSPI_BOARD_B485_HW_COMBINATION[] = {NEURONSPI_BOARD_B485_HW_DEFINITION};
-
-// E-4Light (M613)
-#define NEURONSPI_BOARD_E4LIGHT_HW_DEFINITION_BLOCK_SIZE 35
-static u32 NEURONSPI_BOARD_E4LIGHT_HW_DEFINITION_BLOCK[NEURONSPI_BOARD_E4LIGHT_HW_DEFINITION_BLOCK_SIZE] = {
-               0, 21,  // Register block beginning and size
-               NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE,                                                                                // 0
-               NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE,                                                                                // 1
-               NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE,                                                                                // 2
-               NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE,                                                                                // 3
-               NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE,                                                                                // 4
-               NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE,                                                                                // 5
-               NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE,                                                                                // 6
-               NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE,                                                                                // 7
-               NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE,                                                                                // 8
-               NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE,                                                                                // 9
-               NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE,                                                                                // 10
-               NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE,                                                                                // 11
-               NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE,                                                                                // 12
-               NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE,                                                                                // 13
-               NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE,                                                                                // 14
-               NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE,                                                                                // 15
-               NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE,                                                                                // 16
-               NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE,                                                                                // 17
-               NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE,                                                                                // 18
-               NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE,                                                                                // 19
-               NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE,                                                                                // 20
-               1000, 10,
-               NEURONSPI_REGFUN_SW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,                 // 1000
-               NEURONSPI_REGFUN_DIDO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,             // 1001
-               NEURONSPI_REGFUN_UAIO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,             // 1002
-               NEURONSPI_REGFUN_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,                 // 1003
-               NEURONSPI_REGFUN_FLASH_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,   // 1004
-               NEURONSPI_REGFUN_SERIAL_NR_LOWER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1005
-               NEURONSPI_REGFUN_SERIAL_NR_UPPER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1006
-               NEURONSPI_REGFUN_INTERRUPTS | NEURONSPI_REGFLAG_ACC_AFAP,                                                                               // 1007
-               NEURONSPI_REGFUN_MWD_TO | NEURONSPI_REGFLAG_ACC_6SEC,                                                                                   // 1008
-               NEURONSPI_REGFUN_V_REF_INT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,              // 1009
-};
-
-#define NEURONSPI_BOARD_E4LIGHT_HW_FEATURES {  \
-       .do_count =                                       0,    \
-       .ro_count =                                       0,    \
-       .ds_count =                                       0,    \
-       .di_count =                                       0,    \
-       .led_count =                              0,    \
-       .stm_ai_count =                           0,    \
-       .stm_ao_count =                           0,    \
-       .sec_ai_count =                           0,    \
-       .sec_ao_count =                           0,    \
-       .uart_master_count =              0,    \
-       .uart_slave_count =               0,    \
-       .pwm_channel_count =              0,    \
-       .wd_count =                               1,    \
-       .extension_sys_count =            0,    \
-       .light_count =                            4,    \
-       .owire_count =                            0,    \
-}
-
-#define NEURONSPI_BOARD_E4LIGHT_HW_DEFINITION { \
-               .combination_board_id =         14, \
-               .lower_board_id =                       NEURONSPI_BOARD_LOWER_E4LIGHT_ID, \
-               .upper_board_id =                       NEURONSPI_BOARD_UPPER_NONE_ID, \
-               .name_length =                          8, \
-               .combination_name =                     "E_4Light", \
-               .block_count =                          NEURONSPI_BOARD_E4LIGHT_HW_DEFINITION_BLOCK_SIZE, \
-               .blocks =                                       NEURONSPI_BOARD_E4LIGHT_HW_DEFINITION_BLOCK, \
-               .features =                                     NEURONSPI_BOARD_E4LIGHT_HW_FEATURES \
-}
-static struct neuronspi_board_combination NEURONSPI_BOARD_E4LIGHT_HW_COMBINATION[] = {NEURONSPI_BOARD_E4LIGHT_HW_DEFINITION};
-
-// E-4Ai4Ao_U-6Di5Ro (L503)
-#define NEURONSPI_BOARD_E4AI4AOU6DI5RO_HW_DEFINITION_BLOCK_SIZE 56
-static u32 NEURONSPI_BOARD_E4AI4AOU6DI5RO_HW_DEFINITION_BLOCK[NEURONSPI_BOARD_E4AI4AOU6DI5RO_HW_DEFINITION_BLOCK_SIZE] = {
-               0, 28,  // Register block beginning and size
-               NEURONSPI_REGFUN_DI_READ | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY,                                // 0
-               NEURONSPI_REGFUN_DO_RW | NEURONSPI_REGFLAG_ACC_10HZ,                                                                                                    // 1
-               NEURONSPI_REGFUN_AO_VER2_RW | NEURONSPI_REGFLAG_ACC_AFAP,                                                                                               // 2
-               NEURONSPI_REGFUN_AO_VER2_RW | NEURONSPI_REGFLAG_ACC_AFAP,                                                                                               // 3
-               NEURONSPI_REGFUN_AO_VER2_RW | NEURONSPI_REGFLAG_ACC_AFAP,                                                                                               // 4
-               NEURONSPI_REGFUN_AO_VER2_RW | NEURONSPI_REGFLAG_ACC_AFAP,                                                                                               // 5
-               NEURONSPI_REGFUN_AI_VER2_READ_LOWER | NEURONSPI_REGFLAG_ACC_AFAP,       // 6
-               NEURONSPI_REGFUN_AI_VER2_READ_UPPER | NEURONSPI_REGFLAG_ACC_AFAP,       // 7
-               NEURONSPI_REGFUN_AI_VER2_READ_LOWER | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY,     // 8
-               NEURONSPI_REGFUN_AI_VER2_READ_UPPER | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY,     // 9
-               NEURONSPI_REGFUN_AI_VER2_READ_LOWER | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY,     // 10
-               NEURONSPI_REGFUN_AI_VER2_READ_UPPER | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY,     // 11
-               NEURONSPI_REGFUN_AI_VER2_READ_LOWER | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY,     // 12
-               NEURONSPI_REGFUN_AI_VER2_READ_UPPER | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY,     // 13
-               NEURONSPI_REGFUN_MWD_STATUS | NEURONSPI_REGFLAG_ACC_6SEC | NEURONSPI_REGFLAG_SYS_READ_ONLY,                     // 14
-               NEURONSPI_REGFUN_TX_QUEUE_LEN | NEURONSPI_REGFLAG_ACC_10HZ,                                                                                             // 15
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                                 // 16
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                                 // 17
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                                 // 18
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                                 // 19
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                                 // 20
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                                 // 21
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                                 // 22
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                                 // 23
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                                 // 24
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                                 // 25
-               NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                                 // 26
-               NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC,                                                                                 // 27
-               1000, 24, // Register block beginning and size
-               NEURONSPI_REGFUN_SW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,                                 // 1000
-               NEURONSPI_REGFUN_DIDO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,                             // 1001
-               NEURONSPI_REGFUN_UAIO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,                             // 1002
-               NEURONSPI_REGFUN_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,                                 // 1003
-               NEURONSPI_REGFUN_FLASH_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,                   // 1004
-               NEURONSPI_REGFUN_SERIAL_NR_LOWER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,                // 1005
-               NEURONSPI_REGFUN_SERIAL_NR_UPPER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,                // 1006
-               NEURONSPI_REGFUN_INTERRUPTS | NEURONSPI_REGFLAG_ACC_AFAP,                                                                                               // 1007
-               NEURONSPI_REGFUN_MWD_TO | NEURONSPI_REGFLAG_ACC_6SEC,                                                                                                   // 1008
-               NEURONSPI_REGFUN_V_REF_INT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,                              // 1009
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                                              // 1010
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                                              // 1011
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                                              // 1012
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                                              // 1013
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                                              // 1014
-               NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC,                                                                                              // 1015
-               NEURONSPI_REGFUN_DS_ENABLE | NEURONSPI_REGFLAG_ACC_1HZ,                                                                                                 // 1016
-               NEURONSPI_REGFUN_DS_POLARITY | NEURONSPI_REGFLAG_ACC_1HZ,                                                                                               // 1017
-               NEURONSPI_REGFUN_DS_TOGGLE | NEURONSPI_REGFLAG_ACC_1HZ,                                                                                                 // 1018
-               NEURONSPI_REGFUN_AI_VER2_MODE | NEURONSPI_REGFLAG_ACC_1HZ,                                                                                              // 1019
-               NEURONSPI_REGFUN_AI_VER2_MODE | NEURONSPI_REGFLAG_ACC_1HZ,                                                                                              // 1020
-               NEURONSPI_REGFUN_AI_VER2_MODE | NEURONSPI_REGFLAG_ACC_1HZ,                                                                                              // 1021
-               NEURONSPI_REGFUN_AI_VER2_MODE | NEURONSPI_REGFLAG_ACC_1HZ,                                                                                              // 1022
-               NEURONSPI_REGFUN_RS485_CONFIG | NEURONSPI_REGFLAG_ACC_6SEC                                                                                              // 1023
-};
-
-#define NEURONSPI_BOARD_E4AI4AOU6DI5RO_HW_FEATURES {   \
-       .do_count =                                       0,    \
-       .ro_count =                                       5,    \
-       .ds_count =                                       5,    \
-       .di_count =                                       6,    \
-       .led_count =                              0,    \
-       .stm_ai_count =                           0,    \
-       .stm_ao_count =                           0,    \
-       .sec_ai_count =                           4,    \
-       .sec_ao_count =                           4,    \
-       .uart_master_count =              0,    \
-       .uart_slave_count =               0,    \
-       .pwm_channel_count =              0,    \
-       .wd_count =                               1,    \
-       .extension_sys_count =            0,    \
-       .light_count =                            4,    \
-       .owire_count =                            0,    \
-}
-
-#define NEURONSPI_BOARD_E4AI4AOU6DI5RO_HW_DEFINITION { \
-               .combination_board_id =         15, \
-               .lower_board_id =                       NEURONSPI_BOARD_LOWER_E4AI4AO_ID, \
-               .upper_board_id =                       NEURONSPI_BOARD_UPPER_U6DI5RO_ID, \
-               .name_length =                          17, \
-               .combination_name =                     "E_4Ai4Ao_U_6Di5Ro", \
-               .block_count =                          NEURONSPI_BOARD_E4AI4AOU6DI5RO_HW_DEFINITION_BLOCK_SIZE, \
-               .blocks =                                       NEURONSPI_BOARD_E4AI4AOU6DI5RO_HW_DEFINITION_BLOCK, \
-               .features =                                     NEURONSPI_BOARD_E4AI4AOU6DI5RO_HW_FEATURES \
-}
-static struct neuronspi_board_combination NEURONSPI_BOARD_E4AI4AOU6DI5RO_HW_COMBINATION[] = {NEURONSPI_BOARD_E4AI4AOU6DI5RO_HW_DEFINITION};
-
-/*********************
- * Model Definitions *
- *********************/
-
-#define NEURONSPI_MODEL_S103_HW_DEFINITION_BOARD_SIZE 1
-struct neuronspi_board_combination NEURONSPI_MODEL_S103_HW_DEFINITION_BOARD[NEURONSPI_MODEL_S103_HW_DEFINITION_BOARD_SIZE] = {
-               NEURONSPI_BOARD_B1000_HW_DEFINITION
-};
-
-#define NEURONSPI_MODEL_S103G_HW_DEFINITION_BOARD_SIZE 1
-struct neuronspi_board_combination NEURONSPI_MODEL_S103G_HW_DEFINITION_BOARD[NEURONSPI_MODEL_S103G_HW_DEFINITION_BOARD_SIZE] = {
-               NEURONSPI_BOARD_B1000_HW_DEFINITION
-};
-
-#define NEURONSPI_MODEL_S103IQ_HW_DEFINITION_BOARD_SIZE 1
-struct neuronspi_board_combination NEURONSPI_MODEL_S103IQ_HW_DEFINITION_BOARD[NEURONSPI_MODEL_S103IQ_HW_DEFINITION_BOARD_SIZE] = {
-               NEURONSPI_BOARD_B1000_HW_DEFINITION
-};
-
-#define NEURONSPI_MODEL_S103EO_HW_DEFINITION_BOARD_SIZE 1
-struct neuronspi_board_combination NEURONSPI_MODEL_S103EO_HW_DEFINITION_BOARD[NEURONSPI_MODEL_S103EO_HW_DEFINITION_BOARD_SIZE] = {
-               NEURONSPI_BOARD_B1000_HW_DEFINITION
-};
-
-#define NEURONSPI_MODEL_M103_HW_DEFINITION_BOARD_SIZE 2
-struct neuronspi_board_combination NEURONSPI_MODEL_M103_HW_DEFINITION_BOARD[NEURONSPI_MODEL_M103_HW_DEFINITION_BOARD_SIZE] = {
-               NEURONSPI_BOARD_B1000_HW_DEFINITION, NEURONSPI_BOARD_E8DI8RO_HW_DEFINITION
-};
-
-#define NEURONSPI_MODEL_M203_HW_DEFINITION_BOARD_SIZE 2
-struct neuronspi_board_combination NEURONSPI_MODEL_M203_HW_DEFINITION_BOARD[NEURONSPI_MODEL_M203_HW_DEFINITION_BOARD_SIZE] = {
-               NEURONSPI_BOARD_B1000_HW_DEFINITION, NEURONSPI_BOARD_E16DIU14RO_HW_DEFINITION
-};
-
-#define NEURONSPI_MODEL_M303_HW_DEFINITION_BOARD_SIZE 2
-struct neuronspi_board_combination NEURONSPI_MODEL_M303_HW_DEFINITION_BOARD[NEURONSPI_MODEL_M303_HW_DEFINITION_BOARD_SIZE] = {
-               NEURONSPI_BOARD_B1000_HW_DEFINITION, NEURONSPI_BOARD_E16DIU14DI_HW_DEFINITION
-};
-
-#define NEURONSPI_MODEL_M403_HW_DEFINITION_BOARD_SIZE 2
-struct neuronspi_board_combination NEURONSPI_MODEL_M403_HW_DEFINITION_BOARD[NEURONSPI_MODEL_M403_HW_DEFINITION_BOARD_SIZE] = {
-               NEURONSPI_BOARD_B1000_HW_DEFINITION, NEURONSPI_BOARD_E14ROU14RO_HW_DEFINITION
-};
-
-#define NEURONSPI_MODEL_M503_HW_DEFINITION_BOARD_SIZE 2
-struct neuronspi_board_combination NEURONSPI_MODEL_M503_HW_DEFINITION_BOARD[NEURONSPI_MODEL_M503_HW_DEFINITION_BOARD_SIZE] = {
-               NEURONSPI_BOARD_B1000_HW_DEFINITION, NEURONSPI_BOARD_E4AI4AOU6DI5RO_HW_DEFINITION
-};
-
-#define NEURONSPI_MODEL_M603_HW_DEFINITION_BOARD_SIZE 2
-struct neuronspi_board_combination NEURONSPI_MODEL_M603_HW_DEFINITION_BOARD[NEURONSPI_MODEL_M603_HW_DEFINITION_BOARD_SIZE] = {
-               NEURONSPI_BOARD_B1000_HW_DEFINITION, NEURONSPI_BOARD_E4LIGHT_HW_DEFINITION
-};
-
-#define NEURONSPI_MODEL_L203_HW_DEFINITION_BOARD_SIZE 3
-struct neuronspi_board_combination NEURONSPI_MODEL_L203_HW_DEFINITION_BOARD[NEURONSPI_MODEL_L203_HW_DEFINITION_BOARD_SIZE] = {
-               NEURONSPI_BOARD_B1000_HW_DEFINITION, NEURONSPI_BOARD_E16DIU14RO_HW_DEFINITION, NEURONSPI_BOARD_E16DIU14RO_HW_DEFINITION
-};
-
-#define NEURONSPI_MODEL_L303_HW_DEFINITION_BOARD_SIZE 3
-struct neuronspi_board_combination NEURONSPI_MODEL_L303_HW_DEFINITION_BOARD[NEURONSPI_MODEL_L303_HW_DEFINITION_BOARD_SIZE] = {
-               NEURONSPI_BOARD_B1000_HW_DEFINITION, NEURONSPI_BOARD_E16DIU14DI_HW_DEFINITION, NEURONSPI_BOARD_E16DIU14DI_HW_DEFINITION
-};
-
-#define NEURONSPI_MODEL_L403_HW_DEFINITION_BOARD_SIZE 3
-struct neuronspi_board_combination NEURONSPI_MODEL_L403_HW_DEFINITION_BOARD[NEURONSPI_MODEL_L403_HW_DEFINITION_BOARD_SIZE] = {
-               NEURONSPI_BOARD_B1000_HW_DEFINITION, NEURONSPI_BOARD_E14ROU14RO_HW_DEFINITION, NEURONSPI_BOARD_E14ROU14RO_HW_DEFINITION
-};
-
-#define NEURONSPI_MODEL_L503_HW_DEFINITION_BOARD_SIZE 3
-struct neuronspi_board_combination NEURONSPI_MODEL_L503_HW_DEFINITION_BOARD[NEURONSPI_MODEL_L503_HW_DEFINITION_BOARD_SIZE] = {
-               NEURONSPI_BOARD_B1000_HW_DEFINITION,  NEURONSPI_BOARD_E4AI4AOU6DI5RO_HW_DEFINITION, NEURONSPI_BOARD_E14ROU14DI_HW_DEFINITION
-};
-
-#define NEURONSPI_MODEL_L513_HW_DEFINITION_BOARD_SIZE 3
-struct neuronspi_board_combination NEURONSPI_MODEL_L513_HW_DEFINITION_BOARD[NEURONSPI_MODEL_L513_HW_DEFINITION_BOARD_SIZE] = {
-               NEURONSPI_BOARD_B1000_HW_DEFINITION, NEURONSPI_BOARD_E4AI4AOU6DI5RO_HW_DEFINITION, NEURONSPI_BOARD_E4AI4AOU6DI5RO_HW_DEFINITION
-};
-
-// Board table
-// Column 4 is the number of 0-indexed registers and column 5 is the number of 1000-indexed ones
-#define NEURONSPI_BOARDTABLE_LEN               16
-static struct neuronspi_board_entry NEURONSPI_BOARDTABLE[NEURONSPI_BOARDTABLE_LEN] = {
-       {.index = 0, .lower_board_id = NEURONSPI_BOARD_LOWER_B1000_ID,          .upper_board_id = NEURONSPI_BOARD_UPPER_NONE_ID,
-                       .data_register_count = 21,      .config_register_count = 32, .definition = NEURONSPI_BOARD_B1000_HW_COMBINATION},       // B_1000 (S103)
-       {.index = 1, .lower_board_id = NEURONSPI_BOARD_LOWER_E8DI8RO_ID,        .upper_board_id = NEURONSPI_BOARD_UPPER_NONE_ID,
-                       .data_register_count = 19,      .config_register_count = 21, .definition = NEURONSPI_BOARD_E8DI8RO_HW_COMBINATION},     // E-8Di8Ro (M103)
-       {.index = 2, .lower_board_id = NEURONSPI_BOARD_LOWER_E14RO_ID,          .upper_board_id = NEURONSPI_BOARD_UPPER_NONE_ID,
-                       .data_register_count = 1,       .config_register_count = 0,  .definition = NEURONSPI_BOARD_E14RO_HW_COMBINATION},               // E-14Ro
-       {.index = 3, .lower_board_id = NEURONSPI_BOARD_LOWER_E16DI_ID,          .upper_board_id = NEURONSPI_BOARD_UPPER_NONE_ID,
-                       .data_register_count = 1,       .config_register_count = 0,      .definition = NEURONSPI_BOARD_E16DI_HW_COMBINATION},           // E-16Di
-       {.index = 4, .lower_board_id = NEURONSPI_BOARD_LOWER_E8DI8RO_ID,        .upper_board_id = NEURONSPI_BOARD_UPPER_P11DIR485_ID,
-                       .data_register_count = 36,      .config_register_count = 31,  .definition = NEURONSPI_BOARD_E8DI8ROP11DIR485_HW_COMBINATION},   // E-8Di8Ro_P-11DiR485 (xS10)
-       {.index = 5, .lower_board_id = NEURONSPI_BOARD_LOWER_E14RO_ID,          .upper_board_id = NEURONSPI_BOARD_UPPER_P11DIR485_ID,
-                       .data_register_count = 20,      .config_register_count = 23,  .definition = NEURONSPI_BOARD_E14ROP11DIR485_HW_COMBINATION},     // E-14Ro_P-11DiR485 (xS40)
-       {.index = 6, .lower_board_id = NEURONSPI_BOARD_LOWER_E16DI_ID,          .upper_board_id = NEURONSPI_BOARD_UPPER_P11DIR485_ID,
-                       .data_register_count = 52,      .config_register_count = 36,  .definition = NEURONSPI_BOARD_E16DIP11DIR485_HW_COMBINATION},     // E-16Di_P-11DiR485 (xS30)
-       {.index = 7, .lower_board_id = NEURONSPI_BOARD_LOWER_E14RO_ID,          .upper_board_id = NEURONSPI_BOARD_UPPER_U14RO_ID,
-                       .data_register_count = 3,       .config_register_count = 10,  .definition = NEURONSPI_BOARD_E14ROU14RO_HW_COMBINATION}, // E-14Ro_U-14Ro (M403)
-       {.index = 8, .lower_board_id = NEURONSPI_BOARD_LOWER_E16DI_ID,          .upper_board_id = NEURONSPI_BOARD_UPPER_U14RO_ID,
-                       .data_register_count = 35,      .config_register_count = 29,  .definition = NEURONSPI_BOARD_E16DIU14RO_HW_COMBINATION}, // E-16Di_U-14Ro (M203)
-       {.index = 9, .lower_board_id = NEURONSPI_BOARD_LOWER_E14RO_ID,          .upper_board_id = NEURONSPI_BOARD_UPPER_U14DI_ID,
-                       .data_register_count = 31,      .config_register_count = 27,  .definition = NEURONSPI_BOARD_E14ROU14DI_HW_COMBINATION}, // E-14Ro_U-14Di (L503)
-       {.index = 10, .lower_board_id = NEURONSPI_BOARD_LOWER_E16DI_ID,         .upper_board_id = NEURONSPI_BOARD_UPPER_U14DI_ID,
-                       .data_register_count = 63, .config_register_count = 40,   .definition = NEURONSPI_BOARD_E16DIU14DI_HW_COMBINATION},     // E-16Di_U-14Di (M303)
-       {.index = 11, .lower_board_id = NEURONSPI_BOARD_LOWER_E4AI4AO_ID,       .upper_board_id = NEURONSPI_BOARD_UPPER_NONE_ID,
-                       .data_register_count = 1,       .config_register_count = 0,   .definition = NEURONSPI_BOARD_E4AI4AO_HW_COMBINATION},            // E-4Ai4Ao
-       {.index = 12, .lower_board_id = NEURONSPI_BOARD_LOWER_E4AI4AO_ID,       .upper_board_id = NEURONSPI_BOARD_UPPER_P6DI5RO_ID,
-                       .data_register_count = 27, .config_register_count = 25,   .definition = NEURONSPI_BOARD_E4AI4AOP6DI5RO_HW_COMBINATION}, // E-4Ai4Ao_P-6Di5Ro (xS50)
-       {.index = 13, .lower_board_id = NEURONSPI_BOARD_LOWER_B485_ID,          .upper_board_id = NEURONSPI_BOARD_UPPER_NONE_ID,
-                       .data_register_count = 1,  .config_register_count = 0,    .definition = NEURONSPI_BOARD_B485_HW_COMBINATION},           // B-485
-       {.index = 14, .lower_board_id = NEURONSPI_BOARD_LOWER_E4LIGHT_ID,       .upper_board_id = NEURONSPI_BOARD_UPPER_NONE_ID,
-                       .data_register_count = 21, .config_register_count = 8,    .definition = NEURONSPI_BOARD_E4LIGHT_HW_COMBINATION},                // E-4Light (M603)
-       {.index = 15, .lower_board_id = NEURONSPI_BOARD_LOWER_E4AI4AO_ID,       .upper_board_id = NEURONSPI_BOARD_UPPER_U6DI5RO_ID,
-                       .data_register_count = 28, .config_register_count = 24,   .definition = NEURONSPI_BOARD_E4AI4AOU6DI5RO_HW_COMBINATION}          // E-4Ai4Ao_U-6Di5Ro (M503)
-};
-
-// Module table
-#define NEURONSPI_MODELTABLE_LEN               15
-static struct neuronspi_model_definition NEURONSPI_MODELTABLE[NEURONSPI_MODELTABLE_LEN] = {
-               {.eeprom_length = 4, .eeprom_name = "S103", .name_length = 4, .model_name = "S103",
-                               .combination_count = 1, .combinations = NEURONSPI_MODEL_S103_HW_DEFINITION_BOARD},
-               {.eeprom_length = 4, .eeprom_name = "S103", .name_length = 6, .model_name = "S103-G",
-                               .combination_count = 1, .combinations = NEURONSPI_MODEL_S103G_HW_DEFINITION_BOARD},
-               {.eeprom_length = 6, .eeprom_name = "S103IQ", .name_length = 7, .model_name = "S103-IQ",
-                               .combination_count = 1, .combinations = NEURONSPI_MODEL_S103IQ_HW_DEFINITION_BOARD},
-               {.eeprom_length = 6, .eeprom_name = "S103EO", .name_length = 7, .model_name = "S103-EO",
-                               .combination_count = 1, .combinations = NEURONSPI_MODEL_S103EO_HW_DEFINITION_BOARD},
-               {.eeprom_length = 4, .eeprom_name = "M103", .name_length = 4, .model_name = "M103",
-                               .combination_count = 2, .combinations = NEURONSPI_MODEL_M103_HW_DEFINITION_BOARD},
-               {.eeprom_length = 4, .eeprom_name = "M203", .name_length = 4, .model_name = "M203",
-                               .combination_count = 2, .combinations = NEURONSPI_MODEL_M203_HW_DEFINITION_BOARD},
-               {.eeprom_length = 4, .eeprom_name = "M303", .name_length = 4, .model_name = "M303",
-                               .combination_count = 2, .combinations = NEURONSPI_MODEL_M303_HW_DEFINITION_BOARD},
-               {.eeprom_length = 4, .eeprom_name = "M403", .name_length = 4, .model_name = "M403",
-                               .combination_count = 2, .combinations = NEURONSPI_MODEL_M403_HW_DEFINITION_BOARD},
-               {.eeprom_length = 4, .eeprom_name = "M503", .name_length = 4, .model_name = "M503",
-                               .combination_count = 2, .combinations = NEURONSPI_MODEL_M503_HW_DEFINITION_BOARD},
-               {.eeprom_length = 4, .eeprom_name = "M603", .name_length = 4, .model_name = "M603",
-                               .combination_count = 2, .combinations = NEURONSPI_MODEL_M603_HW_DEFINITION_BOARD},
-               {.eeprom_length = 4, .eeprom_name = "L203", .name_length = 4, .model_name = "L203",
-                               .combination_count = 3, .combinations = NEURONSPI_MODEL_L203_HW_DEFINITION_BOARD},
-               {.eeprom_length = 4, .eeprom_name = "L303", .name_length = 4, .model_name = "L303",
-                               .combination_count = 3, .combinations = NEURONSPI_MODEL_L303_HW_DEFINITION_BOARD},
-               {.eeprom_length = 4, .eeprom_name = "L403", .name_length = 4, .model_name = "L403",
-                               .combination_count = 3, .combinations = NEURONSPI_MODEL_L403_HW_DEFINITION_BOARD},
-               {.eeprom_length = 4, .eeprom_name = "L503", .name_length = 4, .model_name = "L503",
-                               .combination_count = 3, .combinations = NEURONSPI_MODEL_L503_HW_DEFINITION_BOARD},
-               {.eeprom_length = 4, .eeprom_name = "L513", .name_length = 4, .model_name = "L513",
-                               .combination_count = 3, .combinations = NEURONSPI_MODEL_L513_HW_DEFINITION_BOARD}
-};
 
 
 /********************
@@ -1883,7 +157,7 @@ static const struct of_device_id neuronspi_id_match[] = {
                {.compatible = NEURON_DEVICE_NAME},
                {}
 };
-MODULE_DEVICE_TABLE(of, neuronspi_id_match);
+
 
 #define NEURON_INT_RX_NOT_EMPTY                        0x1
 #define NEURON_INT_TX_FINISHED                         0x2
@@ -1909,51 +183,6 @@ MODULE_DEVICE_TABLE(of, neuronspi_id_match);
  * Data structures *
  *******************/
 
-enum neuron_str_attribute_type {
-               NEURON_SATTR_MODEL,
-               NEURON_SATTR_EEPROM,
-               NEURON_SATTR_BOARD_NAME,
-               NEURON_SATTR_GPIO_GROUP_NAME
-};
-
-enum neuron_num_attribute_type {
-               NEURON_NATTR_BOARDCOUNT,
-               NEURON_NATTR_MODE,
-               NEURON_NATTR_CURRENT_VALUE
-};
-
-struct neuronspi_devtype
-{
-       u8      name[10];
-       int32_t nr_gpio;
-       int32_t nr_uart;
-};
-
-struct neuronspi_port
-{
-       struct uart_port                        port;
-       u8                                                      line;
-       struct kthread_work                     tx_work;
-       struct kthread_work                     rx_work;
-       struct kthread_work                     irq_work;
-       u32                                                     flags;
-       u8                                                      ier_clear;
-       u8                                                      buf[NEURONSPI_FIFO_SIZE];
-       struct neuronspi_uart_data      *parent;
-       u8                                                      dev_index;
-       u8                                                      dev_port;
-       u8                                                      parmrk_enabled;
-       u64                                                     parmrk_frame_delay;
-};
-
-struct neuronspi_uart_data
-{
-       const struct neuronspi_devtype  *devtype;
-       struct kthread_worker                   kworker;
-       struct task_struct                              *kworker_task;
-       struct neuronspi_port                   *p;
-       u8                                                              p_count;
-};
 
 static struct neuronspi_uart_data* neuronspi_uart_glob_data;
 
@@ -1961,187 +190,23 @@ static unsigned long neuronspi_lines;
 
 static struct uart_driver* neuronspi_uart;
 
-// Instantiated once
-struct neuronspi_char_driver
-{
-       int32_t major_number;
-       u8 *message;
-       u16 message_size;
-       u32 open_counter;
-       struct class* driver_class;
-       struct device* dev;
-};
-
-
-// Instantiated once per SPI device
-struct neuronspi_driver_data
-{
-       struct spi_driver *spi_driver;
-       struct neuronspi_char_driver *char_driver;
-       struct uart_driver *serial_driver;
-       struct neuronspi_uart_data *uart_data;
-       struct neuronspi_led_driver *led_driver;
-       struct neuronspi_di_driver **di_driver;
-       struct neuronspi_do_driver **do_driver;
-       struct neuronspi_ro_driver **ro_driver;
-       struct platform_device *board_device;
-       struct iio_dev *stm_ai_driver;
-       struct iio_dev *stm_ao_driver;
-       struct iio_dev **sec_ai_driver;
-       struct iio_dev **sec_ao_driver;
-       struct kthread_worker primary_worker;
-       struct task_struct *primary_worker_task;
-       struct regmap *reg_map;
-       struct task_struct *poll_thread;
-       struct mutex device_lock;
-       struct neuronspi_board_features *features;
-       struct neuronspi_board_regstart_table *regstart_table;
-       struct spinlock sysfs_regmap_lock;
-       char platform_name[sizeof("io_group0")];
-       u8 *send_buf;
-       u8 *recv_buf;
-       u8 *first_probe_reply;
-       u8 *second_probe_reply;
-       u8 reserved_device;
-       u8 uart_count;
-       u8 uart_read;
-       u8 *uart_buf;
-       u8 slower_model;
-       u8 no_irq;
-       u8 lower_board_id;
-       u8 upper_board_id;
-       u8 combination_id;
-       int32_t neuron_index;
-       uint16_t sysfs_regmap_target;
-       uint16_t sysfs_counter_target;
-       uint32_t ideal_frequency;
-};
-
-struct neuronspi_di_driver {
-       struct spi_device* spi;
-       struct gpio_chip gpio_c;
-       struct platform_device *plat_dev;
-       u8 di_index;
-       char name[sizeof("di_0_00")];
-};
-
-struct neuronspi_do_driver
-{
-       struct spi_device* spi;
-       struct gpio_chip gpio_c;
-       struct platform_device *plat_dev;
-       u8 do_index;
-       char name[sizeof("do_0_00")];
-};
-
-struct neuronspi_ro_driver
-{
-       struct spi_device* spi;
-       struct gpio_chip gpio_c;
-       struct platform_device *plat_dev;
-       u8 ro_index;
-       char name[sizeof("ro_0_00")];
-};
-
-struct neuronspi_sec_ai_driver
-{
-       struct iio *devices;
-       u16 dev_count;
-};
-
-struct neuronspi_sec_ao_driver
-{
-       struct iio *devices;
-       u16 dev_count;
-};
-
-struct neuronspi_stm_ai_data
-{
-       u32 mode;
-       struct spi_device *parent;
-};
-
-struct neuronspi_stm_ao_data
-{
-       u32 mode;
-       struct spi_device *parent;
-};
-
-struct neuronspi_sec_ai_data
-{
-       u32 index;
-       u32 mode;
-       struct spi_device *parent;
-};
-
-struct neuronspi_sec_ao_data
-{
-       u32 index;
-       u32 mode;
-       struct spi_device *parent;
-};
-
-// Instantiated once per LED
-struct neuronspi_led_driver
-{
-       struct led_classdev     ldev;
-       struct spi_device       *spi;
-       struct kthread_work     led_work;
-       int                                     id;
-       int                                     brightness;
-       char                            name[sizeof("neuron:green:uled-x1")];
-       spinlock_t                      lock;
-};
-
-struct mutex neuronspi_master_mutex;
-
-struct neuronspi_file_data
-{
-       struct spi_device** spi_device;
-       struct mutex            lock;
-       u8                                      *send_buf;
-       u8                                      *recv_buf;
-       uint32_t                        message_len;
-};
-
-struct neuronspi_direct_acc
-{
-       void __iomem            *vaddr;
-       u32                                     size;
-};
-
-static struct neuronspi_char_driver neuronspi_cdrv =
-{
-       .dev = NULL
-};
-
 /*************
  * Functions *
  *************/
 
-static int neuronspi_open (struct inode *, struct file *);
-static int neuronspi_release (struct inode *, struct file *);
-static ssize_t neuronspi_read (struct file *, char *, size_t, loff_t *);
-static ssize_t neuronspi_write (struct file *, const char *, size_t, loff_t *);
-static int32_t char_register_driver(void);
-static int32_t char_unregister_driver(void);
-
-static int neuronspi_create_reg_starts(struct neuronspi_board_regstart_table *out_table, struct neuronspi_board_combination *board);
-static int32_t neuronspi_find_reg_start(struct neuronspi_board_combination *board, uint16_t regfun);
-static int32_t neuronspi_find_model_id(uint32_t probe_count);
-
-int neuronspi_iio_stm_ai_read_raw(struct iio_dev *iio_dev, struct iio_chan_spec const *ch, int *val, int *val2, long mask);
-int neuronspi_iio_stm_ao_read_raw(struct iio_dev *iio_dev, struct iio_chan_spec const *ch, int *val, int *val2, long mask);
-int neuronspi_iio_stm_ao_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int val, int val2, long mask);
-int neuronspi_iio_sec_ai_read_raw(struct iio_dev *iio_dev, struct iio_chan_spec const *ch, int *val, int *val2, long mask);
-int neuronspi_iio_sec_ao_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int val, int val2, long mask);
+int neuronspi_open (struct inode *, struct file *);
+int neuronspi_release (struct inode *, struct file *);
+ssize_t neuronspi_read (struct file *, char *, size_t, loff_t *);
+ssize_t neuronspi_write (struct file *, const char *, size_t, loff_t *);
+int32_t char_register_driver(void);
+int32_t char_unregister_driver(void);
 
-static irqreturn_t neuronspi_spi_irq(int32_t irq, void *dev_id);
+irqreturn_t neuronspi_spi_irq(int32_t irq, void *dev_id);
 static int32_t neuronspi_spi_probe(struct spi_device *spi);
 static int32_t neuronspi_spi_remove(struct spi_device *spi);
 void neuronspi_spi_send_message(struct spi_device *spi_dev, u8 *send_buf, u8 *recv_buf, int32_t len, int32_t freq, int32_t delay, int32_t send_header);
-static uint16_t neuronspi_spi_crc(u8* inputstring, int32_t length, uint16_t initval);
-static int32_t neuronspi_spi_uart_write(struct spi_device *spi, u8 *send_buf, u8 length, u8 uart_index);
+//uint16_t neuronspi_spi_crc(u8* inputstring, int32_t length, uint16_t initval);
+int32_t neuronspi_spi_uart_write(struct spi_device *spi, u8 *send_buf, u8 length, u8 uart_index);
 void neuronspi_spi_uart_read(struct spi_device* spi_dev, u8 *send_buf, u8 *recv_buf, int32_t len, u8 uart_index);
 void neuronspi_spi_set_irqs(struct spi_device* spi_dev, uint16_t to);
 void neuronspi_spi_led_set_brightness(struct spi_device* spi_dev, enum led_brightness brightness, int id);
@@ -2158,131 +223,6 @@ int neuronspi_spi_gpio_do_set(struct spi_device* spi_dev, uint32_t id, int value
 int neuronspi_spi_gpio_ro_set(struct spi_device* spi_dev, uint32_t id, int value);
 int neuronspi_spi_gpio_di_get(struct spi_device* spi_dev, uint32_t id);
 
-static void neuronspi_uart_start_tx(struct uart_port *port);
-static void neuronspi_uart_stop_tx(struct uart_port *port);
-static void neuronspi_uart_stop_rx(struct uart_port *port);
-static void neuronspi_uart_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old);
-static uint32_t neuronspi_uart_tx_empty(struct uart_port *port);
-static void neuronspi_uart_break_ctl(struct uart_port *port, int break_state);
-static void neuronspi_uart_shutdown(struct uart_port *port);
-static int32_t neuronspi_uart_startup(struct uart_port *port);
-static int32_t neuronspi_uart_request_port(struct uart_port *port);
-static int32_t neuronspi_uart_alloc_line(void);
-static void neuronspi_uart_set_mctrl(struct uart_port *port, uint32_t mctrl);
-int    neuronspi_uart_ioctl (struct uart_port *port, unsigned int ioctl_code, unsigned long ioctl_arg);
-static void neuronspi_uart_set_ldisc(struct uart_port *port, struct ktermios *kterm);
-static uint32_t neuronspi_uart_get_mctrl(struct uart_port *port);
-static const char *neuronspi_uart_type(struct uart_port *port);
-static void neuronspi_uart_null_void(struct uart_port *port);
-static void neuronspi_uart_config_port(struct uart_port *port, int flags);
-static int32_t neuronspi_uart_verify_port(struct uart_port *port, struct serial_struct *s);
-static void neuronspi_uart_pm(struct uart_port *port, uint32_t state,  uint32_t oldstate);
-static int32_t neuronspi_uart_poll(void *data);
-static int32_t neuronspi_uart_probe(struct spi_device* dev, u8 device_index);
-static int32_t neuronspi_uart_remove(struct neuronspi_uart_data *u_data);
-static void neuronspi_uart_power(struct uart_port *port, int32_t on);
-static int32_t neuronspi_uart_config_rs485(struct uart_port *port, struct serial_rs485 *rs485);
-void neuronspi_spi_uart_set_cflag(struct spi_device* spi_dev, u8 port, uint32_t to);
-uint32_t neuronspi_spi_uart_get_cflag(struct spi_device* spi_dev, u8 port);
-
-static void neuronspi_uart_fifo_write(struct neuronspi_port *port, u8 to_send);
-static void neuronspi_uart_fifo_read(struct uart_port *port, uint32_t rxlen);
-
-static void neuronspi_uart_rx_proc(struct kthread_work *ws);
-static void neuronspi_uart_tx_proc(struct kthread_work *ws);
-static void neuronspi_uart_ist(struct kthread_work *ws);
-static void neuronspi_uart_handle_tx(struct neuronspi_port *port);
-static void neuronspi_uart_handle_rx(struct neuronspi_port *port, uint32_t rxlen, uint32_t iir);
-static void neuronspi_uart_handle_irq(struct neuronspi_uart_data *uart_data, int32_t portno);
-
-int neuronspi_gpio_di_direction_input(struct gpio_chip *chip, unsigned offset);
-int neuronspi_gpio_di_direction_output(struct gpio_chip *chip, unsigned offset, int value);
-int    neuronspi_gpio_di_get(struct gpio_chip *chip, unsigned offset);
-int neuronspi_gpio_do_direction_input(struct gpio_chip *chip, unsigned offset);
-int neuronspi_gpio_do_direction_output(struct gpio_chip *chip, unsigned offset, int value);
-void neuronspi_gpio_do_set(struct gpio_chip *chip, unsigned offset, int value);
-int neuronspi_gpio_ro_direction_input(struct gpio_chip *chip, unsigned offset);
-int neuronspi_gpio_ro_direction_output(struct gpio_chip *chip, unsigned offset, int value);
-void neuronspi_gpio_ro_set(struct gpio_chip *chip, unsigned offset, int value);
-
-static void neuronspi_led_set_brightness(struct led_classdev *ldev, enum led_brightness brightness);
-
-static ssize_t neuronspi_iio_show_primary_ai_mode(struct device *dev, struct device_attribute *attr, char *buf);
-static ssize_t neuronspi_iio_store_primary_ai_mode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
-static ssize_t neuronspi_iio_show_primary_ao_mode(struct device *dev, struct device_attribute *attr, char *buf);
-static ssize_t neuronspi_iio_store_primary_ao_mode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
-static ssize_t neuronspi_iio_show_secondary_ai_mode(struct device *dev, struct device_attribute *attr, char *buf);
-static ssize_t neuronspi_iio_store_secondary_ai_mode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
-static ssize_t neuronspi_iio_show_secondary_ao_mode(struct device *dev, struct device_attribute *attr, char *buf);
-static ssize_t neuronspi_iio_store_secondary_ao_mode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
-
-static ssize_t neuronspi_show_model(struct device *dev, struct device_attribute *attr, char *buf);
-static ssize_t neuronspi_show_eeprom(struct device *dev, struct device_attribute *attr, char *buf);
-static ssize_t neuronspi_show_regmap(struct device *dev, struct device_attribute *attr, char *buf);
-static ssize_t neuronspi_store_regmap(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
-static ssize_t neuronspi_spi_show_serial(struct device *dev, struct device_attribute *attr, char *buf);
-static ssize_t neuronspi_spi_show_board(struct device *dev, struct device_attribute *attr, char *buf);
-static ssize_t neuronspi_spi_show_lboard_id(struct device *dev, struct device_attribute *attr, char *buf);
-static ssize_t neuronspi_spi_show_uboard_id(struct device *dev, struct device_attribute *attr, char *buf);
-static ssize_t neuronspi_spi_show_hw_version(struct device *dev, struct device_attribute *attr, char *buf);
-static ssize_t neuronspi_spi_show_hw_flash_version(struct device *dev, struct device_attribute *attr, char *buf);
-static ssize_t neuronspi_spi_show_fw_version(struct device *dev, struct device_attribute *attr, char *buf);
-static ssize_t neuronspi_spi_show_uart_queue_length(struct device *dev, struct device_attribute *attr, char *buf);
-static ssize_t neuronspi_spi_show_uart_config(struct device *dev, struct device_attribute *attr, char *buf);
-static ssize_t neuronspi_spi_store_uart_config(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
-static ssize_t neuronspi_spi_show_watchdog_status(struct device *dev, struct device_attribute *attr, char *buf);
-static ssize_t neuronspi_spi_store_watchdog_status(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
-static ssize_t neuronspi_spi_show_watchdog_timeout(struct device *dev, struct device_attribute *attr, char *buf);
-static ssize_t neuronspi_spi_store_watchdog_timeout(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
-static ssize_t neuronspi_spi_gpio_show_pwm_freq(struct device *dev, struct device_attribute *attr, char *buf);
-static ssize_t neuronspi_spi_gpio_store_pwm_freq(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
-static ssize_t neuronspi_spi_gpio_di_show_counter(struct device *dev, struct device_attribute *attr, char *buf);
-static ssize_t neuronspi_spi_gpio_di_store_counter(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
-static ssize_t neuronspi_spi_gpio_di_show_debounce(struct device *dev, struct device_attribute *attr, char *buf);
-static ssize_t neuronspi_spi_gpio_di_store_debounce(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
-static ssize_t neuronspi_spi_gpio_show_pwm_cycle(struct device *dev, struct device_attribute *attr, char *buf);
-static ssize_t neuronspi_spi_gpio_store_pwm_cycle(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
-static ssize_t neuronspi_spi_gpio_show_pwm_presc(struct device *dev, struct device_attribute *attr, char *buf);
-static ssize_t neuronspi_spi_gpio_store_pwm_presc(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
-static ssize_t neuronspi_spi_gpio_store_ds_enable(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
-static ssize_t neuronspi_spi_gpio_store_ds_toggle(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
-static ssize_t neuronspi_spi_gpio_store_ds_polarity(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
-static ssize_t neuronspi_spi_gpio_show_ds_enable(struct device *dev, struct device_attribute *attr, char *buf);
-static ssize_t neuronspi_spi_gpio_show_ds_toggle(struct device *dev, struct device_attribute *attr, char *buf);
-static ssize_t neuronspi_spi_gpio_show_ds_polarity(struct device *dev, struct device_attribute *attr, char *buf);
-static ssize_t neuronspi_spi_gpio_show_do_prefix(struct device *dev, struct device_attribute *attr, char *buf);
-static ssize_t neuronspi_spi_gpio_show_do_base(struct device *dev, struct device_attribute *attr, char *buf);
-static ssize_t neuronspi_spi_gpio_show_do_count(struct device *dev, struct device_attribute *attr, char *buf);
-static ssize_t neuronspi_spi_gpio_show_di_prefix(struct device *dev, struct device_attribute *attr, char *buf);
-static ssize_t neuronspi_spi_gpio_show_di_base(struct device *dev, struct device_attribute *attr, char *buf);
-static ssize_t neuronspi_spi_gpio_show_di_count(struct device *dev, struct device_attribute *attr, char *buf);
-static ssize_t neuronspi_spi_gpio_show_ro_prefix(struct device *dev, struct device_attribute *attr, char *buf);
-static ssize_t neuronspi_spi_gpio_show_ro_base(struct device *dev, struct device_attribute *attr, char *buf);
-static ssize_t neuronspi_spi_gpio_show_ro_count(struct device *dev, struct device_attribute *attr, char *buf);
-
-static ssize_t neuronspi_spi_gpio_di_show_value(struct device *dev, struct device_attribute *attr, char *buf);
-static ssize_t neuronspi_spi_gpio_do_show_value(struct device *dev, struct device_attribute *attr, char *buf);
-static ssize_t neuronspi_spi_gpio_do_store_value(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
-static ssize_t neuronspi_spi_gpio_ro_show_value(struct device *dev, struct device_attribute *attr, char *buf);
-static ssize_t neuronspi_spi_gpio_ro_store_value(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
-
-int neuronspi_regmap_hw_gather_write(void *context, const void *reg, size_t reg_size, const void *val, size_t val_size);
-int neuronspi_regmap_hw_read(void *context, const void *reg_buf, size_t reg_size, void *val_buf, size_t val_size);
-int neuronspi_regmap_hw_reg_read(void *context, unsigned int reg, unsigned int *val);
-int neuronspi_regmap_hw_reg_write(void *context, unsigned int reg, unsigned int val);
-int neuronspi_regmap_hw_write(void *context, const void *data, size_t count);
-
-static void neuronspi_regmap_invalidate_device(struct regmap *reg_map, struct neuronspi_board_combination *device_def, uint32_t period_counter);
-static int32_t neuronspi_regmap_invalidate(void *data);
-
-static struct spinlock* neuronspi_spi_w_spinlock;
-static u8 neuronspi_spi_w_flag = 1;
-static u8 neuronspi_probe_count = 0;
-static int neuronspi_model_id = -1;
-static spinlock_t neuronspi_probe_spinlock;
-static struct spi_device* neuronspi_s_dev[NEURONSPI_MAX_DEVS];
-static struct task_struct *neuronspi_invalidate_thread;
-
 int neuronspi_spi_gpio_di_get(struct spi_device* spi_dev, uint32_t id);
 
 /***********************
@@ -2310,27 +250,6 @@ static struct file_operations file_ops =
        .owner                          = THIS_MODULE
 };
 
-static const struct uart_ops neuronspi_uart_ops =
-{
-       .tx_empty                       = neuronspi_uart_tx_empty,
-       .set_mctrl                      = neuronspi_uart_set_mctrl,
-       .get_mctrl                      = neuronspi_uart_get_mctrl,
-       .stop_tx                        = neuronspi_uart_stop_tx,
-       .start_tx                       = neuronspi_uart_start_tx,
-       .stop_rx                        = neuronspi_uart_stop_rx,
-       .break_ctl                      = neuronspi_uart_break_ctl,
-       .startup                        = neuronspi_uart_startup,
-       .shutdown                       = neuronspi_uart_shutdown,
-       .set_termios            = neuronspi_uart_set_termios,
-       .set_ldisc                      = neuronspi_uart_set_ldisc,
-       .type                           = neuronspi_uart_type,
-       .request_port           = neuronspi_uart_request_port,
-       .release_port           = neuronspi_uart_null_void,
-       .config_port            = neuronspi_uart_config_port,
-       .verify_port            = neuronspi_uart_verify_port,
-       .pm                                     = neuronspi_uart_pm,
-       .ioctl                          = neuronspi_uart_ioctl,
-};
 
 static const struct regmap_bus neuronspi_regmap_bus =
 {
@@ -2434,180 +353,6 @@ static const struct iio_chan_spec neuronspi_sec_ao_chan_spec[] = {
        }
 };
 
-static DEVICE_ATTR(model_name, 0440, neuronspi_show_model, NULL);
-static DEVICE_ATTR(sys_eeprom_name, 0440, neuronspi_show_eeprom, NULL);
-static DEVICE_ATTR(register_read, 0660, neuronspi_show_regmap, neuronspi_store_regmap);
-static DEVICE_ATTR(sys_board_serial, 0440, neuronspi_spi_show_serial, NULL);
-static DEVICE_ATTR(sys_board_name, 0440, neuronspi_spi_show_board, NULL);
-static DEVICE_ATTR(sys_primary_major_id, 0440, neuronspi_spi_show_lboard_id, NULL);
-static DEVICE_ATTR(sys_secondary_major_id, 0440, neuronspi_spi_show_uboard_id, NULL);
-static DEVICE_ATTR(sys_primary_minor_id, 0440, neuronspi_spi_show_hw_version, NULL);
-static DEVICE_ATTR(sys_secondary_minor_id, 0440, neuronspi_spi_show_hw_flash_version, NULL);
-static DEVICE_ATTR(firmware_version, 0440, neuronspi_spi_show_fw_version, NULL);
-static DEVICE_ATTR(watchdog_status, 0660, neuronspi_spi_show_watchdog_status, neuronspi_spi_store_watchdog_status);
-static DEVICE_ATTR(watchdog_timeout, 0660, neuronspi_spi_show_watchdog_timeout, neuronspi_spi_store_watchdog_timeout);
-static DEVICE_ATTR(sys_gpio_do_count, 0440, neuronspi_spi_gpio_show_do_count, NULL);
-static DEVICE_ATTR(sys_gpio_do_prefix, 0440, neuronspi_spi_gpio_show_do_prefix, NULL);
-static DEVICE_ATTR(sys_gpio_do_base, 0440, neuronspi_spi_gpio_show_do_base, NULL);
-static DEVICE_ATTR(sys_gpio_di_count, 0440, neuronspi_spi_gpio_show_di_count, NULL);
-static DEVICE_ATTR(sys_gpio_di_prefix, 0440, neuronspi_spi_gpio_show_di_prefix, NULL);
-static DEVICE_ATTR(ro_value, 0660, neuronspi_spi_gpio_ro_show_value, neuronspi_spi_gpio_ro_store_value);
-static DEVICE_ATTR(do_value, 0660, neuronspi_spi_gpio_do_show_value, neuronspi_spi_gpio_do_store_value);
-static DEVICE_ATTR(counter, 0660, neuronspi_spi_gpio_di_show_counter, neuronspi_spi_gpio_di_store_counter);
-static DEVICE_ATTR(debounce, 0660, neuronspi_spi_gpio_di_show_debounce, neuronspi_spi_gpio_di_store_debounce);
-static DEVICE_ATTR(di_value, 0440, neuronspi_spi_gpio_di_show_value, NULL);
-static DEVICE_ATTR(direct_switch_enable, 0660, neuronspi_spi_gpio_show_ds_enable, neuronspi_spi_gpio_store_ds_enable);
-static DEVICE_ATTR(direct_switch_toggle, 0660, neuronspi_spi_gpio_show_ds_toggle, neuronspi_spi_gpio_store_ds_toggle);
-static DEVICE_ATTR(direct_switch_polarity, 0660, neuronspi_spi_gpio_show_ds_polarity, neuronspi_spi_gpio_store_ds_polarity);
-static DEVICE_ATTR(pwm_frequency_cycle, 0660, neuronspi_spi_gpio_show_pwm_freq, neuronspi_spi_gpio_store_pwm_freq);
-static DEVICE_ATTR(pwm_prescale, 0660, neuronspi_spi_gpio_show_pwm_presc, neuronspi_spi_gpio_store_pwm_presc);
-static DEVICE_ATTR(pwm_duty_cycle, 0660, neuronspi_spi_gpio_show_pwm_cycle, neuronspi_spi_gpio_store_pwm_cycle);
-static DEVICE_ATTR(uart_queue_length, 0440, neuronspi_spi_show_uart_queue_length, NULL);
-static DEVICE_ATTR(uart_config, 0660, neuronspi_spi_show_uart_config, neuronspi_spi_store_uart_config);
-static DEVICE_ATTR(sys_gpio_di_base, 0440, neuronspi_spi_gpio_show_di_base, NULL);
-static DEVICE_ATTR(sys_gpio_ro_count, 0440, neuronspi_spi_gpio_show_ro_count, NULL);
-static DEVICE_ATTR(sys_gpio_ro_prefix, 0440, neuronspi_spi_gpio_show_ro_prefix, NULL);
-static DEVICE_ATTR(sys_gpio_ro_base, 0440, neuronspi_spi_gpio_show_ro_base, NULL);
-static DEVICE_ATTR(mode_ai_type_a, 0660, neuronspi_iio_show_primary_ai_mode, neuronspi_iio_store_primary_ai_mode);
-static DEVICE_ATTR(mode_ao_type_a, 0660, neuronspi_iio_show_primary_ao_mode, neuronspi_iio_store_primary_ao_mode);
-static DEVICE_ATTR(mode_ai_type_b, 0660, neuronspi_iio_show_secondary_ai_mode, neuronspi_iio_store_secondary_ai_mode);
-static DEVICE_ATTR(mode_ao_type_b, 0660, neuronspi_iio_show_secondary_ao_mode, neuronspi_iio_store_secondary_ao_mode);
-
-static struct attribute *neuron_plc_attrs[] = {
-               &dev_attr_model_name.attr,
-               &dev_attr_sys_eeprom_name.attr,
-               NULL,
-};
-
-static struct attribute *neuron_board_attrs[] = {
-               &dev_attr_sys_board_name.attr,
-               &dev_attr_sys_primary_major_id.attr,
-               &dev_attr_sys_secondary_major_id.attr,
-               &dev_attr_sys_primary_minor_id.attr,
-               &dev_attr_sys_secondary_minor_id.attr,
-               &dev_attr_firmware_version.attr,
-               &dev_attr_watchdog_status.attr,
-               &dev_attr_watchdog_timeout.attr,
-               &dev_attr_sys_board_serial.attr,
-               &dev_attr_uart_queue_length.attr,
-               &dev_attr_uart_config.attr,
-               &dev_attr_register_read.attr,
-               NULL,
-};
-
-static struct attribute *neuron_gpio_di_attrs[] = {
-               &dev_attr_sys_gpio_di_count.attr,
-               &dev_attr_sys_gpio_di_prefix.attr,
-               &dev_attr_sys_gpio_di_base.attr,
-               &dev_attr_direct_switch_enable.attr,
-               &dev_attr_direct_switch_toggle.attr,
-               &dev_attr_direct_switch_polarity.attr,
-               &dev_attr_di_value.attr,
-               &dev_attr_counter.attr,
-               &dev_attr_debounce.attr,
-               NULL,
-};
-
-static struct attribute *neuron_gpio_do_attrs[] = {
-               &dev_attr_sys_gpio_do_count.attr,
-               &dev_attr_sys_gpio_do_prefix.attr,
-               &dev_attr_sys_gpio_do_base.attr,
-               &dev_attr_pwm_frequency_cycle.attr,
-               &dev_attr_pwm_prescale.attr,
-               &dev_attr_pwm_duty_cycle.attr,
-               &dev_attr_do_value.attr,
-               NULL,
-};
-
-static struct attribute *neuron_gpio_ro_attrs[] = {
-               &dev_attr_sys_gpio_ro_count.attr,
-               &dev_attr_sys_gpio_ro_prefix.attr,
-               &dev_attr_sys_gpio_ro_base.attr,
-               &dev_attr_ro_value.attr,
-               NULL,
-};
-
-static struct attribute *neuron_stm_ai_attrs[] = {
-               &dev_attr_mode_ai_type_a.attr,
-               NULL,
-};
-
-static struct attribute *neuron_stm_ao_attrs[] = {
-               &dev_attr_mode_ao_type_a.attr,
-               NULL,
-};
-
-static struct attribute *neuron_sec_ai_attrs[] = {
-               &dev_attr_mode_ai_type_b.attr,
-               NULL,
-};
-
-static struct attribute *neuron_sec_ao_attrs[] = {
-               &dev_attr_mode_ao_type_b.attr,
-               NULL,
-};
-
-static struct attribute_group neuron_plc_attr_group = {
-       .attrs = neuron_plc_attrs,
-};
-
-static struct attribute_group neuron_board_attr_group = {
-       .attrs = neuron_board_attrs,
-};
-
-static struct attribute_group neuron_gpio_di_attr_group = {
-       .attrs = neuron_gpio_di_attrs,
-};
-
-static struct attribute_group neuron_gpio_do_attr_group = {
-       .attrs = neuron_gpio_do_attrs,
-};
-
-static struct attribute_group neuron_gpio_ro_attr_group = {
-       .attrs = neuron_gpio_ro_attrs,
-};
-
-static struct attribute_group neuron_stm_ai_group = {
-       .attrs = neuron_stm_ai_attrs,
-};
-
-static struct attribute_group neuron_stm_ao_group = {
-       .attrs = neuron_stm_ao_attrs,
-};
-
-static struct attribute_group neuron_sec_ai_group = {
-       .attrs = neuron_sec_ai_attrs,
-};
-
-static struct attribute_group neuron_sec_ao_group = {
-       .attrs = neuron_sec_ao_attrs,
-};
-
-static const struct attribute_group *neuron_plc_attr_groups[] = {
-       &neuron_plc_attr_group,
-       NULL,
-};
-
-static const struct attribute_group *neuron_board_attr_groups[] = {
-       &neuron_board_attr_group,
-       NULL,
-};
-
-static const struct attribute_group *neuron_gpio_di_attr_groups[] = {
-       &neuron_gpio_di_attr_group,
-       NULL,
-};
-
-static const struct attribute_group *neuron_gpio_do_attr_groups[] = {
-       &neuron_gpio_do_attr_group,
-       NULL,
-};
-
-static const struct attribute_group *neuron_gpio_ro_attr_groups[] = {
-       &neuron_gpio_ro_attr_group,
-       NULL,
-};
-
 static struct platform_device *neuron_plc_dev;
 
 static const struct iio_info neuronspi_stm_ai_info = {
@@ -2646,7 +391,7 @@ static const struct iio_info neuronspi_sec_ao_info = {
  * Inline Functions    *
  ***********************/
 
-__always_inline uint16_t neuronspi_spi_crc(u8* inputstring, int32_t length, uint16_t initval)
+static __always_inline uint16_t neuronspi_spi_crc(u8* inputstring, int32_t length, uint16_t initval)
 {
     int32_t i;
     uint16_t result = initval;
@@ -2656,7 +401,7 @@ __always_inline uint16_t neuronspi_spi_crc(u8* inputstring, int32_t length, uint
     return result;
 }
 
-__always_inline size_t neuronspi_spi_compose_single_coil_write(uint16_t start, uint8_t **buf_inp, uint8_t **buf_outp, uint8_t data)
+static __always_inline size_t neuronspi_spi_compose_single_coil_write(uint16_t start, uint8_t **buf_inp, uint8_t **buf_outp, uint8_t data)
 {
        uint16_t crc1;
        *buf_outp = kzalloc(6, GFP_KERNEL);
@@ -2670,7 +415,7 @@ __always_inline size_t neuronspi_spi_compose_single_coil_write(uint16_t start, u
        return 6;
 }
 
-__always_inline size_t neuronspi_spi_compose_single_coil_read(uint16_t start, uint8_t **buf_inp, uint8_t **buf_outp)
+static __always_inline size_t neuronspi_spi_compose_single_coil_read(uint16_t start, uint8_t **buf_inp, uint8_t **buf_outp)
 {
        uint16_t crc1, crc2;
        *buf_outp = kzalloc(14, GFP_KERNEL);
@@ -2687,7 +432,7 @@ __always_inline size_t neuronspi_spi_compose_single_coil_read(uint16_t start, ui
        return 14;
 }
 
-__always_inline size_t neuronspi_spi_compose_multiple_coil_write(uint8_t number, uint16_t start, uint8_t **buf_inp, uint8_t **buf_outp, uint8_t *data)
+static __always_inline size_t neuronspi_spi_compose_multiple_coil_write(uint8_t number, uint16_t start, uint8_t **buf_inp, uint8_t **buf_outp, uint8_t *data)
 {
        uint16_t crc1, crc2;
        *buf_outp = kzalloc(12 + NEURONSPI_GET_COIL_READ_PHASE2_BYTE_LENGTH(number), GFP_KERNEL);
@@ -2706,7 +451,7 @@ __always_inline size_t neuronspi_spi_compose_multiple_coil_write(uint8_t number,
        return 12 + NEURONSPI_GET_COIL_READ_PHASE2_BYTE_LENGTH(number);
 }
 
-__always_inline size_t neuronspi_spi_compose_multiple_coil_read(uint8_t number, uint16_t start, uint8_t **buf_inp, uint8_t **buf_outp)
+static __always_inline size_t neuronspi_spi_compose_multiple_coil_read(uint8_t number, uint16_t start, uint8_t **buf_inp, uint8_t **buf_outp)
 {
        uint16_t crc1, crc2;
        *buf_outp = kzalloc(12 + NEURONSPI_GET_COIL_READ_PHASE2_BYTE_LENGTH(number), GFP_KERNEL);
@@ -2723,7 +468,7 @@ __always_inline size_t neuronspi_spi_compose_multiple_coil_read(uint8_t number,
        return 12 + NEURONSPI_GET_COIL_READ_PHASE2_BYTE_LENGTH(number);
 }
 
-__always_inline size_t neuronspi_spi_compose_single_register_write(uint16_t start, uint8_t **buf_inp, uint8_t **buf_outp, uint16_t data)
+static __always_inline size_t neuronspi_spi_compose_single_register_write(uint16_t start, uint8_t **buf_inp, uint8_t **buf_outp, uint16_t data)
 {
        uint16_t crc1, crc2;
        *buf_outp = kzalloc(14, GFP_KERNEL);
@@ -2743,7 +488,7 @@ __always_inline size_t neuronspi_spi_compose_single_register_write(uint16_t star
        return 14;
 }
 
-__always_inline size_t neuronspi_spi_compose_single_register_read(uint16_t start, uint8_t **buf_inp, uint8_t **buf_outp)
+static __always_inline size_t neuronspi_spi_compose_single_register_read(uint16_t start, uint8_t **buf_inp, uint8_t **buf_outp)
 {
        uint16_t crc1, crc2;
        *buf_outp = kzalloc(14, GFP_KERNEL);
@@ -2761,7 +506,7 @@ __always_inline size_t neuronspi_spi_compose_single_register_read(uint16_t start
        return 14;
 }
 
-__always_inline size_t neuronspi_spi_compose_multiple_register_write(uint8_t number, uint16_t start, uint8_t **buf_inp, uint8_t **buf_outp, uint8_t *data)
+static __always_inline size_t neuronspi_spi_compose_multiple_register_write(uint8_t number, uint16_t start, uint8_t **buf_inp, uint8_t **buf_outp, uint8_t *data)
 {
        uint16_t crc1, crc2;
        *buf_outp = kzalloc(12 + (number * 2), GFP_KERNEL);
@@ -2780,7 +525,7 @@ __always_inline size_t neuronspi_spi_compose_multiple_register_write(uint8_t num
        return 12 + (number * 2);
 }
 
-__always_inline size_t neuronspi_spi_compose_multiple_register_read(uint8_t number, uint16_t start, uint8_t **buf_inp, uint8_t **buf_outp)
+static __always_inline size_t neuronspi_spi_compose_multiple_register_read(uint8_t number, uint16_t start, uint8_t **buf_inp, uint8_t **buf_outp)
 {
        uint16_t crc1, crc2;
        *buf_outp = kzalloc(12 + (number * 2), GFP_KERNEL);
@@ -2798,4 +543,4 @@ __always_inline size_t neuronspi_spi_compose_multiple_register_read(uint8_t numb
        return 12 + (number * 2);
 }
 
-#endif /* NEURONSPI_H_ */
+#endif /* MODULES_NEURON_SPI_SRC_UNIPI_SPI_H_ */
index b43a7f5ea0e459e3b0d40bb1b7fd1c41bd5ed33d..35ccafc267fcea7944e969abf2214b2cf81f3849 100644 (file)
  * (at your option) any later version.
  *
  */
+
+#include "unipi_sysfs.h"
+
+
+ssize_t neuronspi_show_model(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       ssize_t ret = 0;
+       if (neuronspi_model_id != -1) {
+               ret = scnprintf(buf, 255, "%s\n", NEURONSPI_MODELTABLE[neuronspi_model_id].model_name);
+       }
+       return ret;
+}
+
+ssize_t neuronspi_show_eeprom(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       ssize_t ret = 0;
+       if (neuronspi_model_id != -1) {
+               ret = scnprintf(buf, 255, "%s\n", NEURONSPI_MODELTABLE[neuronspi_model_id].eeprom_name);
+       }
+       return ret;
+}
+
+ssize_t neuronspi_spi_show_serial(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       ssize_t ret = 0;
+       u32 val[2] = {0, 0};
+       struct neuronspi_driver_data *n_spi;
+       struct platform_device *plat = to_platform_device(dev);
+       n_spi = platform_get_drvdata(plat);
+       if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) {
+               regmap_read(n_spi->reg_map, n_spi->regstart_table->sys_serial_num, val);
+               regmap_read(n_spi->reg_map, n_spi->regstart_table->sys_serial_num + 1, &(val[1]));
+               ret = scnprintf(buf, 255, "%d\n", val[0]);
+       }
+       return ret;
+}
+
+ssize_t neuronspi_spi_show_hw_version(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       ssize_t ret = 0;
+       u32 val = 0;
+       struct neuronspi_driver_data *n_spi;
+       struct platform_device *plat = to_platform_device(dev);
+       n_spi = platform_get_drvdata(plat);
+       if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) {
+               regmap_read(n_spi->reg_map, n_spi->regstart_table->sys_hw_ver, &val);
+               ret = scnprintf(buf, 255, "%x.%x\n", (val & 0xF0) >> 4, val & 0xF);
+       }
+       return ret;
+}
+
+ssize_t neuronspi_spi_show_hw_flash_version(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       ssize_t ret = 0;
+       u32 val = 0;
+       struct neuronspi_driver_data *n_spi;
+       struct platform_device *plat = to_platform_device(dev);
+       n_spi = platform_get_drvdata(plat);
+       if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) {
+               regmap_read(n_spi->reg_map, n_spi->regstart_table->sys_hw_flash_ver, &val);
+               ret = scnprintf(buf, 255, "%x.%x\n", (val & 0xF0) >> 4, val & 0xF);
+       }
+       return ret;
+}
+
+ssize_t neuronspi_spi_show_fw_version(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       ssize_t ret = 0;
+       u32 val = 0;
+       struct neuronspi_driver_data *n_spi;
+       struct platform_device *plat = to_platform_device(dev);
+       n_spi = platform_get_drvdata(plat);
+       if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) {
+               regmap_read(n_spi->reg_map, n_spi->regstart_table->sys_sw_ver, &val);
+               ret = scnprintf(buf, 255, "%x.%x%x\n", (val & 0xF00) >> 8, (val & 0xF0) >> 4, val & 0xF);
+       }
+       return ret;
+}
+
+ssize_t neuronspi_spi_show_uart_queue_length(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       ssize_t ret = 0;
+       u32 val = 0;
+       struct neuronspi_driver_data *n_spi;
+       struct platform_device *plat = to_platform_device(dev);
+       n_spi = platform_get_drvdata(plat);
+       if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map && n_spi->regstart_table->uart_queue_reg) {
+               regmap_read(n_spi->reg_map, n_spi->regstart_table->uart_queue_reg, &val);
+               ret = scnprintf(buf, 255, "%d\n", val);
+       }
+       return ret;
+}
+
+ssize_t neuronspi_spi_show_uart_config(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       ssize_t ret = 0;
+       u32 val = 0;
+       struct neuronspi_driver_data *n_spi;
+       struct platform_device *plat = to_platform_device(dev);
+       n_spi = platform_get_drvdata(plat);
+       if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map && n_spi->regstart_table->uart_conf_reg) {
+               regmap_read(n_spi->reg_map, n_spi->regstart_table->uart_conf_reg, &val);
+               ret = scnprintf(buf, 255, "%x\n", val);
+       }
+       return ret;
+}
+
+ssize_t neuronspi_spi_store_uart_config(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+       ssize_t err = 0;
+       unsigned int val = 0;
+       struct neuronspi_driver_data *n_spi;
+       struct platform_device *plat = to_platform_device(dev);
+       n_spi = platform_get_drvdata(plat);
+       err = kstrtouint(buf, 0, &val);
+       if (err < 0) goto err_end;
+       if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map && n_spi->regstart_table->uart_conf_reg) {
+               regmap_write(n_spi->reg_map, n_spi->regstart_table->uart_conf_reg, val);
+       }
+err_end:
+       return count;
+}
+
+ssize_t neuronspi_spi_show_watchdog_status(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       ssize_t ret = 0;
+       u32 val = 0;
+       struct neuronspi_driver_data *n_spi;
+       struct platform_device *plat = to_platform_device(dev);
+       n_spi = platform_get_drvdata(plat);
+       if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) {
+               regmap_read(n_spi->reg_map, n_spi->regstart_table->wd_val_reg, &val);
+               ret = scnprintf(buf, 255, "%x\n", val);
+       }
+       return ret;
+}
+
+ssize_t neuronspi_spi_store_watchdog_status(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+       ssize_t err = 0;
+       unsigned int val = 0;
+       struct neuronspi_driver_data *n_spi;
+       struct platform_device *plat = to_platform_device(dev);
+       n_spi = platform_get_drvdata(plat);
+       err = kstrtouint(buf, 0, &val);
+       if (err < 0) goto err_end;
+       if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) {
+               regmap_write(n_spi->reg_map, n_spi->regstart_table->wd_val_reg, val);
+       }
+err_end:
+       return count;
+}
+
+ssize_t neuronspi_spi_show_watchdog_timeout(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       ssize_t ret = 0;
+       u32 val = 0;
+       struct neuronspi_driver_data *n_spi;
+       struct platform_device *plat = to_platform_device(dev);
+       n_spi = platform_get_drvdata(plat);
+       if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) {
+               regmap_read(n_spi->reg_map, n_spi->regstart_table->wd_timeout_reg, &val);
+               ret = scnprintf(buf, 255, "%d\n", val);
+       }
+       return ret;
+}
+
+ssize_t neuronspi_spi_store_watchdog_timeout(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+       ssize_t err = 0;
+       unsigned int val = 0;
+       struct neuronspi_driver_data *n_spi;
+       struct platform_device *plat = to_platform_device(dev);
+       n_spi = platform_get_drvdata(plat);
+       err = kstrtouint(buf, 0, &val);
+       if (err < 0) goto err_end;
+       if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) {
+               regmap_write(n_spi->reg_map, n_spi->regstart_table->wd_timeout_reg, val);
+       }
+err_end:
+       return count;
+}
+
+ssize_t neuronspi_spi_gpio_show_pwm_presc(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       ssize_t ret = 0;
+       u32 val = 0;
+       struct neuronspi_do_driver *n_do;
+       struct neuronspi_driver_data *n_spi;
+       struct platform_device *plat = to_platform_device(dev);
+       n_do = platform_get_drvdata(plat);
+       n_spi = spi_get_drvdata(n_do->spi);
+       if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) {
+               regmap_read(n_spi->reg_map, n_spi->regstart_table->do_pwm_ps_reg, &val);
+               ret = scnprintf(buf, 255, "%d\n", val);
+       }
+       return ret;
+}
+
+ssize_t neuronspi_spi_gpio_store_pwm_presc(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+       ssize_t err = 0;
+       unsigned int val = 0;
+       struct neuronspi_do_driver *n_do;
+       struct neuronspi_driver_data *n_spi;
+       struct platform_device *plat = to_platform_device(dev);
+       n_do = platform_get_drvdata(plat);
+       n_spi = spi_get_drvdata(n_do->spi);
+       err = kstrtouint(buf, 0, &val);
+       if (err < 0) goto err_end;
+       if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) {
+               regmap_write(n_spi->reg_map, n_spi->regstart_table->do_pwm_ps_reg, val);
+       }
+err_end:
+       return count;
+}
+
+ssize_t neuronspi_spi_gpio_show_pwm_freq(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       ssize_t ret = 0;
+       u32 val = 0;
+       struct neuronspi_do_driver *n_do;
+       struct neuronspi_driver_data *n_spi;
+       struct platform_device *plat = to_platform_device(dev);
+       n_do = platform_get_drvdata(plat);
+       n_spi = spi_get_drvdata(n_do->spi);
+       if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) {
+               regmap_read(n_spi->reg_map, n_spi->regstart_table->do_pwm_c_reg, &val);
+               ret = scnprintf(buf, 255, "%d\n", val);
+       }
+       return ret;
+}
+
+ssize_t neuronspi_spi_gpio_store_pwm_freq(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+       ssize_t err = 0;
+       unsigned int val = 0;
+       struct neuronspi_do_driver *n_do;
+       struct neuronspi_driver_data *n_spi;
+       struct platform_device *plat = to_platform_device(dev);
+       n_do = platform_get_drvdata(plat);
+       n_spi = spi_get_drvdata(n_do->spi);
+       err = kstrtouint(buf, 0, &val);
+       if (err < 0) goto err_end;
+       if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) {
+               regmap_write(n_spi->reg_map, n_spi->regstart_table->do_pwm_c_reg, val);
+       }
+err_end:
+       return count;
+}
+
+ssize_t neuronspi_spi_gpio_show_pwm_cycle(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       ssize_t ret = 0;
+       u32 val = 0;
+       struct neuronspi_do_driver *n_do;
+       struct neuronspi_driver_data *n_spi;
+       struct platform_device *plat = to_platform_device(dev);
+       n_do = platform_get_drvdata(plat);
+       n_spi = spi_get_drvdata(n_do->spi);
+       if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) {
+               regmap_read(n_spi->reg_map, n_spi->regstart_table->do_pwm_reg + n_do->do_index, &val);
+               ret = scnprintf(buf, 255, "%d\n", val);
+       }
+       return ret;
+}
+
+ssize_t neuronspi_spi_gpio_store_pwm_cycle(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+       ssize_t err = 0;
+       unsigned int val = 0;
+       struct neuronspi_do_driver *n_do;
+       struct neuronspi_driver_data *n_spi;
+       struct platform_device *plat = to_platform_device(dev);
+       n_do = platform_get_drvdata(plat);
+       n_spi = spi_get_drvdata(n_do->spi);
+       err = kstrtouint(buf, 0, &val);
+       if (err < 0) goto err_end;
+       if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) {
+               regmap_write(n_spi->reg_map, n_spi->regstart_table->do_pwm_reg + n_do->do_index, val);
+       }
+err_end:
+       return count;
+}
+
+ssize_t neuronspi_spi_gpio_di_show_counter(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       ssize_t ret = 0;
+       u32 val = 0;
+       struct neuronspi_di_driver *n_di;
+       struct neuronspi_driver_data *n_spi;
+       struct platform_device *plat = to_platform_device(dev);
+       n_di = platform_get_drvdata(plat);
+       n_spi = spi_get_drvdata(n_di->spi);
+       if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) {
+               regmap_read(n_spi->reg_map, n_spi->regstart_table->di_counter_reg + (2 * n_di->di_index), &val);
+               ret = scnprintf(buf, 255, "%d\n", val);
+       }
+       return ret;
+}
+
+ssize_t neuronspi_spi_gpio_di_store_counter(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+       ssize_t err = 0;
+       unsigned int val = 0;
+       struct neuronspi_di_driver *n_di;
+       struct neuronspi_driver_data *n_spi;
+       struct platform_device *plat = to_platform_device(dev);
+       n_di = platform_get_drvdata(plat);
+       n_spi = spi_get_drvdata(n_di->spi);
+       err = kstrtouint(buf, 0, &val);
+       if (err < 0) goto err_end;
+       if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) {
+               regmap_write(n_spi->reg_map, n_spi->regstart_table->di_counter_reg + (2 * n_di->di_index), val);
+       }
+err_end:
+       return count;
+}
+
+ssize_t neuronspi_spi_gpio_di_show_debounce(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       ssize_t ret = 0;
+       u32 val = 0;
+       struct neuronspi_di_driver *n_di;
+       struct neuronspi_driver_data *n_spi;
+       struct platform_device *plat = to_platform_device(dev);
+       n_di = platform_get_drvdata(plat);
+       n_spi = spi_get_drvdata(n_di->spi);
+       if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map && n_spi->features && n_spi->features->di_count > n_di->di_index) {
+               regmap_read(n_spi->reg_map, n_spi->regstart_table->di_deboun_reg + n_di->di_index, &val);
+               ret = scnprintf(buf, 255, "%d\n", val);
+       }
+       return ret;
+}
+
+ssize_t neuronspi_spi_gpio_di_store_debounce(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+       ssize_t err = 0;
+       unsigned int val = 0;
+       struct neuronspi_di_driver *n_di;
+       struct neuronspi_driver_data *n_spi;
+       struct platform_device *plat = to_platform_device(dev);
+       n_di = platform_get_drvdata(plat);
+       n_spi = spi_get_drvdata(n_di->spi);
+       err = kstrtouint(buf, 0, &val);
+       if (err < 0) goto err_end;
+       if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map && n_spi->features && n_spi->features->di_count > n_di->di_index) {
+               regmap_write(n_spi->reg_map, n_spi->regstart_table->di_deboun_reg + n_di->di_index, val);
+       }
+err_end:
+       return count;
+}
+
+ssize_t neuronspi_spi_gpio_di_show_value(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       ssize_t ret = 0;
+       int val;
+       struct neuronspi_di_driver *n_di;
+       struct neuronspi_driver_data *n_spi;
+       struct platform_device *plat = to_platform_device(dev);
+       n_di = platform_get_drvdata(plat);
+       n_spi = spi_get_drvdata(n_di->spi);
+       if (n_spi && n_spi->combination_id != -1 && n_spi->features && n_spi->features->di_count > n_di->di_index) {
+               regmap_read(n_spi->reg_map, n_spi->regstart_table->di_val_reg + (n_di->di_index / 16), &val);
+               val &= 0x1 << (n_di->di_index % 15);
+               val = val >> (n_di->di_index % 15);
+               ret = scnprintf(buf, 255, "%d\n", val);
+       }
+       return ret;
+}
+
+ssize_t neuronspi_spi_gpio_do_show_value(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       ssize_t ret = 0;
+       int val;
+       struct neuronspi_do_driver *n_do;
+       struct neuronspi_driver_data *n_spi;
+       struct platform_device *plat = to_platform_device(dev);
+       n_do = platform_get_drvdata(plat);
+       n_spi = spi_get_drvdata(n_do->spi);
+       if (n_spi && n_spi->combination_id != -1 && n_spi->features && n_spi->features->do_count > n_do->do_index) {
+               regmap_read(n_spi->reg_map, n_spi->regstart_table->do_val_reg + (n_do->do_index / 16), &val);
+               val &= 0x1 << (n_do->do_index % 15);
+               val = val >> (n_do->do_index % 15);
+               ret = scnprintf(buf, 255, "%d\n", val);
+       }
+       return ret;
+}
+
+ssize_t neuronspi_spi_gpio_do_store_value(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+       ssize_t err = 0;
+       int inp = 0;
+       unsigned int val;
+       struct neuronspi_do_driver *n_do;
+       struct neuronspi_driver_data *n_spi;
+       struct platform_device *plat = to_platform_device(dev);
+       n_do = platform_get_drvdata(plat);
+       n_spi = spi_get_drvdata(n_do->spi);
+       err = kstrtoint(buf, 0, &inp);
+       if (err < 0) goto err_end;
+       if (inp > 1 || inp < 0) {
+               goto err_end;
+       }
+       if (n_spi && n_spi->combination_id != -1 && n_spi->features && n_spi->features->do_count > n_do->do_index) {
+               regmap_read(n_spi->reg_map, n_spi->regstart_table->do_val_reg + (n_do->do_index / 16), &val);
+               val &= ~(0x1 << (n_do->do_index % 15));
+               val |= inp << (n_do->do_index % 15);
+               regmap_write(n_spi->reg_map, n_spi->regstart_table->do_val_reg + (n_do->do_index / 16), val);
+       }
+err_end:
+       return count;
+}
+
+ssize_t neuronspi_spi_gpio_ro_show_value(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       ssize_t ret = 0;
+       int val;
+       struct neuronspi_ro_driver *n_ro;
+       struct neuronspi_driver_data *n_spi;
+       struct platform_device *plat = to_platform_device(dev);
+       n_ro = platform_get_drvdata(plat);
+       n_spi = spi_get_drvdata(n_ro->spi);
+       if (n_spi && n_spi->combination_id != -1 && n_spi->features && n_spi->features->ro_count > n_ro->ro_index) {
+               regmap_read(n_spi->reg_map, n_spi->regstart_table->ro_val_reg + (n_ro->ro_index / 16), &val);
+               val &= 0x1 << (n_ro->ro_index % 15);
+               val = val >> (n_ro->ro_index % 15);
+               ret = scnprintf(buf, 255, "%d\n", val);
+       }
+       return ret;
+}
+
+ssize_t neuronspi_spi_gpio_ro_store_value(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+       ssize_t err = 0;
+       int inp = 0;
+       unsigned int val;
+       struct neuronspi_ro_driver *n_ro;
+       struct neuronspi_driver_data *n_spi;
+       struct platform_device *plat = to_platform_device(dev);
+       n_ro = platform_get_drvdata(plat);
+       n_spi = spi_get_drvdata(n_ro->spi);
+       err = kstrtoint(buf, 0, &inp);
+       if (err < 0) goto err_end;
+       if (inp > 1 || inp < 0) {
+               goto err_end;
+       }
+       if (n_spi && n_spi->combination_id != -1 && n_spi->features && n_spi->features->ro_count > n_ro->ro_index) {
+               regmap_read(n_spi->reg_map, n_spi->regstart_table->ro_val_reg + (n_ro->ro_index / 16), &val);
+               val &= ~(0x1 << (n_ro->ro_index % 15));
+               val |= inp << (n_ro->ro_index % 15);
+               regmap_write(n_spi->reg_map, n_spi->regstart_table->ro_val_reg + (n_ro->ro_index / 16), val);
+       }
+err_end:
+       return count;
+}
+
+
+ssize_t neuronspi_spi_gpio_show_ds_enable(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       ssize_t ret = 0;
+       int val;
+       struct neuronspi_di_driver *n_di;
+       struct neuronspi_driver_data *n_spi;
+       struct platform_device *plat = to_platform_device(dev);
+       n_di = platform_get_drvdata(plat);
+       n_spi = spi_get_drvdata(n_di->spi);
+       if (n_spi && n_spi->combination_id != -1 && n_spi->features && n_spi->features->ds_count) {
+               regmap_read(n_spi->reg_map, n_spi->regstart_table->di_direct_reg + (n_di->di_index / 16), &val);
+               val &= 0x1 << (n_di->di_index % 15);
+               val = val >> (n_di->di_index % 15);
+               ret = scnprintf(buf, 255, "%d\n", val);
+       }
+       return ret;
+}
+
+ssize_t neuronspi_spi_gpio_show_ds_toggle(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       ssize_t ret = 0;
+       int val;
+       struct neuronspi_di_driver *n_di;
+       struct neuronspi_driver_data *n_spi;
+       struct platform_device *plat = to_platform_device(dev);
+       n_di = platform_get_drvdata(plat);
+       n_spi = spi_get_drvdata(n_di->spi);
+       if (n_spi && n_spi->combination_id != -1 && n_spi->features && n_spi->features->ds_count) {
+               regmap_read(n_spi->reg_map, n_spi->regstart_table->di_toggle_reg + (n_di->di_index / 16), &val);
+               val &= 0x1 << (n_di->di_index % 15);
+               val = val >> (n_di->di_index % 15);
+               ret = scnprintf(buf, 255, "%d\n", val);
+       }
+       return ret;
+}
+
+ssize_t neuronspi_spi_gpio_show_ds_polarity(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       ssize_t ret = 0;
+       int val;
+       struct neuronspi_di_driver *n_di;
+       struct neuronspi_driver_data *n_spi;
+       struct platform_device *plat = to_platform_device(dev);
+       n_di = platform_get_drvdata(plat);
+       n_spi = spi_get_drvdata(n_di->spi);
+       if (n_spi && n_spi->combination_id != -1 && n_spi->features && n_spi->features->ds_count) {
+               regmap_read(n_spi->reg_map, n_spi->regstart_table->di_polar_reg + (n_di->di_index / 16), &val);
+               val &= 0x1 << (n_di->di_index % 15);
+               val = val >> (n_di->di_index % 15);
+               ret = scnprintf(buf, 255, "%d\n", val);
+       }
+       return ret;
+}
+
+ssize_t neuronspi_spi_gpio_store_ds_enable(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+       ssize_t err = 0;
+       int inp = 0;
+       unsigned int val;
+       struct neuronspi_di_driver *n_di;
+       struct neuronspi_driver_data *n_spi;
+       struct platform_device *plat = to_platform_device(dev);
+       n_di = platform_get_drvdata(plat);
+       n_spi = spi_get_drvdata(n_di->spi);
+       err = kstrtoint(buf, 0, &inp);
+       if (err < 0) goto err_end;
+       if (inp > 1 || inp < 0) {
+               goto err_end;
+       }
+       if (n_spi && n_spi->combination_id != -1 && n_spi->features && n_spi->features->ds_count) {
+               regmap_read(n_spi->reg_map, n_spi->regstart_table->di_direct_reg + (n_di->di_index / 16), &val);
+               val &= ~(0x1 << (n_di->di_index % 15));
+               val |= inp << (n_di->di_index % 15);
+               regmap_write(n_spi->reg_map, n_spi->regstart_table->di_direct_reg + (n_di->di_index / 16), val);
+       }
+err_end:
+       return count;
+}
+
+ssize_t neuronspi_spi_gpio_store_ds_toggle(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+       ssize_t err = 0;
+       int inp = 0;
+       unsigned int val;
+       struct neuronspi_di_driver *n_di;
+       struct neuronspi_driver_data *n_spi;
+       struct platform_device *plat = to_platform_device(dev);
+       n_di = platform_get_drvdata(plat);
+       n_spi = spi_get_drvdata(n_di->spi);
+       err = kstrtoint(buf, 0, &inp);
+       if (err < 0) goto err_end;
+       if (inp > 1 || inp < 0) {
+               goto err_end;
+       }
+       if (n_spi && n_spi->combination_id != -1 && n_spi->features && n_spi->features->ds_count) {
+               regmap_read(n_spi->reg_map, n_spi->regstart_table->di_toggle_reg + (n_di->di_index / 16), &val);
+               val &= ~(0x1 << (n_di->di_index % 15));
+               val |= inp << (n_di->di_index % 15);
+               regmap_write(n_spi->reg_map, n_spi->regstart_table->di_toggle_reg + (n_di->di_index / 16), val);
+       }
+err_end:
+       return count;
+}
+
+ssize_t neuronspi_spi_gpio_store_ds_polarity(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+       ssize_t err = 0;
+       int inp = 0;
+       unsigned int val;
+       struct neuronspi_di_driver *n_di;
+       struct neuronspi_driver_data *n_spi;
+       struct platform_device *plat = to_platform_device(dev);
+       n_di = platform_get_drvdata(plat);
+       n_spi = spi_get_drvdata(n_di->spi);
+       err = kstrtoint(buf, 0, &inp);
+       if (err < 0) goto err_end;
+       if (inp > 1 || inp < 0) {
+               goto err_end;
+       }
+       if (n_spi && n_spi->combination_id != -1 && n_spi->features && n_spi->features->ds_count) {
+               regmap_read(n_spi->reg_map, n_spi->regstart_table->di_polar_reg + (n_di->di_index / 16), &val);
+               val &= ~(0x1 << (n_di->di_index % 15));
+               val |= inp << (n_di->di_index % 15);
+               regmap_write(n_spi->reg_map, n_spi->regstart_table->di_polar_reg + (n_di->di_index / 16), val);
+       }
+err_end:
+       return count;
+}
+
+ssize_t neuronspi_show_regmap(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       ssize_t ret = 0;
+       u32 val = 0;
+       struct neuronspi_driver_data *n_spi;
+       struct platform_device *plat = to_platform_device(dev);
+       n_spi = platform_get_drvdata(plat);
+       if (n_spi && n_spi->reg_map) {
+               spin_lock(&n_spi->sysfs_regmap_lock);
+               regmap_read(n_spi->reg_map, n_spi->sysfs_regmap_target, &val);
+               ret = scnprintf(buf, 255, "%x\n", val);
+               spin_unlock(&n_spi->sysfs_regmap_lock);
+       }
+       return ret;
+}
+
+ssize_t neuronspi_store_regmap(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+       ssize_t err = 0;
+       unsigned int val = 0;
+       struct neuronspi_driver_data *n_spi;
+       struct platform_device *plat = to_platform_device(dev);
+       n_spi = platform_get_drvdata(plat);
+       err = kstrtouint(buf, 0, &val);
+       if (err < 0) goto err_end;
+       if (n_spi && n_spi->reg_map && val < 65536) {
+               spin_lock(&n_spi->sysfs_regmap_lock);
+               n_spi->sysfs_regmap_target = val;
+               spin_unlock(&n_spi->sysfs_regmap_lock);
+       }
+err_end:
+       return count;
+}
+
+ssize_t neuronspi_spi_show_board(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       ssize_t ret = 0;
+       struct neuronspi_driver_data *n_spi;
+       struct platform_device *plat = to_platform_device(dev);
+       n_spi = platform_get_drvdata(plat);
+       if (n_spi->combination_id != -1 && n_spi->combination_id < NEURONSPI_BOARDTABLE_LEN) {
+               ret = scnprintf(buf, 255, "%s\n", NEURONSPI_BOARDTABLE[n_spi->combination_id].definition->combination_name);
+       }
+       return ret;
+}
+
+ssize_t neuronspi_spi_show_lboard_id(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       ssize_t ret = 0;
+       struct neuronspi_driver_data *n_spi;
+       struct platform_device *plat = to_platform_device(dev);
+       n_spi = platform_get_drvdata(plat);
+       if (n_spi->combination_id != -1 && n_spi->combination_id < NEURONSPI_BOARDTABLE_LEN) {
+               ret = scnprintf(buf, 255, "%d\n", NEURONSPI_BOARDTABLE[n_spi->combination_id].definition->lower_board_id);
+       }
+       return ret;
+}
+
+ssize_t neuronspi_spi_show_uboard_id(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       ssize_t ret = 0;
+       struct neuronspi_driver_data *n_spi;
+       struct platform_device *plat = to_platform_device(dev);
+       n_spi = platform_get_drvdata(plat);
+       if (n_spi->combination_id != -1 && n_spi->combination_id < NEURONSPI_BOARDTABLE_LEN) {
+               ret = scnprintf(buf, 255, "%d\n", NEURONSPI_BOARDTABLE[n_spi->combination_id].definition->upper_board_id);
+       }
+       return ret;
+}
+
+ssize_t neuronspi_spi_gpio_show_do_prefix(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       ssize_t ret = 0;
+       struct neuronspi_do_driver *n_do;
+       struct neuronspi_driver_data *n_spi;
+       struct platform_device *plat = to_platform_device(dev);
+       n_do = platform_get_drvdata(plat);
+       n_spi = spi_get_drvdata(n_do->spi);
+       if (n_spi->features && n_spi->features->do_count > 0 && n_spi->do_driver) {
+               ret = scnprintf(buf, 255, "%s_%d\n", n_spi->do_driver[n_do->do_index]->gpio_c.label, n_spi->neuron_index + 1);
+       }
+       return ret;
+}
+
+ssize_t neuronspi_spi_gpio_show_di_prefix(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       ssize_t ret = 0;
+       struct neuronspi_di_driver *n_di;
+       struct neuronspi_driver_data *n_spi;
+       struct platform_device *plat = to_platform_device(dev);
+       n_di = platform_get_drvdata(plat);
+       n_spi = spi_get_drvdata(n_di->spi);
+       if (n_spi->features && n_spi->features->di_count > 0 && n_spi->di_driver) {
+               ret = scnprintf(buf, 255, "%s_%d\n", n_spi->di_driver[n_di->di_index]->gpio_c.label, n_spi->neuron_index + 1);
+       }
+       return ret;
+}
+
+ssize_t neuronspi_spi_gpio_show_ro_prefix(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       ssize_t ret = 0;
+       struct neuronspi_ro_driver *n_ro;
+       struct neuronspi_driver_data *n_spi;
+       struct platform_device *plat = to_platform_device(dev);
+       n_ro = platform_get_drvdata(plat);
+       n_spi = spi_get_drvdata(n_ro->spi);
+       if (n_spi->features && n_spi->features->ro_count > 0 && n_spi->ro_driver) {
+               ret = scnprintf(buf, 255, "%s_%d\n", n_spi->ro_driver[n_ro->ro_index]->gpio_c.label, n_spi->neuron_index + 1);
+       }
+       return ret;
+}
+
+ssize_t neuronspi_spi_gpio_show_do_base(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       ssize_t ret = 0;
+       struct neuronspi_do_driver *n_do;
+       struct neuronspi_driver_data *n_spi;
+       struct platform_device *plat = to_platform_device(dev);
+       n_do = platform_get_drvdata(plat);
+       n_spi = spi_get_drvdata(n_do->spi);
+       if (n_spi->features && n_spi->features->do_count > 0 && n_spi->do_driver) {
+               ret = scnprintf(buf, 255, "%d\n", n_spi->do_driver[n_do->do_index]->gpio_c.base);
+       }
+       return ret;
+}
+
+ssize_t neuronspi_spi_gpio_show_di_base(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       ssize_t ret = 0;
+       struct neuronspi_di_driver *n_di;
+       struct neuronspi_driver_data *n_spi;
+       struct platform_device *plat = to_platform_device(dev);
+       n_di = platform_get_drvdata(plat);
+       n_spi = spi_get_drvdata(n_di->spi);
+       if (n_spi->features && n_spi->features->di_count > 0 && n_spi->di_driver) {
+               ret = scnprintf(buf, 255, "%d\n", n_spi->di_driver[n_di->di_index]->gpio_c.base);
+       }
+       return ret;
+}
+
+ssize_t neuronspi_spi_gpio_show_ro_base(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       ssize_t ret = 0;
+       struct neuronspi_ro_driver *n_ro;
+       struct neuronspi_driver_data *n_spi;
+       struct platform_device *plat = to_platform_device(dev);
+       n_ro = platform_get_drvdata(plat);
+       n_spi = spi_get_drvdata(n_ro->spi);
+       if (n_spi->features && n_spi->features->ro_count > 0 && n_spi->ro_driver) {
+               ret = scnprintf(buf, 255, "%d\n", n_spi->ro_driver[n_ro->ro_index]->gpio_c.base);
+       }
+       return ret;
+}
+
+ssize_t neuronspi_spi_gpio_show_do_count(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       ssize_t ret = 0;
+       struct neuronspi_do_driver *n_do;
+       struct neuronspi_driver_data *n_spi;
+       struct platform_device *plat = to_platform_device(dev);
+       n_do = platform_get_drvdata(plat);
+       n_spi = spi_get_drvdata(n_do->spi);
+       if (n_spi->features && n_spi->features->do_count > 0 && n_spi->do_driver) {
+               ret = scnprintf(buf, 255, "%d\n", n_spi->do_driver[n_do->do_index]->gpio_c.ngpio);
+       }
+       return ret;
+}
+
+ssize_t neuronspi_spi_gpio_show_di_count(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       ssize_t ret = 0;
+       struct neuronspi_di_driver *n_di;
+       struct neuronspi_driver_data *n_spi;
+       struct platform_device *plat = to_platform_device(dev);
+       n_di = platform_get_drvdata(plat);
+       n_spi = spi_get_drvdata(n_di->spi);
+       if (n_spi->features && n_spi->features->di_count > 0 && n_spi->di_driver) {
+               ret = scnprintf(buf, 255, "%d\n", n_spi->di_driver[n_di->di_index]->gpio_c.ngpio);
+       }
+       return ret;
+}
+
+ssize_t neuronspi_spi_gpio_show_ro_count(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       ssize_t ret = 0;
+       struct neuronspi_ro_driver *n_ro;
+       struct neuronspi_driver_data *n_spi;
+       struct platform_device *plat = to_platform_device(dev);
+       n_ro = platform_get_drvdata(plat);
+       n_spi = spi_get_drvdata(n_ro->spi);
+       if (n_spi->features && n_spi->features->ro_count > 0 && n_spi->ro_driver) {
+               ret = scnprintf(buf, 255, "%d\n", n_spi->ro_driver[n_ro->ro_index]->gpio_c.ngpio);
+       }
+       return ret;
+}
+
+
+ssize_t neuronspi_iio_show_primary_ai_mode(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       int ret = 0;
+       unsigned int val = 0;
+       struct iio_dev *indio_dev = dev_get_drvdata(dev);
+       struct neuronspi_stm_ai_data *ai_data = iio_priv(indio_dev);
+       struct spi_device *spi = ai_data->parent;
+       struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi);
+       regmap_read(n_spi->reg_map, n_spi->regstart_table->stm_ai_mode_reg, &val);
+       ret = scnprintf(buf, 255, "%d\n", val);
+       return ret;
+}
+
+ssize_t neuronspi_iio_store_primary_ai_mode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+       ssize_t err = 0;
+       unsigned int val = 0;
+       struct iio_dev *indio_dev = dev_get_drvdata(dev);
+       struct neuronspi_stm_ai_data *ai_data = iio_priv(indio_dev);
+       struct spi_device *spi = ai_data->parent;
+       struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi);
+       err = kstrtouint(buf, 0, &val);
+       if (err < 0) goto err_end;
+       if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) {
+               regmap_write(n_spi->reg_map, n_spi->regstart_table->stm_ai_mode_reg, val);
+       }
+err_end:
+       return count;
+}
+
+ssize_t neuronspi_iio_show_primary_ao_mode(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       int ret = 0;
+       unsigned int val = 0;
+       struct iio_dev *indio_dev = dev_get_drvdata(dev);
+       struct neuronspi_stm_ao_data *ao_data = iio_priv(indio_dev);
+       struct spi_device *spi = ao_data->parent;
+       struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi);
+       regmap_read(n_spi->reg_map, n_spi->regstart_table->stm_ao_mode_reg, &val);
+       ret = scnprintf(buf, 255, "%d\n", val);
+       return ret;
+}
+
+ssize_t neuronspi_iio_store_primary_ao_mode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+       ssize_t err = 0;
+       unsigned int val = 0;
+       struct iio_dev *indio_dev = dev_get_drvdata(dev);
+       struct neuronspi_stm_ao_data *ao_data = iio_priv(indio_dev);
+       struct spi_device *spi = ao_data->parent;
+       struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi);
+       err = kstrtouint(buf, 0, &val);
+       if (err < 0) goto err_end;
+       if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) {
+               regmap_write(n_spi->reg_map, n_spi->regstart_table->stm_ao_mode_reg, val);
+       }
+err_end:
+       return count;
+}
+
+ssize_t neuronspi_iio_show_secondary_ai_mode(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       int ret = 0;
+       unsigned int val = 0;
+       struct iio_dev *indio_dev = dev_get_drvdata(dev);
+       struct neuronspi_sec_ai_data *ai_data = iio_priv(indio_dev);
+       struct spi_device *spi = ai_data->parent;
+       struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi);
+       regmap_read(n_spi->reg_map, n_spi->regstart_table->sec_ai_mode_reg + ai_data->index, &val);
+       ret = scnprintf(buf, 255, "%d\n", val);
+       return ret;
+}
+ssize_t neuronspi_iio_store_secondary_ai_mode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+       ssize_t err = 0;
+       unsigned int val = 0;
+       struct iio_dev *indio_dev = dev_get_drvdata(dev);
+       struct neuronspi_sec_ai_data *ai_data = iio_priv(indio_dev);
+       struct spi_device *spi = ai_data->parent;
+       struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi);
+       err = kstrtouint(buf, 0, &val);
+       if (err < 0) goto err_end;
+       if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) {
+               regmap_write(n_spi->reg_map, n_spi->regstart_table->sec_ai_mode_reg + ai_data->index, val);
+       }
+err_end:
+       return count;
+}
+ssize_t neuronspi_iio_show_secondary_ao_mode(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       int ret = 0;
+       unsigned int val = 0;
+       struct iio_dev *indio_dev = dev_get_drvdata(dev);
+       struct neuronspi_sec_ao_data *ao_data = iio_priv(indio_dev);
+       struct spi_device *spi = ao_data->parent;
+       struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi);
+       regmap_read(n_spi->reg_map, n_spi->regstart_table->sec_ao_mode_reg + ao_data->index, &val);
+       ret = scnprintf(buf, 255, "%d\n", val);
+       return ret;
+}
+ssize_t neuronspi_iio_store_secondary_ao_mode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+       ssize_t err = 0;
+       unsigned int val = 0;
+       struct iio_dev *indio_dev = dev_get_drvdata(dev);
+       struct neuronspi_sec_ao_data *ao_data = iio_priv(indio_dev);
+       struct spi_device *spi = ao_data->parent;
+       struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi);
+       err = kstrtouint(buf, 0, &val);
+       if (err < 0) goto err_end;
+       if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) {
+               regmap_write(n_spi->reg_map, n_spi->regstart_table->sec_ao_mode_reg + ao_data->index, val);
+       }
+err_end:
+       return count;
+}
index 5509cea1fa83d9d2716b809d102ee4ccba9800ba..f4fa30b39ddcf011ea46795ff03ca06b5ab42133 100644 (file)
 #ifndef MODULES_NEURON_SPI_SRC_UNIPI_SYSFS_H_
 #define MODULES_NEURON_SPI_SRC_UNIPI_SYSFS_H_
 
+#include <linux/bitops.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/gpio.h>
+#include <linux/gpio/driver.h>
+#include <linux/i2c.h>
+#include <linux/iio/iio.h>
+#include <uapi/linux/iio/types.h>
+#include <linux/iio/sysfs.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/regmap.h>
+#include <linux/serial_core.h>
+#include <linux/serial.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/spi/spi.h>
+#include <linux/leds.h>
+#include <linux/uaccess.h>
+#include <asm/termbits.h>
+#include <asm/gpio.h>
 
+#include "unipi_common.h"
+#include "unipi_platform.h"
 
+ssize_t neuronspi_show_model(struct device *dev, struct device_attribute *attr, char *buf);
+ssize_t neuronspi_show_eeprom(struct device *dev, struct device_attribute *attr, char *buf);
+ssize_t neuronspi_show_regmap(struct device *dev, struct device_attribute *attr, char *buf);
+ssize_t neuronspi_store_regmap(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
+ssize_t neuronspi_spi_show_serial(struct device *dev, struct device_attribute *attr, char *buf);
+ssize_t neuronspi_spi_show_board(struct device *dev, struct device_attribute *attr, char *buf);
+ssize_t neuronspi_spi_show_lboard_id(struct device *dev, struct device_attribute *attr, char *buf);
+ssize_t neuronspi_spi_show_uboard_id(struct device *dev, struct device_attribute *attr, char *buf);
+ssize_t neuronspi_spi_show_hw_version(struct device *dev, struct device_attribute *attr, char *buf);
+ssize_t neuronspi_spi_show_hw_flash_version(struct device *dev, struct device_attribute *attr, char *buf);
+ssize_t neuronspi_spi_show_fw_version(struct device *dev, struct device_attribute *attr, char *buf);
+ssize_t neuronspi_spi_show_uart_queue_length(struct device *dev, struct device_attribute *attr, char *buf);
+ssize_t neuronspi_spi_show_uart_config(struct device *dev, struct device_attribute *attr, char *buf);
+ssize_t neuronspi_spi_store_uart_config(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
+ssize_t neuronspi_spi_show_watchdog_status(struct device *dev, struct device_attribute *attr, char *buf);
+ssize_t neuronspi_spi_store_watchdog_status(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
+ssize_t neuronspi_spi_show_watchdog_timeout(struct device *dev, struct device_attribute *attr, char *buf);
+ssize_t neuronspi_spi_store_watchdog_timeout(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
+ssize_t neuronspi_spi_gpio_show_pwm_freq(struct device *dev, struct device_attribute *attr, char *buf);
+ssize_t neuronspi_spi_gpio_store_pwm_freq(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
+ssize_t neuronspi_spi_gpio_di_show_counter(struct device *dev, struct device_attribute *attr, char *buf);
+ssize_t neuronspi_spi_gpio_di_store_counter(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
+ssize_t neuronspi_spi_gpio_di_show_debounce(struct device *dev, struct device_attribute *attr, char *buf);
+ssize_t neuronspi_spi_gpio_di_store_debounce(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
+ssize_t neuronspi_spi_gpio_show_pwm_cycle(struct device *dev, struct device_attribute *attr, char *buf);
+ssize_t neuronspi_spi_gpio_store_pwm_cycle(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
+ssize_t neuronspi_spi_gpio_show_pwm_presc(struct device *dev, struct device_attribute *attr, char *buf);
+ssize_t neuronspi_spi_gpio_store_pwm_presc(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
+ssize_t neuronspi_spi_gpio_store_ds_enable(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
+ssize_t neuronspi_spi_gpio_store_ds_toggle(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
+ssize_t neuronspi_spi_gpio_store_ds_polarity(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
+ssize_t neuronspi_spi_gpio_show_ds_enable(struct device *dev, struct device_attribute *attr, char *buf);
+ssize_t neuronspi_spi_gpio_show_ds_toggle(struct device *dev, struct device_attribute *attr, char *buf);
+ssize_t neuronspi_spi_gpio_show_ds_polarity(struct device *dev, struct device_attribute *attr, char *buf);
+ssize_t neuronspi_spi_gpio_show_do_prefix(struct device *dev, struct device_attribute *attr, char *buf);
+ssize_t neuronspi_spi_gpio_show_do_base(struct device *dev, struct device_attribute *attr, char *buf);
+ssize_t neuronspi_spi_gpio_show_do_count(struct device *dev, struct device_attribute *attr, char *buf);
+ssize_t neuronspi_spi_gpio_show_di_prefix(struct device *dev, struct device_attribute *attr, char *buf);
+ssize_t neuronspi_spi_gpio_show_di_base(struct device *dev, struct device_attribute *attr, char *buf);
+ssize_t neuronspi_spi_gpio_show_di_count(struct device *dev, struct device_attribute *attr, char *buf);
+ssize_t neuronspi_spi_gpio_show_ro_prefix(struct device *dev, struct device_attribute *attr, char *buf);
+ssize_t neuronspi_spi_gpio_show_ro_base(struct device *dev, struct device_attribute *attr, char *buf);
+ssize_t neuronspi_spi_gpio_show_ro_count(struct device *dev, struct device_attribute *attr, char *buf);
+ssize_t neuronspi_spi_gpio_di_show_value(struct device *dev, struct device_attribute *attr, char *buf);
+ssize_t neuronspi_spi_gpio_do_show_value(struct device *dev, struct device_attribute *attr, char *buf);
+ssize_t neuronspi_spi_gpio_do_store_value(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
+ssize_t neuronspi_spi_gpio_ro_show_value(struct device *dev, struct device_attribute *attr, char *buf);
+ssize_t neuronspi_spi_gpio_ro_store_value(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
+ssize_t neuronspi_iio_show_primary_ai_mode(struct device *dev, struct device_attribute *attr, char *buf);
+ssize_t neuronspi_iio_store_primary_ai_mode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
+ssize_t neuronspi_iio_show_primary_ao_mode(struct device *dev, struct device_attribute *attr, char *buf);
+ssize_t neuronspi_iio_store_primary_ao_mode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
+ssize_t neuronspi_iio_show_secondary_ai_mode(struct device *dev, struct device_attribute *attr, char *buf);
+ssize_t neuronspi_iio_store_secondary_ai_mode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
+ssize_t neuronspi_iio_show_secondary_ao_mode(struct device *dev, struct device_attribute *attr, char *buf);
+ssize_t neuronspi_iio_store_secondary_ao_mode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
 
+static DEVICE_ATTR(model_name, 0440, neuronspi_show_model, NULL);
+static DEVICE_ATTR(sys_eeprom_name, 0440, neuronspi_show_eeprom, NULL);
+static DEVICE_ATTR(register_read, 0660, neuronspi_show_regmap, neuronspi_store_regmap);
+static DEVICE_ATTR(sys_board_serial, 0440, neuronspi_spi_show_serial, NULL);
+static DEVICE_ATTR(sys_board_name, 0440, neuronspi_spi_show_board, NULL);
+static DEVICE_ATTR(sys_primary_major_id, 0440, neuronspi_spi_show_lboard_id, NULL);
+static DEVICE_ATTR(sys_secondary_major_id, 0440, neuronspi_spi_show_uboard_id, NULL);
+static DEVICE_ATTR(sys_primary_minor_id, 0440, neuronspi_spi_show_hw_version, NULL);
+static DEVICE_ATTR(sys_secondary_minor_id, 0440, neuronspi_spi_show_hw_flash_version, NULL);
+static DEVICE_ATTR(firmware_version, 0440, neuronspi_spi_show_fw_version, NULL);
+static DEVICE_ATTR(watchdog_status, 0660, neuronspi_spi_show_watchdog_status, neuronspi_spi_store_watchdog_status);
+static DEVICE_ATTR(watchdog_timeout, 0660, neuronspi_spi_show_watchdog_timeout, neuronspi_spi_store_watchdog_timeout);
+static DEVICE_ATTR(sys_gpio_do_count, 0440, neuronspi_spi_gpio_show_do_count, NULL);
+static DEVICE_ATTR(sys_gpio_do_prefix, 0440, neuronspi_spi_gpio_show_do_prefix, NULL);
+static DEVICE_ATTR(sys_gpio_do_base, 0440, neuronspi_spi_gpio_show_do_base, NULL);
+static DEVICE_ATTR(sys_gpio_di_count, 0440, neuronspi_spi_gpio_show_di_count, NULL);
+static DEVICE_ATTR(sys_gpio_di_prefix, 0440, neuronspi_spi_gpio_show_di_prefix, NULL);
+static DEVICE_ATTR(ro_value, 0660, neuronspi_spi_gpio_ro_show_value, neuronspi_spi_gpio_ro_store_value);
+static DEVICE_ATTR(do_value, 0660, neuronspi_spi_gpio_do_show_value, neuronspi_spi_gpio_do_store_value);
+static DEVICE_ATTR(counter, 0660, neuronspi_spi_gpio_di_show_counter, neuronspi_spi_gpio_di_store_counter);
+static DEVICE_ATTR(debounce, 0660, neuronspi_spi_gpio_di_show_debounce, neuronspi_spi_gpio_di_store_debounce);
+static DEVICE_ATTR(di_value, 0440, neuronspi_spi_gpio_di_show_value, NULL);
+static DEVICE_ATTR(direct_switch_enable, 0660, neuronspi_spi_gpio_show_ds_enable, neuronspi_spi_gpio_store_ds_enable);
+static DEVICE_ATTR(direct_switch_toggle, 0660, neuronspi_spi_gpio_show_ds_toggle, neuronspi_spi_gpio_store_ds_toggle);
+static DEVICE_ATTR(direct_switch_polarity, 0660, neuronspi_spi_gpio_show_ds_polarity, neuronspi_spi_gpio_store_ds_polarity);
+static DEVICE_ATTR(pwm_frequency_cycle, 0660, neuronspi_spi_gpio_show_pwm_freq, neuronspi_spi_gpio_store_pwm_freq);
+static DEVICE_ATTR(pwm_prescale, 0660, neuronspi_spi_gpio_show_pwm_presc, neuronspi_spi_gpio_store_pwm_presc);
+static DEVICE_ATTR(pwm_duty_cycle, 0660, neuronspi_spi_gpio_show_pwm_cycle, neuronspi_spi_gpio_store_pwm_cycle);
+static DEVICE_ATTR(uart_queue_length, 0440, neuronspi_spi_show_uart_queue_length, NULL);
+static DEVICE_ATTR(uart_config, 0660, neuronspi_spi_show_uart_config, neuronspi_spi_store_uart_config);
+static DEVICE_ATTR(sys_gpio_di_base, 0440, neuronspi_spi_gpio_show_di_base, NULL);
+static DEVICE_ATTR(sys_gpio_ro_count, 0440, neuronspi_spi_gpio_show_ro_count, NULL);
+static DEVICE_ATTR(sys_gpio_ro_prefix, 0440, neuronspi_spi_gpio_show_ro_prefix, NULL);
+static DEVICE_ATTR(sys_gpio_ro_base, 0440, neuronspi_spi_gpio_show_ro_base, NULL);
+static DEVICE_ATTR(mode_ai_type_a, 0660, neuronspi_iio_show_primary_ai_mode, neuronspi_iio_store_primary_ai_mode);
+static DEVICE_ATTR(mode_ao_type_a, 0660, neuronspi_iio_show_primary_ao_mode, neuronspi_iio_store_primary_ao_mode);
+static DEVICE_ATTR(mode_ai_type_b, 0660, neuronspi_iio_show_secondary_ai_mode, neuronspi_iio_store_secondary_ai_mode);
+static DEVICE_ATTR(mode_ao_type_b, 0660, neuronspi_iio_show_secondary_ao_mode, neuronspi_iio_store_secondary_ao_mode);
+
+static struct attribute *neuron_plc_attrs[] = {
+               &dev_attr_model_name.attr,
+               &dev_attr_sys_eeprom_name.attr,
+               NULL,
+};
+
+static struct attribute *neuron_board_attrs[] = {
+               &dev_attr_sys_board_name.attr,
+               &dev_attr_sys_primary_major_id.attr,
+               &dev_attr_sys_secondary_major_id.attr,
+               &dev_attr_sys_primary_minor_id.attr,
+               &dev_attr_sys_secondary_minor_id.attr,
+               &dev_attr_firmware_version.attr,
+               &dev_attr_watchdog_status.attr,
+               &dev_attr_watchdog_timeout.attr,
+               &dev_attr_sys_board_serial.attr,
+               &dev_attr_uart_queue_length.attr,
+               &dev_attr_uart_config.attr,
+               &dev_attr_register_read.attr,
+               NULL,
+};
+
+static struct attribute *neuron_gpio_di_attrs[] = {
+               &dev_attr_sys_gpio_di_count.attr,
+               &dev_attr_sys_gpio_di_prefix.attr,
+               &dev_attr_sys_gpio_di_base.attr,
+               &dev_attr_direct_switch_enable.attr,
+               &dev_attr_direct_switch_toggle.attr,
+               &dev_attr_direct_switch_polarity.attr,
+               &dev_attr_di_value.attr,
+               &dev_attr_counter.attr,
+               &dev_attr_debounce.attr,
+               NULL,
+};
+
+static struct attribute *neuron_gpio_do_attrs[] = {
+               &dev_attr_sys_gpio_do_count.attr,
+               &dev_attr_sys_gpio_do_prefix.attr,
+               &dev_attr_sys_gpio_do_base.attr,
+               &dev_attr_pwm_frequency_cycle.attr,
+               &dev_attr_pwm_prescale.attr,
+               &dev_attr_pwm_duty_cycle.attr,
+               &dev_attr_do_value.attr,
+               NULL,
+};
+
+static struct attribute *neuron_gpio_ro_attrs[] = {
+               &dev_attr_sys_gpio_ro_count.attr,
+               &dev_attr_sys_gpio_ro_prefix.attr,
+               &dev_attr_sys_gpio_ro_base.attr,
+               &dev_attr_ro_value.attr,
+               NULL,
+};
+
+static struct attribute *neuron_stm_ai_attrs[] = {
+               &dev_attr_mode_ai_type_a.attr,
+               NULL,
+};
+
+static struct attribute *neuron_stm_ao_attrs[] = {
+               &dev_attr_mode_ao_type_a.attr,
+               NULL,
+};
+
+static struct attribute *neuron_sec_ai_attrs[] = {
+               &dev_attr_mode_ai_type_b.attr,
+               NULL,
+};
+
+static struct attribute *neuron_sec_ao_attrs[] = {
+               &dev_attr_mode_ao_type_b.attr,
+               NULL,
+};
+
+static struct attribute_group neuron_plc_attr_group = {
+       .attrs = neuron_plc_attrs,
+};
+
+static struct attribute_group neuron_board_attr_group = {
+       .attrs = neuron_board_attrs,
+};
+
+static struct attribute_group neuron_gpio_di_attr_group = {
+       .attrs = neuron_gpio_di_attrs,
+};
+
+static struct attribute_group neuron_gpio_do_attr_group = {
+       .attrs = neuron_gpio_do_attrs,
+};
+
+static struct attribute_group neuron_gpio_ro_attr_group = {
+       .attrs = neuron_gpio_ro_attrs,
+};
+
+static struct attribute_group neuron_stm_ai_group = {
+       .attrs = neuron_stm_ai_attrs,
+};
+
+static struct attribute_group neuron_stm_ao_group = {
+       .attrs = neuron_stm_ao_attrs,
+};
+
+static struct attribute_group neuron_sec_ai_group = {
+       .attrs = neuron_sec_ai_attrs,
+};
+
+static struct attribute_group neuron_sec_ao_group = {
+       .attrs = neuron_sec_ao_attrs,
+};
+
+static const struct attribute_group *neuron_plc_attr_groups[] = {
+       &neuron_plc_attr_group,
+       NULL,
+};
+
+static const struct attribute_group *neuron_board_attr_groups[] = {
+       &neuron_board_attr_group,
+       NULL,
+};
+
+static const struct attribute_group *neuron_gpio_di_attr_groups[] = {
+       &neuron_gpio_di_attr_group,
+       NULL,
+};
+
+static const struct attribute_group *neuron_gpio_do_attr_groups[] = {
+       &neuron_gpio_do_attr_group,
+       NULL,
+};
+
+static const struct attribute_group *neuron_gpio_ro_attr_groups[] = {
+       &neuron_gpio_ro_attr_group,
+       NULL,
+};
 
 #endif /* MODULES_NEURON_SPI_SRC_UNIPI_SYSFS_H_ */
index b43a7f5ea0e459e3b0d40bb1b7fd1c41bd5ed33d..90200f772c5dad91ba765d140dec106aefca2fcc 100644 (file)
  * (at your option) any later version.
  *
  */
+
+
+#include "unipi_uart.h"
+#include "unipi_spi.h"
+
+void neuronspi_uart_tx_proc(struct kthread_work *ws)
+{
+       struct neuronspi_port *port = to_neuronspi_port(ws, tx_work);
+
+       if ((port->port.rs485.flags & SER_RS485_ENABLED) &&
+           (port->port.rs485.delay_rts_before_send > 0)) {
+               msleep(port->port.rs485.delay_rts_before_send);
+       }
+
+       neuronspi_uart_handle_tx(port);
+}
+
+u32 neuronspi_uart_tx_empty(struct uart_port *port)
+{
+#if NEURONSPI_DETAILED_DEBUG > 0
+       printk(KERN_INFO "NEURONSPI: UART TX Empty\n");
+#endif
+       return TIOCSER_TEMT;
+}
+
+u32 neuronspi_uart_get_mctrl(struct uart_port *port)
+{
+       /* DCD and DSR are not wired and CTS/RTS is handled automatically
+        * so just indicate DSR and CAR asserted
+        */
+#if NEURONSPI_DETAILED_DEBUG > 0
+       printk(KERN_DEBUG "NEURONSPI: UART MCTRL Get\n");
+#endif
+       return TIOCM_DSR | TIOCM_CAR;
+}
+
+void neuronspi_uart_set_mctrl(struct uart_port *port, u32 mctrl)
+{
+       /* Do Nothing */
+}
+
+int    neuronspi_uart_ioctl (struct uart_port *port, unsigned int ioctl_code, unsigned long ioctl_arg)
+{
+       switch (ioctl_code) {
+       case TIOCSETD: {
+               printk(KERN_INFO "NEURONSPI: IOCTL TIOCSETD\n");
+               return 1;
+       }
+       case 0x5480: {
+               printk(KERN_INFO "NEURONSPI: IOCTL 0x5480\n");
+               return 1;
+       }
+       case 0x5481: {
+               printk(KERN_INFO "NEURONSPI: IOCTL 0x5481\n");
+               return 1;
+       }
+       default: {
+               return 0;
+       }
+       }
+}
+
+void neuronspi_uart_set_parmrk(struct uart_port *port, int to)
+{
+       struct neuronspi_port *n_port;
+       n_port = to_neuronspi_port(port, port);
+}
+
+void neuronspi_uart_set_ldisc(struct uart_port *port, struct ktermios *kterm)
+{
+       struct neuronspi_port *n_port;
+       n_port = to_neuronspi_port(port, port);
+       if (kterm->c_line == N_PROFIBUS_FDL) {
+               printk(KERN_INFO "NEURONSPI: PROFIBUS discipline set/n");
+       }
+       return;
+}
+
+void neuronspi_uart_break_ctl(struct uart_port *port, int break_state)
+{
+
+}
+
+void neuronspi_uart_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old)
+{
+       s32 baud;
+       struct neuronspi_port *n_port;
+       n_port = to_neuronspi_port(port, port);
+       if (old && old->c_iflag && old->c_iflag != termios->c_iflag) {
+               printk(KERN_INFO "NEURONSPI: c_iflag termios:%d\n", termios->c_iflag);
+       }
+#if NEURONSPI_DETAILED_DEBUG > 0
+       printk(KERN_DEBUG "NEURONSPI: TERMIOS Set, p:%d, c_cflag:%x\n", port->line, termios->c_cflag);
+#endif
+       neuronspi_spi_uart_set_cflag(neuronspi_s_dev[n_port->dev_index], n_port->dev_port, termios->c_cflag);
+       if (old && termios && (old->c_iflag & PARMRK) != (termios->c_iflag & PARMRK)) {
+               if (termios->c_iflag & PARMRK) {
+                       neuronspi_uart_set_parmrk(port, 1);             // TODO: Re-enable line discipline once finished
+               } else {
+                       neuronspi_uart_set_parmrk(port, 0);
+               }
+       }
+       if (old && termios && old->c_line != termios->c_line) {
+               if (termios->c_line == N_PROFIBUS_FDL) {
+                       printk(KERN_INFO "NEURONSPI: Line Discipline change/n");
+                       neuronspi_uart_set_ldisc(port, termios);
+               }
+       }
+
+       baud = uart_get_baud_rate(port, termios, old, 2400, 115200);
+       uart_update_timeout(port, termios->c_cflag, baud);
+}
+
+s32 neuronspi_uart_config_rs485(struct uart_port *port, struct serial_rs485 *rs485)
+{
+       port->rs485 = *rs485;
+       return 0;
+}
+
+// Initialise the module
+s32 neuronspi_uart_startup(struct uart_port *port)
+{
+       struct neuronspi_port *n_port = to_neuronspi_port(port, port);
+       struct spi_device *spi = neuronspi_s_dev[n_port->dev_index];
+       struct neuronspi_driver_data *d_data = spi_get_drvdata(spi);
+       neuronspi_spi_set_irqs(spi, 0x5);
+       if (d_data->poll_thread != NULL) {
+               wake_up_process(d_data->poll_thread);
+       } else if (d_data->no_irq) {
+               d_data->poll_thread = kthread_create(neuronspi_uart_poll, (void *)d_data, "UART_poll_thread");
+       }
+       neuronspi_uart_power(port, 1);
+       // TODO: /* Reset FIFOs*/
+#if NEURONSPI_DETAILED_DEBUG > 0
+       printk(KERN_DEBUG "NEURONSPI: UART Startup\n");
+#endif
+       return 0;
+}
+
+void neuronspi_uart_shutdown(struct uart_port *port)
+{
+    neuronspi_uart_power(port, 0);
+}
+
+const char* neuronspi_uart_type(struct uart_port *port)
+{
+       return port->type == PORT_NEURONSPI ? "NEURONSPI_NAME" : NULL;
+}
+
+s32 neuronspi_uart_request_port(struct uart_port *port)
+{
+#if NEURONSPI_DETAILED_DEBUG > 0
+       printk(KERN_DEBUG "NEURONSPI: Requested port %d\n", port->line);
+#endif
+       return 0;
+}
+
+void neuronspi_uart_fifo_read(struct uart_port *port, u32 rxlen)
+{
+       struct neuronspi_port *s = to_neuronspi_port(port,port);
+       struct neuronspi_driver_data *d_data = spi_get_drvdata(neuronspi_s_dev[s->dev_index]);
+#if NEURONSPI_DETAILED_DEBUG > 0
+       printk(KERN_INFO "NEURONSPI: FIFO Read len:%d\n", rxlen);
+#endif
+    memcpy(s->buf, d_data->uart_buf, rxlen);
+}
+
+void neuronspi_uart_fifo_write(struct neuronspi_port *port, u8 to_send)
+{
+       s32 i;
+#if NEURONSPI_DETAILED_DEBUG > 0
+       printk(KERN_INFO "NEURONSPI: FIFO Write to_send:%d\n", to_send);
+#endif
+       for (i = 0; i < to_send; i++) {
+#if NEURONSPI_DETAILED_DEBUG > 0
+               printk(KERN_INFO "NEURONSPI: UART Char Send: %x\n", port->buf[i]);
+#endif
+       }
+    neuronspi_spi_uart_write(neuronspi_s_dev[port->dev_index], port->buf, to_send, port->dev_port);
+}
+
+s32 neuronspi_uart_alloc_line(void)
+{
+       s32 i;
+       BUILD_BUG_ON(NEURONSPI_MAX_DEVS > BITS_PER_LONG);
+
+       for (i = 0; i < NEURONSPI_MAX_DEVS; i++)
+               if (!test_and_set_bit(i, &neuronspi_lines))
+                       break;
+
+       return i;
+}
+
+void neuronspi_uart_power(struct uart_port *port, s32 on)
+{
+    /* Do nothing */
+}
+
+void neuronspi_uart_handle_rx(struct neuronspi_port *port, u32 rxlen, u32 iir)
+{
+       u32 ch, flag, bytes_read, i;
+       while (rxlen) {
+
+               neuronspi_uart_fifo_read(&port->port, rxlen);
+               bytes_read = rxlen;
+
+               port->port.icount.rx++;
+               flag = TTY_NORMAL;
+
+               for (i = 0; i < bytes_read; ++i) {
+#if NEURONSPI_DETAILED_DEBUG > 0
+                       printk(KERN_INFO "NEURONSPI: UART Insert Char:%x\n", port->buf[i]);
+#endif
+                       ch = port->buf[i];
+                       if (uart_handle_sysrq_char(port, ch))
+                               continue;
+
+                       uart_insert_char(&port->port, 0, 0, ch, flag);
+               }
+               rxlen -= bytes_read;
+       }
+
+       tty_flip_buffer_push(&port->port.state->port);
+}
+
+void neuronspi_uart_handle_tx(struct neuronspi_port *port)
+{
+       u32 txlen, to_send, i;
+       struct spi_device *spi;
+       struct neuronspi_driver_data *d_data;
+       struct circ_buf *xmit;
+
+       spi = neuronspi_s_dev[port->dev_index];
+       d_data = spi_get_drvdata(spi);
+       xmit = &port->port.state->xmit;
+
+       if (unlikely(port->port.x_char)) {
+               neuronspi_spi_uart_write(spi, &port->port.x_char, 1, port->dev_port);
+               port->port.icount.tx++;
+               port->port.x_char = 0;
+               return;
+       }
+
+       if (uart_circ_empty(xmit) || uart_tx_stopped(&port->port)) {
+               return;
+       }
+
+
+       /* Get length of data pending in circular buffer */
+       to_send = uart_circ_chars_pending(xmit);
+       if (likely(to_send)) {
+               /* Limit to size of TX FIFO */
+               txlen = NEURONSPI_FIFO_SIZE;
+               to_send = (to_send > txlen) ? txlen : to_send;
+
+               /* Add data to send */
+               port->port.icount.tx += to_send;
+
+               /* Convert to linear buffer */
+               for (i = 0; i < to_send; ++i) {
+                       port->buf[i] = xmit->buf[xmit->tail];
+                       xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+               }
+
+               neuronspi_uart_fifo_write(port, to_send);
+       }
+
+
+       if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+               uart_write_wakeup(&port->port);
+}
+
+void neuronspi_uart_handle_irq(struct neuronspi_uart_data *uart_data, u32 portno)
+{
+       struct neuronspi_port *n_port = &uart_data->p[portno];
+       struct spi_device *spi = neuronspi_s_dev[n_port->dev_index];
+       u8 *send_buf = kzalloc(NEURONSPI_UART_PROBE_MESSAGE_LEN, GFP_KERNEL);
+       u8 *recv_buf = kzalloc(NEURONSPI_UART_PROBE_MESSAGE_LEN, GFP_KERNEL);
+       memcpy(send_buf, NEURONSPI_UART_PROBE_MESSAGE, NEURONSPI_UART_PROBE_MESSAGE_LEN);
+       neuronspi_spi_send_message(spi, send_buf, recv_buf, NEURONSPI_UART_PROBE_MESSAGE_LEN, NEURONSPI_DEFAULT_FREQ, 25, 1);
+       kfree(send_buf);
+       kfree(recv_buf);
+}
+
+void neuronspi_uart_ist(struct kthread_work *ws)
+{
+       struct neuronspi_port *p = to_neuronspi_port(ws, irq_work);
+       neuronspi_uart_handle_irq(p->parent, p->line);
+}
+
+void neuronspi_uart_config_port(struct uart_port *port, int flags)
+{
+       if (flags & UART_CONFIG_TYPE)
+               port->type = PORT_NEURONSPI;
+}
+
+s32 neuronspi_uart_verify_port(struct uart_port *port,
+                                struct serial_struct *s)
+{
+       if ((s->type != PORT_UNKNOWN) && (s->type != PORT_NEURONSPI))
+               return -EINVAL;
+       if (s->irq != port->irq)
+               return -EINVAL;
+
+       return 0;
+}
+
+void neuronspi_uart_pm(struct uart_port *port, u32 state, u32 oldstate)
+{
+       neuronspi_uart_power(port, (state == UART_PM_STATE_ON) ? 1 : 0);
+}
+
+void neuronspi_uart_null_void(struct uart_port *port)
+{
+       /* Do nothing */
+}
+
+s32 neuronspi_uart_probe(struct spi_device* dev, u8 device_index)
+{
+       struct neuronspi_driver_data* driver_data = spi_get_drvdata(dev);
+       struct sched_param sched_param = { .sched_priority = MAX_RT_PRIO / 2 };
+       s32 i, j, ret, new_uart_count;
+       struct neuronspi_uart_data *uart_data = driver_data->uart_data;
+
+       if (uart_data->p == NULL) {
+               uart_data->p = kzalloc(sizeof(struct neuronspi_port[NEURONSPI_MAX_UART]), GFP_KERNEL);
+               for (i = 0; i < NEURONSPI_MAX_UART; i++) {
+                       uart_data->p[i].parent = uart_data;
+               }
+#if NEURONSPI_DETAILED_DEBUG > 0
+               printk(KERN_DEBUG "NEURONSPI: Allocated port structure for %d potential UART devices\n", NEURONSPI_MAX_UART);
+#endif
+       }
+
+       new_uart_count = driver_data->uart_count + uart_data->p_count;
+
+       // Initialise port data
+       for (i = uart_data->p_count; i < new_uart_count; i++) {
+               uart_data->p[i].dev_index = device_index;
+               uart_data->p[i].dev_port = i - uart_data->p_count;
+               uart_data->p[i].line            = i;
+               uart_data->p[i].port.dev        = &(dev->dev);
+               uart_data->p[i].port.irq        = dev->irq;
+               uart_data->p[i].port.type       = PORT_NEURONSPI;
+               uart_data->p[i].port.fifosize   = NEURONSPI_FIFO_SIZE;
+               uart_data->p[i].port.flags      = UPF_FIXED_TYPE | UPF_LOW_LATENCY;
+               uart_data->p[i].port.iotype     = UPIO_PORT;
+               uart_data->p[i].port.uartclk    = 9600;
+               uart_data->p[i].port.rs485_config = neuronspi_uart_config_rs485;
+               uart_data->p[i].port.ops        = &neuronspi_uart_ops;
+               uart_data->p[i].port.line       = neuronspi_uart_alloc_line();
+               spin_lock_init(&uart_data->p[i].port.lock);
+               if (uart_data->p[i].port.line >= NEURONSPI_MAX_DEVS) {
+                       ret = -ENOMEM;
+               }
+               kthread_init_work(&(uart_data->p[i].tx_work), neuronspi_uart_tx_proc);
+               kthread_init_work(&(uart_data->p[i].rx_work), neuronspi_uart_rx_proc);
+               kthread_init_work(&(uart_data->p[i].irq_work), neuronspi_uart_ist);
+               uart_add_one_port(driver_data->serial_driver, &uart_data->p[i].port);
+               printk(KERN_INFO "NEURONSPI: Added UART port %d\n", i);
+       }
+
+       // For ports on multiple SPI devices renumber the ports to correspond to SPI chip-select numbering
+       if (uart_data->p_count) {
+               // First remove all existing ports
+               for (i = 0; i < new_uart_count; i++) {
+                       uart_remove_one_port(driver_data->serial_driver, &uart_data->p[i].port);
+                       clear_bit(uart_data->p[i].port.line, &neuronspi_lines);
+                       kthread_flush_worker(&uart_data->kworker);
+               }
+               // Now add the ports in the correct order
+               for (i = 0; i < NEURONSPI_MAX_DEVS; i++) {
+                       if (neuronspi_s_dev[i] != NULL) {
+                               driver_data = spi_get_drvdata(neuronspi_s_dev[i]);
+#if NEURONSPI_DETAILED_DEBUG > 0
+                               printk(KERN_DEBUG "NEURONSPI: Renumber not NULL %d UC:%d\n", i, driver_data->uart_count);
+#endif
+                               if (driver_data->uart_count) {
+                                       for (j = 0; j < new_uart_count; j++) {
+                                               if (uart_data->p[j].dev_index == i) {
+                                                       uart_data->p[j].port.dev        = &(neuronspi_s_dev[i]->dev);
+                                                       uart_data->p[j].port.irq        = neuronspi_s_dev[i]->irq;
+                                                       uart_data->p[j].port.type       = PORT_NEURONSPI;
+                                                       uart_data->p[j].port.fifosize   = NEURONSPI_FIFO_SIZE;
+                                                       uart_data->p[j].port.flags      = UPF_FIXED_TYPE | UPF_LOW_LATENCY;
+                                                       uart_data->p[j].port.iotype     = UPIO_PORT;
+                                                       uart_data->p[j].port.uartclk    = 9800;
+                                                       uart_data->p[j].port.rs485_config = neuronspi_uart_config_rs485;
+                                                       uart_data->p[j].port.ops        = &neuronspi_uart_ops;
+                                                       uart_data->p[j].port.line       = neuronspi_uart_alloc_line();
+                                                       uart_add_one_port(driver_data->serial_driver, &uart_data->p[j].port);
+#if NEURONSPI_DETAILED_DEBUG > 0
+                                                       printk(KERN_DEBUG "NEURONSPI: Added UART port %d\n", j);
+#endif
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+
+       uart_data->p_count = new_uart_count;
+       if (uart_data->kworker_task == NULL) {
+#if NEURONSPI_DETAILED_DEBUG > 0
+               printk(KERN_DEBUG "NEURONSPI: KWorker Task is NULL\n");
+#endif
+
+               kthread_init_worker(&uart_data->kworker);
+
+               uart_data->kworker_task = kthread_run(kthread_worker_fn, &uart_data->kworker,
+                                                 "neuronspi");
+               if (IS_ERR(uart_data->kworker_task)) {
+                       ret = PTR_ERR(uart_data->kworker_task);
+               }
+               sched_setscheduler(uart_data->kworker_task, SCHED_FIFO, &sched_param);
+       }
+       return ret;
+}
+
+s32 neuronspi_uart_remove(struct neuronspi_uart_data *u_data)
+{
+       struct neuronspi_driver_data *d_data;
+       struct spi_device *spi;
+       s32 i;
+
+       for (i = 0; i < NEURONSPI_MAX_DEVS; i++) {
+               if (!(neuronspi_s_dev[i] == NULL)) {
+                       spi = neuronspi_s_dev[i];
+                       d_data = spi_get_drvdata(spi);
+                       if (d_data->poll_thread != NULL) {
+                               kthread_stop(d_data->poll_thread);
+                       }
+               }
+       }
+       for (i = 0; i < u_data->p_count; i++) {
+               uart_remove_one_port(neuronspi_uart, &u_data->p[i].port);
+               clear_bit(u_data->p[i].port.line, &neuronspi_lines);
+               neuronspi_uart_power(&u_data->p[i].port, 0);
+       }
+
+       kthread_flush_worker(&u_data->kworker);
+       return 0;
+}
+
+void neuronspi_uart_rx_proc(struct kthread_work *ws)
+{
+       s32 end_flag = 0;
+       s32 read_count = 0;
+       struct neuronspi_port *n_port = to_neuronspi_port(ws, rx_work);
+       struct spi_device *spi = neuronspi_s_dev[n_port->dev_index];
+       struct neuronspi_driver_data *d_data = spi_get_drvdata(spi);
+
+       u8 *send_buf = kzalloc(NEURONSPI_BUFFER_MAX, GFP_KERNEL);
+       u8 *recv_buf = kzalloc(NEURONSPI_BUFFER_MAX, GFP_KERNEL);
+
+       mutex_lock(&neuronspi_master_mutex);
+       read_count = d_data->uart_read;
+       mutex_unlock(&neuronspi_master_mutex);
+
+       while (!end_flag) {
+               memset(recv_buf, 0, NEURONSPI_BUFFER_MAX);
+               neuronspi_spi_uart_read(spi, send_buf, recv_buf, read_count, n_port->dev_port);
+               if (recv_buf[6] == 0x65 && recv_buf[7] > 0) {
+                       mutex_lock(&neuronspi_master_mutex);
+                       memcpy(&d_data->uart_buf[0], &recv_buf[10], recv_buf[7]);
+                       neuronspi_uart_handle_rx(n_port, recv_buf[7], 1);
+                       read_count = recv_buf[9];
+                       mutex_unlock(&neuronspi_master_mutex);
+               } else if (recv_buf[0] != 0x41) {
+                       mutex_lock(&neuronspi_master_mutex);
+                       d_data->uart_read = 0;
+                       end_flag = 1;
+                       mutex_unlock(&neuronspi_master_mutex);
+               }
+       }
+       kfree(recv_buf);
+       kfree(send_buf);
+}
+
+
+void neuronspi_uart_stop_tx(struct uart_port *port)
+{
+    // ToDo : create new opcode / coil?
+}
+
+void neuronspi_uart_stop_rx(struct uart_port *port)
+{
+    // ToDo : create new opcode / coil?
+}
+
+void neuronspi_uart_start_tx(struct uart_port *port)
+{
+       struct neuronspi_port *n_port = to_neuronspi_port(port,port);
+#if NEURONSPI_DETAILED_DEBUG > 0
+       printk(KERN_INFO "NEURONSPI: Start TX\n");
+#endif
+       kthread_queue_work(&n_port->parent->kworker, &n_port->tx_work);
+}
+
+s32 neuronspi_uart_poll(void *data)
+{
+       struct neuronspi_driver_data *d_data = (struct neuronspi_driver_data*) data;
+       struct neuronspi_uart_data *u_data;
+       s32 i;
+       while (!kthread_should_stop()) {
+               usleep_range(2000,8000);
+               if (d_data->uart_count) {
+                       u_data = d_data->uart_data;
+                       for (i = 0; i < u_data->p_count; i++) {
+                               if (u_data->p[i].dev_index == d_data->neuron_index) {
+                                       kthread_queue_work(&u_data->kworker, &u_data->p[i].irq_work);
+                               }
+                       }
+               }
+       }
+       return 0;
+}
index 06ec14864b51f77f68d24a12afb929be3b6be499..fcedc87056e5cf0596b4b7cf8ce264d7cb4d2474 100644 (file)
 #ifndef MODULES_NEURON_SPI_SRC_UNIPI_UART_H_
 #define MODULES_NEURON_SPI_SRC_UNIPI_UART_H_
 
+#include <linux/bitops.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/gpio.h>
+#include <linux/gpio/driver.h>
+#include <linux/i2c.h>
+#include <linux/iio/iio.h>
+#include <uapi/linux/iio/types.h>
+#include <linux/iio/sysfs.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/regmap.h>
+#include <linux/serial_core.h>
+#include <linux/serial.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/spi/spi.h>
+#include <linux/leds.h>
+#include <linux/uaccess.h>
+#include <asm/termbits.h>
+#include <asm/gpio.h>
 
+#include "unipi_common.h"
+#include "unipi_platform.h"
 
+void neuronspi_uart_start_tx(struct uart_port *port);
+void neuronspi_uart_stop_tx(struct uart_port *port);
+void neuronspi_uart_stop_rx(struct uart_port *port);
+void neuronspi_uart_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old);
+u32 neuronspi_uart_tx_empty(struct uart_port *port);
+void neuronspi_uart_break_ctl(struct uart_port *port, int break_state);
+void neuronspi_uart_shutdown(struct uart_port *port);
+s32 neuronspi_uart_startup(struct uart_port *port);
+s32 neuronspi_uart_request_port(struct uart_port *port);
+s32 neuronspi_uart_alloc_line(void);
+void neuronspi_uart_set_mctrl(struct uart_port *port, u32 mctrl);
+int    neuronspi_uart_ioctl (struct uart_port *port, unsigned int ioctl_code, unsigned long ioctl_arg);
+void neuronspi_uart_set_ldisc(struct uart_port *port, struct ktermios *kterm);
+u32 neuronspi_uart_get_mctrl(struct uart_port *port);
+const char *neuronspi_uart_type(struct uart_port *port);
+void neuronspi_uart_null_void(struct uart_port *port);
+void neuronspi_uart_config_port(struct uart_port *port, int flags);
+s32 neuronspi_uart_verify_port(struct uart_port *port, struct serial_struct *s);
+void neuronspi_uart_pm(struct uart_port *port, u32 state,  u32 oldstate);
+s32 neuronspi_uart_poll(void *data);
+s32 neuronspi_uart_probe(struct spi_device* dev, u8 device_index);
+s32 neuronspi_uart_remove(struct neuronspi_uart_data *u_data);
+void neuronspi_uart_power(struct uart_port *port, s32 on);
+s32 neuronspi_uart_config_rs485(struct uart_port *port, struct serial_rs485 *rs485);
+void neuronspi_spi_uart_set_cflag(struct spi_device* spi_dev, u8 port, u32 to);
+u32 neuronspi_spi_uart_get_cflag(struct spi_device* spi_dev, u8 port);
+void neuronspi_uart_fifo_write(struct neuronspi_port *port, u8 to_send);
+void neuronspi_uart_fifo_read(struct uart_port *port, u32 rxlen);
+void neuronspi_uart_rx_proc(struct kthread_work *ws);
+void neuronspi_uart_tx_proc(struct kthread_work *ws);
+void neuronspi_uart_ist(struct kthread_work *ws);
+void neuronspi_uart_handle_tx(struct neuronspi_port *port);
+void neuronspi_uart_handle_rx(struct neuronspi_port *port, u32 rxlen, u32 iir);
+void neuronspi_uart_handle_irq(struct neuronspi_uart_data *uart_data, u32 portno);
 
+static const struct uart_ops neuronspi_uart_ops =
+{
+       .tx_empty                       = neuronspi_uart_tx_empty,
+       .set_mctrl                      = neuronspi_uart_set_mctrl,
+       .get_mctrl                      = neuronspi_uart_get_mctrl,
+       .stop_tx                        = neuronspi_uart_stop_tx,
+       .start_tx                       = neuronspi_uart_start_tx,
+       .stop_rx                        = neuronspi_uart_stop_rx,
+       .break_ctl                      = neuronspi_uart_break_ctl,
+       .startup                        = neuronspi_uart_startup,
+       .shutdown                       = neuronspi_uart_shutdown,
+       .set_termios            = neuronspi_uart_set_termios,
+       .set_ldisc                      = neuronspi_uart_set_ldisc,
+       .type                           = neuronspi_uart_type,
+       .request_port           = neuronspi_uart_request_port,
+       .release_port           = neuronspi_uart_null_void,
+       .config_port            = neuronspi_uart_config_port,
+       .verify_port            = neuronspi_uart_verify_port,
+       .pm                                     = neuronspi_uart_pm,
+       .ioctl                          = neuronspi_uart_ioctl,
+};
 
 #endif /* MODULES_NEURON_SPI_SRC_UNIPI_UART_H_ */