changed neuronspi_spi_send_message to neuronspi_spi_send_op using structured buffers
authorMiroslav Ondra <ondra@faster.cz>
Tue, 28 Aug 2018 10:18:08 +0000 (12:18 +0200)
committerMiroslav Ondra <ondra@faster.cz>
Tue, 28 Aug 2018 10:18:08 +0000 (12:18 +0200)
buffers for spi_transfer are aligned (using unaligned buffers caused unexpected memory change)
support for crc calc in neuronspi_spi_send_op
changed uart behavior - checking tx queue, rx ordering
fixed regmap

modules/unipi/current [new file with mode: 0755]
modules/unipi/src/unipi_common.h
modules/unipi/src/unipi_gpio.c
modules/unipi/src/unipi_iio.c
modules/unipi/src/unipi_misc.c
modules/unipi/src/unipi_platform.c
modules/unipi/src/unipi_spi.c
modules/unipi/src/unipi_spi.h
modules/unipi/src/unipi_sysfs.c
modules/unipi/src/unipi_tty.c
modules/unipi/src/unipi_uart.c

diff --git a/modules/unipi/current b/modules/unipi/current
new file mode 100755 (executable)
index 0000000..2a3d334
--- /dev/null
@@ -0,0 +1,15 @@
+#!/bin/bash
+
+
+cd tmp
+. versions
+
+
+KERNEL_VER=`ls -1 h/lib/modules | grep '\-v7'`
+echo $KERNEL_VER
+cp h/usr/src/linux-headers-${KERNEL_VER}/.config linux-raspberrypi-kernel_${RPI_FIRMWARE_VER}
+cp h/usr/src/linux-headers-${KERNEL_VER}/Module.symvers linux-raspberrypi-kernel_${RPI_FIRMWARE_VER}
+cd linux-raspberrypi-kernel_${RPI_FIRMWARE_VER}
+make modules_prepare CROSS_COMPILE=arm-linux-gnueabi- ARCH=arm
+cd ../..
+make all CCPREFIX=arm-linux-gnueabi- ARCH=arm LINUX_DIR_PATH=tmp/linux-raspberrypi-kernel_${RPI_FIRMWARE_VER}
index bcfe71aac520776aaffe882feb087aff57ed312b..8c76cf2c35dca83b15c8b15b4c1251c83de0ba9b 100644 (file)
 #define NEURONSPI_BUFFER_MAX                   1152
 #define NEURONSPI_HEADER_LENGTH                10
 #define NEURONSPI_FIRST_MESSAGE_LENGTH 6
+#define NEURONSPI_FIRST_MESSAGE_ALLOC  8
 #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                  7500000
-#define NEURONSPI_MAX_TX                               62
+//#define NEURONSPI_MAX_TX                             62
+#define NEURONSPI_MAX_TX                               256
 #define NEURONSPI_MAX_BAUD                             115200
 #define NEURONSPI_FIFO_SIZE                            256
 #define NEURONSPI_FIFO_MIN_CONTINUOUS  50
-#define NEURONSPI_DETAILED_DEBUG               0
+#define NEURONSPI_DETAILED_DEBUG               1
 #define NEURONSPI_LAST_TRANSFER_DELAY  40
 
 #define NEURON_DEVICE_NAME                             "unipispi"
@@ -113,6 +115,13 @@ struct neuronspi_devtype
        s32     nr_uart;
 };
 
+
+struct neuronspi_op_buffer
+{
+    u8  first_message[8];
+    u8  *second_message;
+};
+
 struct neuronspi_port
 {
        struct uart_port                        port;
@@ -126,9 +135,10 @@ struct neuronspi_port
        struct neuronspi_uart_data      *parent;
        u8                                                      dev_index;
        u8                                                      dev_port;
-       u8                                                      parmrk_enabled;
-       u64                                                     parmrk_frame_delay;
+//     u8                                                      parmrk_enabled;
+//     u64                                                     parmrk_frame_delay;
        s32                                                     baud;
+    unsigned int                one_char_usec;
 };
 
 struct neuronspi_uart_data
@@ -178,10 +188,10 @@ struct neuronspi_driver_data
        char platform_name[sizeof("io_group0")];
        u32 probe_always_succeeds;
        u32 always_create_uart;
-       u8 *send_buf;
-       u8 *recv_buf;
+       //u8 *send_buf;
+       //u8 *recv_buf;
        u8 *first_probe_reply;
-       u8 *second_probe_reply;
+       //u8 *second_probe_reply;
        u8 reserved_device;
        u8 uart_count;
        u8 uart_read;
@@ -260,9 +270,13 @@ struct neuronspi_file_data
 {
        struct spi_device** spi_device;
        struct mutex            lock;
-       u8                                      *send_buf;
-       u8                                      *recv_buf;
-       u32                     message_len;
+       //u8                                    *send_buf;
+       //u8                                    *recv_buf;
+    struct neuronspi_op_buffer send_buf;
+    struct neuronspi_op_buffer recv_buf;
+       u32                             message_len;
+       u8                                      device_index;
+       u8                                      has_first_message;
 };
 
 struct neuronspi_direct_acc
@@ -283,4 +297,6 @@ extern struct task_struct *neuronspi_invalidate_thread;
 
 extern int neuronspi_model_id;
 
+#define NEURON_FIRMWARE_VERSION(neuronspi_driver_data) (*(uint16_t*) (neuronspi_driver_data->first_probe_reply+4))
+
 #endif /* MODULES_NEURON_SPI_SRC_UNIPI_COMMON_H_ */
index e53ed706f3f504a6ea8dba61d10adade461cee21..3cfab5bf47792a2d02a9ccaa5b1647b4949a2dcd 100644 (file)
  * Non-static Functions *
  ************************/
 
+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_ATOMIC);
+       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);
+       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);
+       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);
+       return ret;
+}
+
+
 int neuronspi_gpio_di_direction_input(struct gpio_chip *chip, unsigned offset) {
        return 0;
 }
index fc4d39b5e49b4e5bb38eb536904af2e9fca2aa4a..a22cee37f29c5656f0eb38002f0e4613c6f2e82b 100644 (file)
 /************************
  * Non-static Functions *
  ************************/
+/*
+ * NOTE: This function uses 64-bit fixed-point arithmetic,
+ * which necessitates using the do_div macro to avoid unnecessary long/long division.
+ */
+void neuronspi_spi_iio_sec_ai_read_voltage(struct iio_dev *indio_dev, struct iio_chan_spec const *ch, int *val, int *val2, long mask)
+{
+       struct neuronspi_analog_data *ai_data = iio_priv(indio_dev);
+       struct spi_device *spi = ai_data->parent;
+       struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi);
+       u32 sec_ai_val_l = 0;
+       u32 sec_ai_val_h = 0;
+       u32 sec_ai_val_m = 0;
+       u8 sec_ai_exp = 0;
+       regmap_read(n_spi->reg_map, n_spi->regstart_table->sec_ai_val_reg + 1 + (2 * ai_data->index), &sec_ai_val_h);
+       regmap_read(n_spi->reg_map, n_spi->regstart_table->sec_ai_val_reg + (2 * ai_data->index), &sec_ai_val_l);
+       sec_ai_val_m = ((((u32)sec_ai_val_h) << 25) | (((u32)sec_ai_val_l) << 9)) >> 16;
+       sec_ai_exp = (sec_ai_val_h & 0x7F80) >> 7;
+
+       *val = sec_ai_val_m | 0x00010000;
+       if (142 - ((int)sec_ai_exp) <= 0) {
+               *val = (*val << (((int)sec_ai_exp) - 142)) * 1000;
+               *val2 = 1;
+       } else {
+               *val = *val * 1000;
+               *val2 = 2 << (142 - sec_ai_exp);
+       }
+
+}
+
+void neuronspi_spi_iio_sec_ai_read_current(struct iio_dev *indio_dev, struct iio_chan_spec const *ch, int *val, int *val2, long mask)
+{
+       struct neuronspi_analog_data *ai_data = iio_priv(indio_dev);
+       struct spi_device *spi = ai_data->parent;
+       struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi);
+       u32 sec_ai_val_l = 0;
+       u32 sec_ai_val_h = 0;
+       u32 sec_ai_val_m = 0;
+       u8 sec_ai_exp = 0;
+
+       regmap_read(n_spi->reg_map, n_spi->regstart_table->sec_ai_val_reg + 1 + (2 * ai_data->index), &sec_ai_val_h);
+       regmap_read(n_spi->reg_map, n_spi->regstart_table->sec_ai_val_reg + (2 * ai_data->index), &sec_ai_val_l);
+       sec_ai_val_m = ((((u32)sec_ai_val_h) << 25) | (((u32)sec_ai_val_l) << 9)) >> 16;
+       sec_ai_exp = (sec_ai_val_h & 0x7F80) >> 7;
+       *val = sec_ai_val_m | 0x00010000;
+       if (142 - ((int)sec_ai_exp) <= 0) {
+               *val2 = 1;
+               *val = *val << (((int)sec_ai_exp) - 142);
+       } else {
+               *val2 = 2 << (142 - sec_ai_exp);
+       }
+}
+
+void neuronspi_spi_iio_sec_ai_read_resistance(struct iio_dev *indio_dev, struct iio_chan_spec const *ch, int *val, int *val2, long mask)
+{
+       struct neuronspi_analog_data *ai_data = iio_priv(indio_dev);
+       struct spi_device *spi = ai_data->parent;
+       struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi);
+       u32 sec_ai_val_l = 0;
+       u32 sec_ai_val_h = 0;
+       u32 sec_ai_val_m = 0;
+       u8 sec_ai_exp = 0;
+       regmap_read(n_spi->reg_map, n_spi->regstart_table->sec_ai_val_reg + 1 + (2 * ai_data->index), &sec_ai_val_h);
+       regmap_read(n_spi->reg_map, n_spi->regstart_table->sec_ai_val_reg + (2 * ai_data->index), &sec_ai_val_l);
+       sec_ai_val_m = ((((u32)sec_ai_val_h) << 25) | (((u32)sec_ai_val_l) << 9)) >> 16;
+       sec_ai_exp = (sec_ai_val_h & 0x7F80) >> 7;
+       *val = sec_ai_val_m | 0x00010000;
+       if (142 - ((int)sec_ai_exp) <= 0) {
+               *val2 = 1;
+               *val = *val << (((int)sec_ai_exp) - 142);
+       } else {
+               *val2 = 2 << (142 - sec_ai_exp);
+       }
+}
+
+void neuronspi_spi_iio_sec_ao_set_voltage(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int val, int val2, long mask)
+{
+       struct neuronspi_analog_data *ao_data = iio_priv(indio_dev);
+       struct spi_device *spi = ao_data->parent;
+       struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi);
+       u32 sec_true_val;
+       if (val > 10000) val = 10000;
+       sec_true_val = (val * 2) / 5;
+       regmap_write(n_spi->reg_map, n_spi->regstart_table->sec_ao_val_reg + ao_data->index, sec_true_val);
+}
+
+/*
+ * NOTE: This function uses 64-bit fixed-point arithmetic,
+ * which necessitates using the do_div macro to avoid unnecessary long/long division.
+ */
+void neuronspi_spi_iio_stm_ai_read_voltage(struct iio_dev *iio_dev, struct iio_chan_spec const *ch, int *val, int *val2, long mask)
+{
+       struct neuronspi_analog_data *ai_data = iio_priv(iio_dev);
+       struct spi_device *spi = ai_data->parent;
+       struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi);
+       u32 stm_ai_val = 0;
+       u32 stm_v_int_ref = 0;
+       u32 stm_v_inp_ref = 0;
+       u32 stm_v_err = 0;
+       u32 stm_v_off = 0;
+       u64 stm_true_val = 0;
+       u64 stm_true_ref = 0;
+       regmap_read(n_spi->reg_map, n_spi->regstart_table->stm_ai_val_reg, &stm_ai_val);
+       regmap_read(n_spi->reg_map, n_spi->regstart_table->vref_int, &stm_v_int_ref);
+       regmap_read(n_spi->reg_map, n_spi->regstart_table->vref_inp, &stm_v_inp_ref);
+       regmap_read(n_spi->reg_map, n_spi->regstart_table->stm_ai_vol_err, &stm_v_err);
+       regmap_read(n_spi->reg_map, n_spi->regstart_table->stm_ai_vol_off, &stm_v_off);
+       stm_true_ref = ((u64)stm_v_int_ref) * 99000;
+       stm_v_inp_ref = stm_v_inp_ref * 10000;
+       stm_true_val = stm_true_ref * ((u64)(stm_ai_val * 1000));
+       do_div(stm_true_val, stm_v_inp_ref);
+       do_div(stm_true_val, 4096);
+       stm_true_val *= (10000 + stm_v_err);
+       stm_true_val += stm_v_off;
+       do_div(stm_true_val, 10000);
+       *val = stm_true_val;
+}
+
+void neuronspi_spi_iio_stm_ai_read_current(struct iio_dev *indio_dev, struct iio_chan_spec const *ch, int *val, int *val2, long mask)
+{
+       struct neuronspi_analog_data *ai_data = iio_priv(indio_dev);
+       struct spi_device *spi = ai_data->parent;
+       struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi);
+       u32 stm_ai_val = 0;
+       u32 stm_v_int_ref = 0;
+       u32 stm_v_inp_ref = 0;
+       u32 stm_i_err = 0;
+       u32 stm_i_off = 0;
+       u64 stm_true_val = 0;
+       u64 stm_true_ref = 0;
+       regmap_read(n_spi->reg_map, n_spi->regstart_table->stm_ai_val_reg, &stm_ai_val);
+       regmap_read(n_spi->reg_map, n_spi->regstart_table->vref_int, &stm_v_int_ref);
+       regmap_read(n_spi->reg_map, n_spi->regstart_table->vref_inp, &stm_v_inp_ref);
+       regmap_read(n_spi->reg_map, n_spi->regstart_table->stm_ai_curr_err, &stm_i_err);
+       regmap_read(n_spi->reg_map, n_spi->regstart_table->stm_ai_curr_off, &stm_i_off);
+       stm_true_ref = ((u64)stm_v_int_ref) * 330000;
+       stm_v_inp_ref = stm_v_inp_ref * 10000;
+       stm_true_val = stm_true_ref * ((u64)(stm_ai_val * 1000));
+       do_div(stm_true_val, stm_v_inp_ref);
+       do_div(stm_true_val, 4096);
+       stm_true_val *= (10000 + stm_i_err);
+       stm_true_val += stm_i_off;
+       do_div(stm_true_val, 10000);
+       *val = stm_true_val;
+       *val2 = 1000;
+}
+
+void neuronspi_spi_iio_stm_ao_read_resistance(struct iio_dev *indio_dev, struct iio_chan_spec const *ch, int *val, int *val2, long mask)
+{
+       struct neuronspi_analog_data *ao_data = iio_priv(indio_dev);
+       struct spi_device *spi = ao_data->parent;
+       struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi);
+       u32 stm_aio_val = 0;
+       regmap_read(n_spi->reg_map, n_spi->regstart_table->stm_aio_val_reg, &stm_aio_val);
+       *val = stm_aio_val;
+       *val2 = 10;
+}
+
+
+void neuronspi_spi_iio_stm_ao_set_voltage(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int val, int val2, long mask)
+{
+       struct neuronspi_analog_data *ao_data = iio_priv(indio_dev);
+       struct spi_device *spi = ao_data->parent;
+       struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi);
+       u32 stm_v_int_ref = 0;
+       u32 stm_v_inp_ref = 0;
+       u32 stm_v_err = 0;
+       u32 stm_v_off = 0;
+       u64 stm_true_val = val;
+       u64 stm_true_val_fraction = val2 / 100;
+       u64 stm_true_ref = 0;
+       regmap_read(n_spi->reg_map, n_spi->regstart_table->vref_int, &stm_v_int_ref);
+       regmap_read(n_spi->reg_map, n_spi->regstart_table->vref_inp, &stm_v_inp_ref);
+       regmap_read(n_spi->reg_map, n_spi->regstart_table->stm_ao_vol_err, &stm_v_err);
+       regmap_read(n_spi->reg_map, n_spi->regstart_table->stm_ao_vol_off, &stm_v_off);
+       stm_true_ref = ((u64)stm_v_int_ref) * (99000 + stm_v_err) * 1000;
+       stm_v_inp_ref = stm_v_inp_ref * 10000;
+       stm_true_val = ((stm_true_val * 10000) + (stm_true_val_fraction) - stm_v_off) * 4095;
+       do_div(stm_true_ref, stm_v_inp_ref);
+       stm_v_inp_ref = stm_true_ref;
+       do_div(stm_true_val, stm_v_inp_ref);
+       do_div(stm_true_val, 10000);
+       if (stm_true_val > 4095) stm_true_val = 4095;
+       regmap_write(n_spi->reg_map, n_spi->regstart_table->stm_ao_val_reg, (unsigned int) stm_true_val);
+}
+
+void neuronspi_spi_iio_stm_ao_set_current(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int val, int val2, long mask)
+{
+       struct neuronspi_analog_data *ao_data = iio_priv(indio_dev);
+       struct spi_device *spi = ao_data->parent;
+       struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi);
+       u32 stm_v_int_ref = 0;
+       u32 stm_v_inp_ref = 0;
+       u32 stm_i_err = 0;
+       u32 stm_i_off = 0;
+       u64 stm_true_val = val;
+       u64 stm_true_val_fraction = val2 / 100;
+       u64 stm_true_ref = 0;
+       regmap_read(n_spi->reg_map, n_spi->regstart_table->vref_int, &stm_v_int_ref);
+       regmap_read(n_spi->reg_map, n_spi->regstart_table->vref_inp, &stm_v_inp_ref);
+       regmap_read(n_spi->reg_map, n_spi->regstart_table->stm_ao_curr_err, &stm_i_err);
+       regmap_read(n_spi->reg_map, n_spi->regstart_table->stm_ao_curr_off, &stm_i_off);
+       stm_true_ref = ((u64)stm_v_int_ref) * (330000 + stm_i_err) * 100;
+       stm_v_inp_ref = stm_v_inp_ref * 1000;
+       stm_true_val = (((stm_true_val * 10000) + (stm_true_val_fraction)) - stm_i_off) * 4095;
+       do_div(stm_true_ref, stm_v_inp_ref);
+       stm_v_inp_ref = stm_true_ref;
+       do_div(stm_true_val, stm_v_inp_ref);
+       do_div(stm_true_val, 10);
+       if (stm_true_val > 4095) stm_true_val = 4095;
+       regmap_write(n_spi->reg_map, n_spi->regstart_table->stm_ao_val_reg, (unsigned int)stm_true_val);
+}
 
 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_analog_data *ai_data = iio_priv(indio_dev);
index 3b6ac08cb6738b63b950d9a1253a6b6982411bc2..016871256e53559f9ced6c880e49b2f2e2549540 100644 (file)
  * Non-static Functions *
  ************************/
 
+void neuronspi_spi_led_set_brightness(struct spi_device* spi_dev, enum led_brightness brightness, int id)
+{
+       struct neuronspi_driver_data *d_data = spi_get_drvdata(spi_dev);
+        u16 coil;
+#if NEURONSPI_DETAILED_DEBUG > 0
+       printk(KERN_INFO "UNIPISPI: SPI LED Set, Dev-CS:%d, led id:%d\n", spi_dev->chip_select, id);
+#endif
+
+       if (d_data->features != NULL) {
+               coil = d_data->features->di_count + d_data->features->do_count + d_data->features->ro_count + id;
+       } else {
+               coil = 8 + id;
+       }
+    unipispi_modbus_write_coil(spi_dev, coil, brightness > 0);
+}
+
+
 void neuronspi_led_proc(struct kthread_work *ws)
 {
        struct neuronspi_led_driver *led = to_led_driver(ws, led_work);
index 0486ffe6c318726156bf4b3387b51a3b132bea36..ce1fc0dd900288218bcb707714d78021a8505899 100644 (file)
@@ -1735,12 +1735,20 @@ void neuronspi_regmap_invalidate_device(struct regmap *reg_map, struct neuronspi
 int neuronspi_regmap_hw_reg_read(void *context, unsigned int reg, unsigned int *val)
 {
        struct spi_device *spi = context;
+
+    u16 value;
+    if (unipispi_modbus_read_register(spi, reg, &value) == 0) {
+        *val = value;
+    } else {
+        *val = 0;
+    }
+/*    
        struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi);
        u8 *inp_buf;
        u8 *outp_buf;
        int write_length, i;
        write_length = neuronspi_spi_compose_single_register_read(reg, &inp_buf, &outp_buf);
-       if (neuronspi_spi_send_message(spi, inp_buf, outp_buf, write_length, n_spi->ideal_frequency, 25, 1, 0)) {
+       if (neuronspi___spi_send_message(spi, inp_buf, outp_buf, write_length, n_spi->ideal_frequency, 25, 1, 0)) {
                for (i = 0; i < write_length; i++) {
                        outp_buf[i] = 0;
                }
@@ -1748,24 +1756,32 @@ int neuronspi_regmap_hw_reg_read(void *context, unsigned int reg, unsigned int *
        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);
+       BUG_ON(count < 2);
+       //return neuronspi_regmap_hw_gather_write(context, data, 1, data + 1, count - 1);
+       return neuronspi_regmap_hw_gather_write(context, data, sizeof(u16), data + sizeof(u16), count - sizeof(u16));
 }
 
 int neuronspi_regmap_hw_reg_write(void *context, unsigned int reg, unsigned int val)
 {
        struct spi_device *spi = context;
+
+    if (unipispi_modbus_write_register(spi, reg, val) == 0) {
+        return 0;
+    }
+    return 0; // ???
+/*    
        struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi);
        u8 *inp_buf;
        u8 *outp_buf;
        int write_length, i;
        write_length = neuronspi_spi_compose_single_register_write(reg, &inp_buf, &outp_buf, (val >> 8));
-       if (neuronspi_spi_send_message(spi, inp_buf, outp_buf, write_length, n_spi->ideal_frequency, 25, 1, 0)) {
+       if (neuronspi___spi_send_message(spi, inp_buf, outp_buf, write_length, n_spi->ideal_frequency, 25, 1, 0)) {
                memcpy(&val, &outp_buf[NEURONSPI_HEADER_LENGTH], sizeof(u16));
                for (i = 0; i < write_length; i++) {
                        outp_buf[i] = 0;
@@ -1774,29 +1790,42 @@ int neuronspi_regmap_hw_reg_write(void *context, unsigned int reg, unsigned int
        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;
+       //u16 *mb_val_buf = (u16*)val;
        struct spi_device *spi = context;
+
+       printk(KERN_INFO "UNIPISPI: Regmap_hw_gather_write reg[%d](%d) val(%d):%8ph\n", *mb_reg_buf, reg_size, val_size, val);
+    
+       if (reg_size == sizeof(u16)) {
+               return unipispi_modbus_write_register(spi, mb_reg_buf[0], *((u16*)val));
+       }
+       if (reg_size == sizeof(u32)) {
+               return unipispi_modbus_write_u32(spi, mb_reg_buf[0], *((u32*)val));
+       }
+    
+    if (val_size & 1) return 0; // val_size must be even (u16)
+    return unipispi_modbus_write_many(spi, mb_reg_buf[0], (u16*)val, val_size / sizeof(u16));
+
+/*
        struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi);
        u8 *inp_buf;
        u8 *outp_buf;
        int i, write_length;
        int block_counter = 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]));
+                       //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, 0);
+                               neuronspi___spi_send_message(spi, inp_buf, outp_buf, write_length, n_spi->ideal_frequency, 125, 1, 0);
                                block_counter = 0;
                                kfree(inp_buf);
                                kfree(outp_buf);
@@ -1805,7 +1834,7 @@ int neuronspi_regmap_hw_gather_write(void *context, const void *reg, size_t reg_
                        }
                }
        }
-       return 0;
+       return 0;*/
 }
 
 int neuronspi_create_reg_starts(struct neuronspi_board_regstart_table *out_table, struct neuronspi_board_combination *board) {
@@ -1897,18 +1926,31 @@ s32 neuronspi_find_reg_start(struct neuronspi_board_combination *board, u16 regf
 
 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;
+       //u16 *mb_val_buf = val_buf;
+       struct spi_device *spi = context;
+       if (context == NULL) {
+               return 0;
+       }
+       printk(KERN_INFO "UNIPISPI: Regmap_hw_read reg[%d](%dB) val(%dB):%8ph\n", *mb_reg_buf, reg_size, val_size, val_buf);
+
+    if (val_size == sizeof(u16)) {
+        return unipispi_modbus_read_register(spi, *mb_reg_buf, (u16*) val_buf);
+    }
+    if (val_size == sizeof(u32)) {
+        return unipispi_modbus_read_u32(spi, *mb_reg_buf, (u32*) val_buf);
+    }
+
+    if (val_size & 1) return 0; // val_size must be even (u16)
+    
+    return unipispi_modbus_read_many(spi, *mb_reg_buf, (u16*) val_buf, val_size / (sizeof(u16)));
+
+/*
        struct neuronspi_driver_data *n_spi;
        u8 *inp_buf;
        u8 *outp_buf;
        int i, j, write_length;
        int block_counter = 0;
-       if (context == NULL) {
-               return 0;
-       }
-       spi = context;
-       n_spi = spi_get_drvdata(spi);
+    n_spi = spi_get_drvdata(spi);
        if (n_spi == NULL) {
                return 0;
        }
@@ -1916,7 +1958,7 @@ int neuronspi_regmap_hw_read(void *context, const void *reg_buf, size_t reg_size
                // 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);
-                       if (neuronspi_spi_send_message(spi, inp_buf, outp_buf, write_length, n_spi->ideal_frequency, 125, 1, 0)) {
+                       if (neuronspi___spi_send_message(spi, inp_buf, outp_buf, write_length, n_spi->ideal_frequency, 125, 1, 0)) {
                                for (j = 0; j < write_length; j++) {
                                        outp_buf[j] = 0;
                                }
@@ -1929,7 +1971,7 @@ int neuronspi_regmap_hw_read(void *context, const void *reg_buf, size_t reg_size
                        block_counter++;
                }
        }
-       return 0;
+       return 0; */
 }
 
 s32 neuronspi_find_model_id(u32 probe_count)
index 592bfbd50441df28dfb14d8d1abaa709988fa830..04f893c4f390d6a01450c1cf1dfb2c862b5071f8 100644 (file)
 #include "unipi_spi.h"
 #include "unipi_tty.h"
 
+/* using trace_printk or printk ???*/
+
+#if NEURONSPI_DETAILED_DEBUG > 1
+# define unipi_spi_trace_1(f, args...) printk(f, ##args)
+#else
+# define unipi_spi_trace_1(f, args...)
+#endif
+
+#if NEURONSPI_DETAILED_DEBUG > 0
+# define unipi_spi_trace(f, args...)   printk(f, ##args)
+#else
+# define unipi_spi_trace(f, args...)
+#endif
+
+
 /********************
  * Data Definitions *
  ********************/
@@ -60,14 +75,11 @@ struct neuronspi_char_driver neuronspi_cdrv =
 };
 
 struct mutex neuronspi_master_mutex;
-struct mutex neuronspi_uart_mutex;
 struct mutex unipi_inv_speed_mutex;
-struct spinlock *neuronspi_spi_w_spinlock;
 int neuronspi_model_id = -1;
 struct spi_device *neuronspi_s_dev[NEURONSPI_MAX_DEVS];
 struct task_struct *neuronspi_invalidate_thread;
 
-static u8 neuronspi_spi_w_flag = 1;
 static u8 neuronspi_probe_count = 0;
 static struct spinlock *neuronspi_probe_spinlock;
 static struct sched_param neuronspi_sched_param = { .sched_priority = MAX_RT_PRIO / 2 };
@@ -75,7 +87,198 @@ static struct sched_param neuronspi_sched_param = { .sched_priority = MAX_RT_PRI
 /************************
  * Non-static Functions *
  ************************/
+int _neuronspi_spi_send_op(struct spi_device* spi_dev, s32 trans_count, const struct neuronspi_op_buffer* send_buf,
+                            struct neuronspi_op_buffer* recv_buf, s32 len, 
+                            s32 freq, s32 delay, s32 send_header, u8 lock_val, u16 crc2);
+
+
+int neuronspi_spi_send_const_op(struct spi_device* spi_dev, const struct neuronspi_op_buffer* send_buf,
+                            struct neuronspi_op_buffer* recv_buf, s32 len, 
+                            s32 freq, s32 delay)
+{
+       s32 trans_count = (len-1) / NEURONSPI_MAX_TX + 3; // number of transmissions
+    return _neuronspi_spi_send_op(spi_dev,trans_count, send_buf,recv_buf,len,freq, delay, UNIPISPI_OP_MODE_SEND_HEADER, 0, 0);
+}
+
+
+/*
+ *  send_header: bits of UNIPISPI_OP_MODE_SEND_HEADER | UNIPISPI_OP_MODE_DO_CRC | UNIPISPI_OP_MODE_HAVE_CRC_SPACE
+ *  len:         length of second message. If DO_CRC is not set, len includes crc
+ *  buffers:     must be long enough if HAVE_CRC_SPACE is set  
+ *  returns:     0 if success
+ */
+int neuronspi_spi_send_op(struct spi_device* spi_dev, struct neuronspi_op_buffer* send_buf, struct neuronspi_op_buffer* recv_buf, s32 len, 
+                          s32 freq, s32 delay, s32 send_header, u8 lock_val)
+{
+       u16 packet_crc = 0;
+       s32 trans_count = 2; // number of transmissions
+
+    if (send_header & UNIPISPI_OP_MODE_SEND_HEADER) {
+               unipi_spi_trace_1(KERN_INFO "UNIPISPI: SPI Master Write(op1) %8ph\n", send_buf->first_message);
+        if (send_header & UNIPISPI_OP_MODE_DO_CRC) {
+            packet_crc = neuronspi_spi_crc(send_buf->first_message, 4, 0);
+            *((u16*)(send_buf->first_message+4)) = packet_crc;
+        }
+    }
+
+    if (len > 0) {
+        if (send_header & UNIPISPI_OP_MODE_DO_CRC) {
+            packet_crc = neuronspi_spi_crc(send_buf->second_message, len, packet_crc);
+            if (send_header & UNIPISPI_OP_MODE_HAVE_CRC_SPACE) {
+                // crc can be placed into data buffer
+                send_buf->second_message[len] = packet_crc & 0xff;
+                send_buf->second_message[len+1] = packet_crc >> 8;
+                len += 2;
+            } else {
+                // crc needs own buffer and own chunk
+                //crc_send_buf[0] = packet_crc;
+                trans_count++;
+            }
+        }
+               trans_count += (len-1) / NEURONSPI_MAX_TX + 1;
+               unipi_spi_trace_1(KERN_INFO "UNIPISPI: SPI Master Write(%3d) %32ph\n", len, send_buf->second_message);
+    }
+    return _neuronspi_spi_send_op(spi_dev,trans_count, send_buf,recv_buf,len,freq, delay, send_header, lock_val, packet_crc);
+}
+
+int _neuronspi_spi_send_op(struct spi_device* spi_dev, s32 trans_count, const struct neuronspi_op_buffer* send_buf,
+                            struct neuronspi_op_buffer* recv_buf, s32 len, 
+                            s32 freq, s32 delay, s32 send_header, u8 lock_val, u16 crc2)
+{
+       s32 i = 0;
+    s32 remain;
+       int ret_code = 0;
+       u16 recv_crc1 = 0;
+       u16 recv_crc2;
+       u16 packet_crc;
+    u16 crc_send_buf[2];
+    u16 crc_recv_buf[2];
+
+       struct neuronspi_driver_data *d_data;
+    struct spi_transfer* s_trans;
+
+       mutex_lock(&neuronspi_master_mutex);
+    d_data = spi_get_drvdata(spi_dev);
+
+    // Check if there are running reserved operations
+       if (d_data != NULL && d_data->reserved_device && lock_val != d_data->reserved_device) {
+               recv_buf->first_message[0] = 0;
+        if ((len > 0) && (recv_buf->second_message)) recv_buf->second_message[0] = 0;
+        mutex_unlock(&neuronspi_master_mutex);
+        return -1; // blocked by reservation
+       }
+
+       s_trans = kzalloc(sizeof(struct spi_transfer) * trans_count, GFP_ATOMIC);
+       s_trans[0].delay_usecs = NEURONSPI_EDGE_DELAY;
+       s_trans[0].bits_per_word = 8;
+       s_trans[0].speed_hz = freq;
+
+       s_trans[1].bits_per_word = 8;
+       s_trans[1].speed_hz = freq;
+    if (send_header) {
+        s_trans[1].delay_usecs = delay;
+        s_trans[1].len = NEURONSPI_FIRST_MESSAGE_LENGTH;
+        s_trans[1].tx_buf = send_buf->first_message;
+        s_trans[1].rx_buf = recv_buf->first_message;
+    }
+    if (len > 0) {
+               remain = len;
+               for (i = 2; i < trans_count; i++) {
+                       memset(&(s_trans[i]), 0, sizeof(s_trans[i]));
+                       s_trans[i].delay_usecs = 0;
+                       s_trans[i].bits_per_word = 8;
+                       s_trans[i].speed_hz = freq;
+                       s_trans[i].tx_buf = send_buf->second_message + (NEURONSPI_MAX_TX * (i - 2));
+                       s_trans[i].rx_buf = recv_buf->second_message + (NEURONSPI_MAX_TX * (i - 2));
+                       s_trans[i].len = (remain > NEURONSPI_MAX_TX) ? NEURONSPI_MAX_TX : remain;
+                       remain -= NEURONSPI_MAX_TX;
+               }
+        // corrent last chunk 
+        s_trans[trans_count-1].delay_usecs = NEURONSPI_LAST_TRANSFER_DELAY;
+        if ((send_header & (UNIPISPI_OP_MODE_HAVE_CRC_SPACE | UNIPISPI_OP_MODE_DO_CRC)) == (UNIPISPI_OP_MODE_DO_CRC)) {
+            // crc2 is placed into own chunk
+            crc_recv_buf[0] = crc2;
+                       s_trans[trans_count-1].tx_buf = crc_send_buf;
+                       s_trans[trans_count-1].rx_buf = crc_recv_buf;
+                       s_trans[trans_count-1].len = 2;
+        } else {
+            // crc is in part of data chunk
+            // len is size of second message WITHOUT crc
+            len -= 2;
+        }
+       }
+
+    // Call SPI transaction
+       spi_sync_transfer(spi_dev, s_trans, trans_count);
+       kfree(s_trans);
+
+    if (send_header & UNIPISPI_OP_MODE_SEND_HEADER) {
+        unipi_spi_trace_1(KERN_INFO "UNIPISPI: SPI Master Read (op1) %8ph\n", recv_buf->first_message);
+    }
 
+    // skip next processing if reserved operation is running
+    if (send_header & UNIPISPI_OP_MODE_SEND_HEADER) {
+               recv_crc1 = neuronspi_spi_crc(recv_buf->first_message, 4, 0);
+               packet_crc = *((u16*)(recv_buf->first_message+4));
+
+               if (recv_crc1 == packet_crc) {
+            unipi_spi_trace_1(KERN_INFO "UNIPISPI: SPI CRC1 Correct (=%04x)", packet_crc);
+
+            if (d_data != NULL && !d_data->reserved_device && ((recv_buf->first_message[0] & 0xfd) == 0x41)) {
+                // Signal the UART to issue character reads
+                               unipi_spi_trace(KERN_INFO "UNIPISPI: Reading UART data for device %d\n", d_data->neuron_index);
+
+                           if (recv_buf->first_message[0] == 0x41) {
+                    // read one incomming character from UART
+                                       d_data->uart_buf[0] = recv_buf->first_message[3];
+                                       for (i = 0; i < d_data->uart_data->p_count; i++) {
+                                               if (d_data->uart_data->p[i].dev_index == d_data->neuron_index) {
+                                                       neuronspi_uart_handle_rx(&d_data->uart_data->p[i], 1, 1);
+                                               }
+                                       }
+                               }
+                               if (!(d_data->uart_read) && (d_data->uart_count)) {
+                    // read queue length
+                                       d_data->uart_read = recv_buf->first_message[2];
+                                       for (i = 0; i < d_data->uart_data->p_count; i++) {
+                        unipi_spi_trace(KERN_INFO "UNIPISPI: UART Buffer:%d, UART Local Port Count:%d, UART Global Port Count:%d\n", d_data->uart_read,
+                                                       d_data->uart_count,  d_data->uart_data->p_count);
+                                               if (d_data->uart_data->p[i].dev_index == d_data->neuron_index && !d_data->reserved_device) {
+                                                       kthread_queue_work(&d_data->uart_data->kworker, &d_data->uart_data->p[i].rx_work);
+                                               }
+                                       }
+                               }
+                       }
+               } else {
+            recv_buf->first_message[0] = 0;
+                       unipi_spi_trace(KERN_INFO "UNIPISPI: SPI CRC1 Not Correct (Received: %04x Calculated: %04x)\n", packet_crc, recv_crc1);
+               }
+    }
+    if (len > 0) {
+        // Check second message crc
+               recv_crc2 = neuronspi_spi_crc(recv_buf->second_message, len, recv_crc1);
+        if ((send_header & (UNIPISPI_OP_MODE_HAVE_CRC_SPACE | UNIPISPI_OP_MODE_DO_CRC)) == (UNIPISPI_OP_MODE_DO_CRC)) {
+            packet_crc = crc_recv_buf[0];
+        } else {
+            packet_crc = recv_buf->second_message[len] | (recv_buf->second_message[len+1] << 8);
+        }
+               unipi_spi_trace_1(KERN_INFO "UNIPISPI: SPI Master Read - %d:\n\t%100ph\n\t%100ph\n\t%100ph\n\t%100ph\n", len, recv_buf->second_message, &recv_buf->second_message[64],
+                                        &recv_buf->second_message[128], &recv_buf->second_message[192]);
+
+               if (recv_crc2 != packet_crc) {
+            unipi_spi_trace_1(KERN_INFO "UNIPISPI: SPI CRC2 Not Correct: %04x COMPUTED: %04x\n", packet_crc, recv_crc2);
+            if (send_header & UNIPISPI_OP_MODE_SEND_HEADER) 
+                recv_buf->second_message[0] = 0;
+            ret_code = 1;
+               }
+    }
+    mutex_unlock(&neuronspi_master_mutex);
+    return ret_code;
+}
+
+/*****************************************************************
+ *  Modbus like Interface via /dev/unipispi 
+ */
 int neuronspi_open (struct inode *inode_p, struct file *file_p)
 {
        struct neuronspi_file_data *f_internal_data;
@@ -84,8 +287,8 @@ int neuronspi_open (struct inode *inode_p, struct file *file_p)
        }
        neuronspi_cdrv.open_counter += 1;
        f_internal_data = kzalloc(sizeof(*f_internal_data), GFP_ATOMIC);
-       f_internal_data->recv_buf = kzalloc(NEURONSPI_BUFFER_MAX, GFP_ATOMIC);
-       f_internal_data->send_buf = kzalloc(NEURONSPI_BUFFER_MAX, GFP_ATOMIC);
+       f_internal_data->recv_buf.second_message = kzalloc(NEURONSPI_BUFFER_MAX, GFP_ATOMIC);
+       f_internal_data->send_buf.second_message = kzalloc(NEURONSPI_BUFFER_MAX, GFP_ATOMIC);
        f_internal_data->spi_device = neuronspi_s_dev;
        mutex_init(&f_internal_data->lock);
        file_p->private_data = f_internal_data;
@@ -100,10 +303,10 @@ int neuronspi_release (struct inode *inode_p, struct file *file_p)
        }
        f_internal_data = (struct neuronspi_file_data*)file_p->private_data;
        f_internal_data->spi_device = NULL;
-       kfree(f_internal_data->recv_buf);
-       f_internal_data->recv_buf = NULL;
-       kfree(f_internal_data->send_buf);
-       f_internal_data->send_buf = NULL;
+       kfree(f_internal_data->recv_buf.second_message);
+       f_internal_data->recv_buf.second_message = NULL;
+       kfree(f_internal_data->send_buf.second_message);
+       f_internal_data->send_buf.second_message = NULL;
        kfree(f_internal_data);
        file_p->private_data = NULL;
        neuronspi_cdrv.open_counter -= 1;
@@ -114,7 +317,7 @@ ssize_t neuronspi_read (struct file *file_p, char *buffer, size_t len, loff_t *o
 {
 
        s32 result = 0;
-       u8 device_index = 0;
+    loff_t dummy_offset = 0;
        struct neuronspi_file_data* private_data;
        struct spi_device* spi_driver_data;
        struct neuronspi_driver_data* driver_data;
@@ -126,59 +329,64 @@ ssize_t neuronspi_read (struct file *file_p, char *buffer, size_t len, loff_t *o
     if (len == 0) return result; // Empty read
     if (len > 4095) return -EMSGSIZE;
     if (file_p == NULL) {
-       printk(KERN_DEBUG "UNIPISPI: File Pointer is NULL\n");
+       printk(KERN_DEBUG "UNIPISPI: CDEV File Pointer is NULL\n");
        return -8;
     }
     if (file_p->private_data == NULL) {
-       printk(KERN_DEBUG "UNIPISPI: No Private Data\n");
+       printk(KERN_DEBUG "UNIPISPI: CDEV No Private Data\n");
        return -1;      // No private data
     }
     private_data = (struct neuronspi_file_data*) file_p->private_data;
     if (private_data == NULL) return -4;
-    device_index = private_data->send_buf[0];
-    spi_driver_data = private_data->spi_device[device_index];  // Get private (driver) data from FP
+    spi_driver_data = private_data->spi_device[private_data->device_index];    // Get private (driver) data from FP
     if (spi_driver_data == NULL) return -2;
+
     driver_data = spi_get_drvdata(spi_driver_data);
     if (driver_data == NULL) return -2;
     if (driver_data->spi_driver == NULL) return -2;    // Invalid private data
     if ((driver_data->first_probe_reply[0] == 0) && !(driver_data->probe_always_succeeds) ) return -3; // Device not present
+
     mutex_lock(&(private_data->lock));
-    if (private_data->recv_buf == NULL) {
+    if (private_data->recv_buf.second_message == NULL) {
        mutex_unlock(&(private_data->lock));
        return -10;
     }
-#if NEURONSPI_DETAILED_DEBUG > 0
-    printk(KERN_INFO "UNIPISPI: Device read %d DEV:%s%d DRV:%s%d\n", private_data->message_len, (spi_driver_data->dev.of_node->name),
-               (spi_driver_data->chip_select), (driver_data->spi_driver->driver.name), (device_index));
-#endif
-    if ((((s32)len) == private_data->message_len + 10)) {
-       memcpy(buffer, private_data->recv_buf, len);
-       result = len;
+    unipi_spi_trace(KERN_INFO "UNIPISPI: CDEV Read %d, DEV:%s%d DRV:%s%d msglen=%d offset=%d\n", len, (spi_driver_data->dev.of_node->name),
+               (spi_driver_data->chip_select), (driver_data->spi_driver->driver.name), (private_data->device_index),private_data->message_len, (int)*offset);
+            
+       if (private_data->has_first_message & UNIPISPI_OP_MODE_SEND_HEADER) {
+               result = simple_read_from_buffer(buffer, len, &dummy_offset, private_data->recv_buf.first_message, NEURONSPI_FIRST_MESSAGE_LENGTH);
+               if (result >=0) {
+            dummy_offset = 0;
+                       result = simple_read_from_buffer(buffer+result, len - result, &dummy_offset,
+                                                                       private_data->recv_buf.second_message, private_data->message_len);
+        }
+       } else {
+               result = simple_read_from_buffer(buffer, len, &dummy_offset, private_data->recv_buf.second_message, private_data->message_len);
+       }
+       if (result >= 0) {
+       if (result + NEURONSPI_HEADER_LENGTH <= len) result = len;
+       }
+/*
     } else if (private_data->message_len == 0) {
        mutex_unlock(&(private_data->lock));
        return -9;
-    } else if (len <= private_data->message_len) {
-       result = simple_read_from_buffer(buffer, len, offset, private_data->recv_buf, len);
-    } else {
-       mutex_unlock(&(private_data->lock));
-       return -9;
     }
-    memset(private_data->recv_buf, 0, NEURONSPI_BUFFER_MAX);
+*/
        mutex_unlock(&(private_data->lock));
        return result;
 }
 
 
-
 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;
-       u32 frequency = NEURONSPI_COMMON_FREQ;
-       s32 transmit_len = len - NEURONSPI_HEADER_LENGTH;
-       s32 send_header = 0;
+       u32 frequency;
+       u8  reservation, send_header;
        s32 delay = 25;
-       unsigned long flags;
+    loff_t dummy_offset = 0;
+    size_t datalen;
+       //unsigned long flags;
        struct neuronspi_file_data* private_data;
        struct spi_device* spi_driver_data;
        struct neuronspi_driver_data* driver_data;
@@ -186,476 +394,365 @@ ssize_t neuronspi_write (struct file *file_p, const char *buffer, size_t len, lo
        if (neuronspi_cdrv.open_counter == 0) {
                neuronspi_cdrv.open_counter = 1;
        }
-#if NEURONSPI_DETAILED_DEBUG > 0
-       printk(KERN_INFO "UNIPISPI: LENGTH:%d\n", len);
-#endif
-       if (buffer == NULL) {
+
+       unipi_spi_trace(KERN_INFO "UNIPISPI: CDEV Write len:%d\n", len);
+       if ((buffer == NULL) || (len == 0)) {
                return 0; // Void write
        }
-    if (len == 0) {
-       return result; // Empty write
-    }
-    if (len > 4095) return -EMSGSIZE;
+
+    if ((len > 4095) || (len < NEURONSPI_HEADER_LENGTH + NEURONSPI_FIRST_MESSAGE_LENGTH)) return -EMSGSIZE;
     if (file_p == NULL) {
        return -12;
     }
     if (file_p->private_data == NULL) {
-       printk(KERN_DEBUG "UNIPISPI: No Private Data\n");
+       printk(KERN_DEBUG "UNIPISPI: CDEV No Private Data\n");
        return -1;      // No private data
     }
     // Read packet header and initialise private data (dependent on each other)
     device_index = buffer[0];
+    send_header = buffer[3];
+    frequency = (buffer[4] << 8 | buffer[5]) * 1000;
+       delay = buffer[6];
+    reservation = buffer[7]; // Device reservation
+
+    buffer += NEURONSPI_HEADER_LENGTH;
+    datalen = len - NEURONSPI_HEADER_LENGTH;
+    
     if (device_index > NEURONSPI_MAX_DEVS - 1) return -2;
     private_data = (struct neuronspi_file_data*) file_p->private_data;
     spi_driver_data = private_data->spi_device[device_index];  // Get private (driver) data from FP
     if (spi_driver_data == NULL) return -2;
+
     driver_data = spi_get_drvdata(spi_driver_data);
     if (driver_data == NULL) return -2;
     if (driver_data->spi_driver == NULL) return -2;    // Invalid private data
-    if ((driver_data->first_probe_reply[0] == 0) && !(driver_data->probe_always_succeeds) ) return -3; // Device not present
-    send_header = buffer[3];
-    if (buffer[4]) {   // Frequency setting
-       frequency = (buffer[4] << 8 | buffer[5]) * 1000;
-    }
-    if (buffer[6]) {   // Delay setting
-       delay = buffer[6];
-    }
-    if (buffer[7]) {   // Device reservation
-       if (buffer[7] == 255) { // Unlock device
-               driver_data->reserved_device = 0;
-       } else if ((driver_data->reserved_device) && buffer[7] != driver_data->reserved_device) {
-               return -4;                              // Another device reserved
-       } else if (!driver_data->reserved_device) {
-               driver_data->reserved_device = buffer[7];       // Reserve the device
-       }
-#ifdef STRICT_RESERVING
-    } else if (driver_data->reserved_device) {
-       return -5;                      // Device reserved
-    }
-    if (driver_data->slower_model && frequency > NEURONSPI_SLOWER_FREQ) {
-       frequency = NEURONSPI_SLOWER_FREQ;
-    }
-#else
-       } else if (device_index == (driver_data->reserved_device - 1)) {
-               return -5;                      // Device reserved
-       }
-       if (driver_data->slower_model) {
-               frequency = NEURONSPI_SLOWER_FREQ;
+    if ((driver_data->first_probe_reply[0] == 0) && !(driver_data->probe_always_succeeds) ) 
+        return -3; // Device not present
+
+    if (delay == 0) { delay = 25; }    // Delay setting
+
+    if (reservation == 255) { 
+        // Unlock device
+               driver_data->reserved_device = 0;
+       
+    } else if (driver_data->reserved_device == 0) {
+        // Reserve the device
+               driver_data->reserved_device = reservation;
+
+    } else if (reservation != driver_data->reserved_device) {
+        // Another device reserved
+               return -4;                              
+       }
+
+    if (!frequency || (frequency > driver_data->ideal_frequency)) 
+        frequency = driver_data->ideal_frequency;
+
+    mutex_lock(&(private_data->lock));
+       private_data->device_index = device_index;
+    private_data->has_first_message = send_header;
+       if (send_header & UNIPISPI_OP_MODE_SEND_HEADER) {
+       private_data->message_len = datalen - NEURONSPI_FIRST_MESSAGE_LENGTH;
+               simple_write_to_buffer(private_data->send_buf.first_message, NEURONSPI_FIRST_MESSAGE_LENGTH, &dummy_offset, buffer, datalen);
+        dummy_offset = 0;
+               simple_write_to_buffer(private_data->send_buf.second_message, NEURONSPI_BUFFER_MAX, &dummy_offset, buffer+NEURONSPI_FIRST_MESSAGE_LENGTH, private_data->message_len);
+        //memcpy(private_data->send_buf.first_message, buffer + NEURONSPI_HEADER_LENGTH, NEURONSPI_FIRST_MESSAGE_LENGTH);
+               //memcpy(private_data->send_buf.second_message, buffer + NEURONSPI_HEADER_LENGTH + NEURONSPI_FIRST_MESSAGE_LENGTH, private_data->message_len);
+       } else {
+       private_data->message_len = datalen;
+               simple_write_to_buffer(private_data->send_buf.second_message, NEURONSPI_BUFFER_MAX, &dummy_offset, buffer, datalen);
+               //memcpy(private_data->send_buf.second_message, buffer + NEURONSPI_HEADER_LENGTH, private_data->message_len);
        }
+
+    // clear receive buffer content
+#if NEURONSPI_DETAILED_DEBUG > 1
+    memset(private_data->recv_buf.first_message, 0, sizeof(private_data->recv_buf.first_message));
+    memset(private_data->recv_buf.second_message, 0, NEURONSPI_BUFFER_MAX );
+#else
+    private_data->recv_buf.first_message[0] = 0;
+    private_data->recv_buf.second_message[0] = 0;
 #endif
-    mutex_lock(&(private_data->lock));
-    memset(private_data->send_buf, 0, NEURONSPI_BUFFER_MAX );
-    memcpy(private_data->send_buf, buffer, len);
-    memset(private_data->recv_buf, 0, NEURONSPI_BUFFER_MAX );
-    private_data->message_len = transmit_len;
-    spin_lock_irqsave(neuronspi_spi_w_spinlock, flags);
-    neuronspi_spi_w_flag = 1;
-    spin_unlock_irqrestore(neuronspi_spi_w_spinlock, flags);
-    neuronspi_spi_send_message(spi_driver_data, &private_data->send_buf[NEURONSPI_HEADER_LENGTH], private_data->recv_buf,
-               transmit_len, frequency, delay, send_header, buffer[7]);
+
+    neuronspi_spi_send_op(spi_driver_data, &private_data->send_buf, &private_data->recv_buf, private_data->message_len,
+                                                               frequency, delay, send_header, reservation);
     mutex_unlock(&private_data->lock);
     return len;
 }
 
-s32 neuronspi_spi_uart_write(struct spi_device *spi, u8 *send_buf, u8 length, u8 uart_index)
+/********************************************************
+ *  Interface used by kernel - UnipiSpi operations 
+ */
+
+s32 neuronspi_spi_uart_write(struct spi_device *spi, u8 *send_buf, int length, u8 uart_index)
 {
        u8 *message_buf;
        u8 *recv_buf;
-       s32 transmit_len, i;
+       s32 transmit_len;
        struct neuronspi_driver_data *d_data = spi_get_drvdata(spi);
-       u16 crc1, crc2;
-       u32 frequency = NEURONSPI_COMMON_FREQ;
-#if NEURONSPI_DETAILED_DEBUG > 0
-       printk(KERN_INFO "UNIPISPI: UART SPI Write, dev:%d, len:%d\n", uart_index, length);
-#endif
-       if (length == 0) {
+       struct neuronspi_op_buffer send_op;
+       struct neuronspi_op_buffer recv_op;
+       s32 frequency = NEURONSPI_DEFAULT_FREQ;
+       if (d_data) {
+               frequency = d_data->ideal_frequency;
+       }
+
+       unipi_spi_trace(KERN_INFO "UNIPISPI: UART SPI Write, dev:%d, len:%d\n", uart_index, length);
+       if ((length == 0) || (length > 256)) {
                return -1;
        }
+       if (d_data->reserved_device) {
+               return 0;
+       }
+
        if (length == 1) {
-               transmit_len = 6;
-               message_buf = kzalloc(transmit_len, GFP_ATOMIC);
-               memcpy(message_buf, NEURONSPI_SPI_UART_SHORT_MESSAGE, NEURONSPI_SPI_UART_SHORT_MESSAGE_LEN);
-               message_buf[1] = send_buf[0];
-               message_buf[3] = uart_index;
-               crc1 = neuronspi_spi_crc(message_buf, 4, 0);
-               memcpy(&message_buf[4], &crc1, 2);
+               transmit_len = 0;
+               send_op.first_message[0] = 0x41;
+               send_op.first_message[1] = send_buf[0];
+               send_op.first_message[2] = 0;
+               send_op.first_message[3] = uart_index;
+               //neuronspi___spi_send_message_crc(spi, &send_op, &recv_op, transmit_len, frequency, 65);
+               neuronspi_spi_send_op(spi, &send_op, &recv_op, transmit_len, frequency, 65, UNIPISPI_OP_MODE_SEND_HEADER|UNIPISPI_OP_MODE_DO_CRC|UNIPISPI_OP_MODE_HAVE_CRC_SPACE, 0);
        } else {
-               transmit_len = 6 + length + 2;
-               message_buf = kzalloc(transmit_len, GFP_ATOMIC);
-               memcpy(message_buf, NEURONSPI_SPI_UART_LONG_MESSAGE, NEURONSPI_SPI_UART_LONG_MESSAGE_LEN);
-               message_buf[1] = length;
-               message_buf[3] = uart_index;
-               crc1 = neuronspi_spi_crc(message_buf, 4, 0);
-               memcpy(&message_buf[4], &crc1, 2);
-               for (i = 0; i < length; i++) {
-                       message_buf[6 + i] = send_buf[i];
-               }
-               crc2 = neuronspi_spi_crc(&message_buf[6], length, crc1);
-               memcpy(&message_buf[6+length], &crc2, 2);
+               transmit_len = length & 1 ? length+1 : length;  // transmit_length must be even
+               send_op.first_message[0] = 0x64;                //NEURONSPI_SPI_UART_LONG_MESSAGE[0];
+               send_op.first_message[1] = length == 256 ? 0 : length;           // special case length==256
+               send_op.first_message[2] = 0;
+               send_op.first_message[3] = uart_index;
+               message_buf = kzalloc(transmit_len+16, GFP_ATOMIC);
+               memcpy(message_buf, send_buf, length);
+               recv_buf = kzalloc(transmit_len+16, GFP_ATOMIC);
+               memset(recv_buf+transmit_len, 0xff, 16);
+        
+        recv_op.second_message = recv_buf;
+        send_op.second_message = message_buf;
+               neuronspi_spi_send_op(spi, &send_op, &recv_op, transmit_len, frequency, 65, UNIPISPI_OP_MODE_SEND_HEADER|UNIPISPI_OP_MODE_DO_CRC|UNIPISPI_OP_MODE_HAVE_CRC_SPACE, 0);
+               //neuronspi___spi_send_message_crc(spi, &send_op, &recv_op, transmit_len, frequency, 65);
+
+               kfree(message_buf);
+               kfree(recv_buf);
        }
-       recv_buf = kzalloc(transmit_len, GFP_ATOMIC);
-       if (d_data->slower_model) {
-               frequency = NEURONSPI_SLOWER_FREQ;
-       }
-       if (!d_data->reserved_device) {
-               neuronspi_spi_send_message(spi, message_buf, recv_buf, transmit_len, frequency, 65, 1, 0);
-       }
-       kfree(message_buf);
-       kfree(recv_buf);
        return 0;
 }
 
-
-void neuronspi_spi_uart_read(struct spi_device* spi, u8 *send_buf, u8 *recv_buf, s32 len, u8 uart_index)
+void neuronspi_spi_uart_read(struct spi_device* spi, u8 *recv_buf, s32 len, u8 uart_index)
 {
        s32 transmit_len;
+       struct neuronspi_op_buffer send_op;
+       struct neuronspi_op_buffer recv_op;
+    u8 *send_buf;
        struct neuronspi_driver_data *d_data = spi_get_drvdata(spi);
-       u16 crc1, crc2;
-       s32 frequency = NEURONSPI_COMMON_FREQ;
-       if (d_data->slower_model) {
-               frequency = NEURONSPI_SLOWER_FREQ;
+       s32 frequency = NEURONSPI_DEFAULT_FREQ;
+       if (d_data) {
+               frequency = d_data->ideal_frequency;
        }
-#if NEURONSPI_DETAILED_DEBUG > 0
-       printk(KERN_INFO "UNIPISPI: UART SPI Read, cs:%d, len:%d\n", uart_index, len);
-#endif
-       if (len <= 2) {
-               memcpy(send_buf, NEURONSPI_SPI_UART_READ_MESSAGE, NEURONSPI_SPI_UART_READ_MESSAGE_LEN);
-               transmit_len = NEURONSPI_SPI_UART_READ_MESSAGE_LEN;
+
+       unipi_spi_trace(KERN_INFO "UNIPISPI: UART SPI Read, cs:%d, len:%d\n", uart_index, len);
+       if (len < 246) {
+               len = (len+4);
        } else {
-               memcpy(send_buf, NEURONSPI_SPI_UART_READ_MESSAGE, NEURONSPI_SPI_UART_READ_MESSAGE_LEN);
-               if (len < 100) {
-                       len = (len * 2) + 1;
-               } else {
-                       len = 201;
-               }
-               transmit_len = 5 + len + 6;     // Header (-1 for the byte there) + 4 bytes in second part + 2 bytes of CRC
-               send_buf[1] = len + 3;  // Length of second part (len + 4 - 1)
-
-               crc1 = neuronspi_spi_crc(send_buf, 4, 0);
-               memcpy(&send_buf[4], &crc1, 2);
-               send_buf[7] = len;
-               crc2 = neuronspi_spi_crc(&send_buf[6], len + 3, crc1);
-               memcpy(&send_buf[len + 9], &crc2, 2);
-#if NEURONSPI_DETAILED_DEBUG > 0
-               printk(KERN_INFO "UNIPISPI: UART Device Read len:%d %100ph\n", transmit_len, send_buf);
-#endif
+               len = 250;
        }
-       if (!d_data->reserved_device) {
-               neuronspi_spi_send_message(spi, send_buf, recv_buf, transmit_len, frequency, 65, 1, 0);
-       }
-}
+       transmit_len = (len & 1 ? len+1 : len) + 4;  // transmit_length must be even
 
-void neuronspi_spi_set_irqs(struct spi_device* spi_dev, u16 to)
-{
-       u8 *message_buf;
-       u8 *recv_buf;
-       u16 crc1, crc2;
-       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 "UNIPISPI: SPI IRQ Set, Dev-CS:%d, to:%d\n", spi_dev->chip_select, to);
-#endif
-       message_buf = kzalloc(NEURONSPI_SPI_IRQ_SET_MESSAGE_LEN, GFP_ATOMIC);
-       recv_buf = kzalloc(NEURONSPI_SPI_IRQ_SET_MESSAGE_LEN, GFP_ATOMIC);
-       memcpy(message_buf, NEURONSPI_SPI_IRQ_SET_MESSAGE, NEURONSPI_SPI_IRQ_SET_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_IRQ_SET_MESSAGE_LEN - 8, crc1);
-       memcpy(&message_buf[NEURONSPI_SPI_IRQ_SET_MESSAGE_LEN - 2], &crc2, 2);
-       if (!d_data->reserved_device) {
-               neuronspi_spi_send_message(spi_dev, message_buf, recv_buf, NEURONSPI_SPI_IRQ_SET_MESSAGE_LEN, frequency, 65, 1, 0);
-       }
-       kfree(message_buf);
-       kfree(recv_buf);
-}
+       send_op.first_message[1] = transmit_len;     //
+       send_op.first_message[2] = 0;
+       send_op.first_message[3] = uart_index;
 
-void neuronspi_spi_uart_set_cflag(struct spi_device* spi_dev, u8 port, u32 to)
-{
-       u8 *message_buf;
-       u8 *recv_buf;
-       u16 crc1, crc2;
-       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;
+       send_buf = kzalloc(transmit_len, GFP_ATOMIC);
+
+    if (NEURON_FIRMWARE_VERSION(d_data) < 0x518) {
+               send_op.first_message[0] = 0x65;
+       } else  {
+               send_op.first_message[0] = 0x68;
        }
-#if NEURONSPI_DETAILED_DEBUG > 0
-       printk(KERN_INFO "UNIPISPI: SPI TERMIOS Set, Dev-CS:%d, to:%x\n", spi_dev->chip_select, to);
-#endif
-       message_buf = kzalloc(NEURONSPI_SPI_UART_SET_CFLAG_MESSAGE_LEN, GFP_ATOMIC);
-       recv_buf = kzalloc(NEURONSPI_SPI_UART_SET_CFLAG_MESSAGE_LEN, GFP_ATOMIC);
-       memcpy(message_buf, NEURONSPI_SPI_UART_SET_CFLAG_MESSAGE, NEURONSPI_SPI_UART_SET_CFLAG_MESSAGE_LEN);
-       crc1 = neuronspi_spi_crc(message_buf, 4, 0);
-       memcpy(&message_buf[4], &crc1, 2);
-       memcpy(&message_buf[10], &to, 4);
-       crc2 = neuronspi_spi_crc(&message_buf[6], NEURONSPI_SPI_UART_SET_CFLAG_MESSAGE_LEN - 8, crc1);
-       memcpy(&message_buf[NEURONSPI_SPI_UART_SET_CFLAG_MESSAGE_LEN - 2], &crc2, 2);
+       send_buf[0] = 0x65;
+
+    send_op.second_message = send_buf;
+    recv_op.second_message = recv_buf;
+
+       unipi_spi_trace(KERN_INFO "UNIPISPI: UART Device Read len:%d\n", transmit_len);
+
        if (!d_data->reserved_device) {
-               neuronspi_spi_send_message(spi_dev, message_buf, recv_buf, NEURONSPI_SPI_UART_SET_CFLAG_MESSAGE_LEN, frequency, 65, 1, 0);
+               neuronspi_spi_send_op(spi, &send_op, &recv_op, transmit_len, frequency, 65, 
+                                UNIPISPI_OP_MODE_SEND_HEADER|UNIPISPI_OP_MODE_DO_CRC|UNIPISPI_OP_MODE_HAVE_CRC_SPACE, 0);
        }
-       kfree(message_buf);
-       kfree(recv_buf);
+    kfree(send_buf);
 }
 
-void neuronspi_spi_uart_set_ldisc(struct spi_device* spi_dev, u8 port, u8 to)
+int unipispi_modbus_read_register(struct spi_device* spi_dev, u16 reg, u16* value)
 {
-       u8 *message_buf;
-       u8 *recv_buf;
+    struct neuronspi_op_buffer send_buf;
+    struct neuronspi_op_buffer recv_buf;
+    u8 send_data[4+2+2]; // cmd: 4B, value 2B, crc 2B
+    u8 recv_data[4+2+2];    
+    int ret_code;
        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 > 1
-       printk(KERN_INFO "UNIPISPI: SPI TERMIOS Set, Dev-CS:%d, to:%x\n", spi_dev->chip_select, to);
-#endif
-       neuronspi_spi_compose_single_register_write(503, &message_buf, &recv_buf, to);
-       if (!d_data->reserved_device) {
-               neuronspi_spi_send_message(spi_dev, message_buf, recv_buf, NEURONSPI_SPI_UART_SET_CFLAG_MESSAGE_LEN, frequency, 35, 1, 0);
-       }
-       kfree(message_buf);
-       kfree(recv_buf);
+       s32 frequency = NEURONSPI_DEFAULT_FREQ;
+       if (d_data) {
+               frequency = d_data->ideal_frequency;
+       }
+    send_buf.second_message = send_data;
+    recv_buf.second_message = recv_data;
+
+    send_buf.first_message[0] = 0x03;  // OP_READ_REGISTERS
+    send_buf.first_message[1] = 4+2;
+    *((u16*)(send_buf.first_message + 2)) = reg;
+       memcpy(send_data, send_buf.first_message, 4);
+       send_data[1] = 1;
+    
+       ret_code = neuronspi_spi_send_op(spi_dev, &send_buf, &recv_buf, 4+2, frequency, 35,
+                                    UNIPISPI_OP_MODE_SEND_HEADER|UNIPISPI_OP_MODE_DO_CRC|UNIPISPI_OP_MODE_HAVE_CRC_SPACE, 0);
+       if (ret_code == 0) {
+        if ((recv_data[0] == 0x03) && (recv_data[1]==1)) {
+            *value = *((u16*)(recv_data + 4));
+        } else {
+            ret_code = 2;
+        }
+    }
+    return ret_code;
 }
 
-u8 neuronspi_spi_uart_get_ldisc(struct spi_device* spi_dev, u8 port)
+int unipispi_modbus_read_u32(struct spi_device* spi_dev, u16 reg, u32* value)
 {
-       u8 *message_buf;
-       u8 *recv_buf;
-       u8 outp;
+    struct neuronspi_op_buffer send_buf;
+    struct neuronspi_op_buffer recv_buf;
+    u8 send_data[4+4+2]; // cmd: 4B, value 4B, crc 2B
+    u8 recv_data[4+4+2];    
+    int ret_code;
        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_spi_compose_single_register_read(503, &message_buf, &recv_buf);
-       if (!d_data->reserved_device) {
-               neuronspi_spi_send_message(spi_dev, message_buf, recv_buf, NEURONSPI_SPI_UART_SET_CFLAG_MESSAGE_LEN, frequency, 35, 1, 0);
-       }
-       outp = recv_buf[MODBUS_FIRST_DATA_BYTE + 1];
-#if NEURONSPI_DETAILED_DEBUG > 1
-       printk(KERN_INFO "UNIPISPI: SPI TERMIOS GET, Dev-CS:%d, to:%x\n", spi_dev->chip_select, outp);
-#endif
-       kfree(message_buf);
-       kfree(recv_buf);
-       return outp;
+       s32 frequency = NEURONSPI_DEFAULT_FREQ;
+       if (d_data) {
+               frequency = d_data->ideal_frequency;
+       }
+    send_buf.second_message = send_data;
+    recv_buf.second_message = recv_data;
+
+    send_buf.first_message[0] = 0x03;  // OP_READ_REGISTERS
+    send_buf.first_message[1] = 4+4;
+    *((u16*)(send_buf.first_message + 2)) = reg;
+       memcpy(send_data, send_buf.first_message, 4);
+       send_data[1] = 2;
+    
+       ret_code = neuronspi_spi_send_op(spi_dev, &send_buf, &recv_buf, 4+4, frequency, 35,
+                                    UNIPISPI_OP_MODE_SEND_HEADER|UNIPISPI_OP_MODE_DO_CRC|UNIPISPI_OP_MODE_HAVE_CRC_SPACE, 0);
+       if (ret_code == 0) {
+        if ((recv_data[0] == 0x03) && (recv_data[1]==2)) {
+            *value = *((u32*)(recv_data + 4));
+        } else {
+            ret_code = 2;
+        }
+    }
+    return ret_code;
 }
 
-
-/*
- * NOTE: This function uses 64-bit fixed-point arithmetic,
- * which necessitates using the do_div macro to avoid unnecessary long/long division.
- */
-void neuronspi_spi_iio_sec_ai_read_voltage(struct iio_dev *indio_dev, struct iio_chan_spec const *ch, int *val, int *val2, long mask)
+int unipispi_modbus_read_many(struct spi_device* spi_dev, u16 reg, u16* value, int register_count)
 {
-       struct neuronspi_analog_data *ai_data = iio_priv(indio_dev);
-       struct spi_device *spi = ai_data->parent;
-       struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi);
-       u32 sec_ai_val_l = 0;
-       u32 sec_ai_val_h = 0;
-       u32 sec_ai_val_m = 0;
-       u8 sec_ai_exp = 0;
-       regmap_read(n_spi->reg_map, n_spi->regstart_table->sec_ai_val_reg + 1 + (2 * ai_data->index), &sec_ai_val_h);
-       regmap_read(n_spi->reg_map, n_spi->regstart_table->sec_ai_val_reg + (2 * ai_data->index), &sec_ai_val_l);
-       sec_ai_val_m = ((((u32)sec_ai_val_h) << 25) | (((u32)sec_ai_val_l) << 9)) >> 16;
-       sec_ai_exp = (sec_ai_val_h & 0x7F80) >> 7;
-
-       *val = sec_ai_val_m | 0x00010000;
-       if (142 - ((int)sec_ai_exp) <= 0) {
-               *val = (*val << (((int)sec_ai_exp) - 142)) * 1000;
-               *val2 = 1;
-       } else {
-               *val = *val * 1000;
-               *val2 = 2 << (142 - sec_ai_exp);
-       }
-
+       printk(KERN_ERR "UNIPISPI: modbus read many(%d) UNIMPLENETED\n", register_count);
+    //ToDo: 
+    return 0;
 }
 
-void neuronspi_spi_iio_sec_ai_read_current(struct iio_dev *indio_dev, struct iio_chan_spec const *ch, int *val, int *val2, long mask)
-{
-       struct neuronspi_analog_data *ai_data = iio_priv(indio_dev);
-       struct spi_device *spi = ai_data->parent;
-       struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi);
-       u32 sec_ai_val_l = 0;
-       u32 sec_ai_val_h = 0;
-       u32 sec_ai_val_m = 0;
-       u8 sec_ai_exp = 0;
-
-       regmap_read(n_spi->reg_map, n_spi->regstart_table->sec_ai_val_reg + 1 + (2 * ai_data->index), &sec_ai_val_h);
-       regmap_read(n_spi->reg_map, n_spi->regstart_table->sec_ai_val_reg + (2 * ai_data->index), &sec_ai_val_l);
-       sec_ai_val_m = ((((u32)sec_ai_val_h) << 25) | (((u32)sec_ai_val_l) << 9)) >> 16;
-       sec_ai_exp = (sec_ai_val_h & 0x7F80) >> 7;
-       *val = sec_ai_val_m | 0x00010000;
-       if (142 - ((int)sec_ai_exp) <= 0) {
-               *val2 = 1;
-               *val = *val << (((int)sec_ai_exp) - 142);
-       } else {
-               *val2 = 2 << (142 - sec_ai_exp);
-       }
-}
 
-void neuronspi_spi_iio_sec_ai_read_resistance(struct iio_dev *indio_dev, struct iio_chan_spec const *ch, int *val, int *val2, long mask)
+int unipispi_modbus_write_register(struct spi_device* spi_dev, u16 reg, u16 value)
 {
-       struct neuronspi_analog_data *ai_data = iio_priv(indio_dev);
-       struct spi_device *spi = ai_data->parent;
-       struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi);
-       u32 sec_ai_val_l = 0;
-       u32 sec_ai_val_h = 0;
-       u32 sec_ai_val_m = 0;
-       u8 sec_ai_exp = 0;
-       regmap_read(n_spi->reg_map, n_spi->regstart_table->sec_ai_val_reg + 1 + (2 * ai_data->index), &sec_ai_val_h);
-       regmap_read(n_spi->reg_map, n_spi->regstart_table->sec_ai_val_reg + (2 * ai_data->index), &sec_ai_val_l);
-       sec_ai_val_m = ((((u32)sec_ai_val_h) << 25) | (((u32)sec_ai_val_l) << 9)) >> 16;
-       sec_ai_exp = (sec_ai_val_h & 0x7F80) >> 7;
-       *val = sec_ai_val_m | 0x00010000;
-       if (142 - ((int)sec_ai_exp) <= 0) {
-               *val2 = 1;
-               *val = *val << (((int)sec_ai_exp) - 142);
-       } else {
-               *val2 = 2 << (142 - sec_ai_exp);
-       }
+    struct neuronspi_op_buffer send_buf;
+    struct neuronspi_op_buffer recv_buf;
+    u8 send_data[4+2+2]; // cmd: 4B, value 2B, crc 2B
+    u8 recv_data[4+2+2];    
+    int ret_code;
+       struct neuronspi_driver_data *d_data = spi_get_drvdata(spi_dev);
+       s32 frequency = NEURONSPI_DEFAULT_FREQ;
+       if (d_data) {
+               frequency = d_data->ideal_frequency;
+       }
+    send_buf.second_message = send_data;
+    recv_buf.second_message = recv_data;
+
+    send_buf.first_message[0] = 0x06;   // OP_WRITE_REGISTERS
+    send_buf.first_message[1] = 4+2;
+    *((u16*)(send_buf.first_message + 2)) = reg;
+       memcpy(send_data, send_buf.first_message, 4);
+       send_data[1] = 1;
+    *((u16*)(send_data + 4)) = value;
+    
+       ret_code = neuronspi_spi_send_op(spi_dev, &send_buf, &recv_buf, 4+2, frequency, 35,
+                                    UNIPISPI_OP_MODE_SEND_HEADER|UNIPISPI_OP_MODE_DO_CRC|UNIPISPI_OP_MODE_HAVE_CRC_SPACE, 0);
+       if (ret_code == 0) {
+        if ((recv_data[0] != 0x06) || (recv_data[1]!=1)) {
+            ret_code = 2;
+        }
+    }
+    return ret_code;
 }
 
-void neuronspi_spi_iio_sec_ao_set_voltage(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int val, int val2, long mask)
+int unipispi_modbus_write_u32(struct spi_device* spi_dev, u16 reg, u32 value)
 {
-       struct neuronspi_analog_data *ao_data = iio_priv(indio_dev);
-       struct spi_device *spi = ao_data->parent;
-       struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi);
-       u32 sec_true_val;
-       if (val > 10000) val = 10000;
-       sec_true_val = (val * 2) / 5;
-       regmap_write(n_spi->reg_map, n_spi->regstart_table->sec_ao_val_reg + ao_data->index, sec_true_val);
+    struct neuronspi_op_buffer send_buf;
+    struct neuronspi_op_buffer recv_buf;
+    u8 send_data[4+4+2]; // cmd: 4B, value 4B, crc 2B
+    u8 recv_data[4+4+2];    
+    int ret_code;
+       struct neuronspi_driver_data *d_data = spi_get_drvdata(spi_dev);
+       s32 frequency = NEURONSPI_DEFAULT_FREQ;
+       if (d_data) {
+               frequency = d_data->ideal_frequency;
+       }
+    send_buf.second_message = send_data;
+    recv_buf.second_message = recv_data;
+
+    send_buf.first_message[0] = 0x06;    // OP_WRITE_REGISTERS
+    send_buf.first_message[1] = 4+4;
+    *((u16*)(send_buf.first_message + 2)) = reg;
+       memcpy(send_data, send_buf.first_message, 4);
+       send_data[1] = 2;
+    *((u32*)(send_data + 4)) = value;
+    
+       ret_code = neuronspi_spi_send_op(spi_dev, &send_buf, &recv_buf, 4+4, frequency, 35,
+                                    UNIPISPI_OP_MODE_SEND_HEADER|UNIPISPI_OP_MODE_DO_CRC|UNIPISPI_OP_MODE_HAVE_CRC_SPACE, 0);
+       if (ret_code == 0) {
+        if ((recv_data[0] != 0x06) || (recv_data[1]!=2)) {
+            ret_code = 2;
+        }
+    }
+    return ret_code;
 }
 
-/*
- * NOTE: This function uses 64-bit fixed-point arithmetic,
- * which necessitates using the do_div macro to avoid unnecessary long/long division.
- */
-void neuronspi_spi_iio_stm_ai_read_voltage(struct iio_dev *iio_dev, struct iio_chan_spec const *ch, int *val, int *val2, long mask)
+int unipispi_modbus_write_many(struct spi_device* spi_dev, u16 reg, u16* value, int register_count)
 {
-       struct neuronspi_analog_data *ai_data = iio_priv(iio_dev);
-       struct spi_device *spi = ai_data->parent;
-       struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi);
-       u32 stm_ai_val = 0;
-       u32 stm_v_int_ref = 0;
-       u32 stm_v_inp_ref = 0;
-       u32 stm_v_err = 0;
-       u32 stm_v_off = 0;
-       u64 stm_true_val = 0;
-       u64 stm_true_ref = 0;
-       regmap_read(n_spi->reg_map, n_spi->regstart_table->stm_ai_val_reg, &stm_ai_val);
-       regmap_read(n_spi->reg_map, n_spi->regstart_table->vref_int, &stm_v_int_ref);
-       regmap_read(n_spi->reg_map, n_spi->regstart_table->vref_inp, &stm_v_inp_ref);
-       regmap_read(n_spi->reg_map, n_spi->regstart_table->stm_ai_vol_err, &stm_v_err);
-       regmap_read(n_spi->reg_map, n_spi->regstart_table->stm_ai_vol_off, &stm_v_off);
-       stm_true_ref = ((u64)stm_v_int_ref) * 99000;
-       stm_v_inp_ref = stm_v_inp_ref * 10000;
-       stm_true_val = stm_true_ref * ((u64)(stm_ai_val * 1000));
-       do_div(stm_true_val, stm_v_inp_ref);
-       do_div(stm_true_val, 4096);
-       stm_true_val *= (10000 + stm_v_err);
-       stm_true_val += stm_v_off;
-       do_div(stm_true_val, 10000);
-       *val = stm_true_val;
+       printk(KERN_ERR "UNIPISPI: modbus write many(%d) UNIMPLENETED\n", register_count);
+    //ToDo:
+    return 0;
 }
 
-void neuronspi_spi_iio_stm_ai_read_current(struct iio_dev *indio_dev, struct iio_chan_spec const *ch, int *val, int *val2, long mask)
+int unipispi_modbus_write_coil(struct spi_device* spi_dev, u16 coil, int value)
 {
-       struct neuronspi_analog_data *ai_data = iio_priv(indio_dev);
-       struct spi_device *spi = ai_data->parent;
-       struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi);
-       u32 stm_ai_val = 0;
-       u32 stm_v_int_ref = 0;
-       u32 stm_v_inp_ref = 0;
-       u32 stm_i_err = 0;
-       u32 stm_i_off = 0;
-       u64 stm_true_val = 0;
-       u64 stm_true_ref = 0;
-       regmap_read(n_spi->reg_map, n_spi->regstart_table->stm_ai_val_reg, &stm_ai_val);
-       regmap_read(n_spi->reg_map, n_spi->regstart_table->vref_int, &stm_v_int_ref);
-       regmap_read(n_spi->reg_map, n_spi->regstart_table->vref_inp, &stm_v_inp_ref);
-       regmap_read(n_spi->reg_map, n_spi->regstart_table->stm_ai_curr_err, &stm_i_err);
-       regmap_read(n_spi->reg_map, n_spi->regstart_table->stm_ai_curr_off, &stm_i_off);
-       stm_true_ref = ((u64)stm_v_int_ref) * 330000;
-       stm_v_inp_ref = stm_v_inp_ref * 10000;
-       stm_true_val = stm_true_ref * ((u64)(stm_ai_val * 1000));
-       do_div(stm_true_val, stm_v_inp_ref);
-       do_div(stm_true_val, 4096);
-       stm_true_val *= (10000 + stm_i_err);
-       stm_true_val += stm_i_off;
-       do_div(stm_true_val, 10000);
-       *val = stm_true_val;
-       *val2 = 1000;
-}
+    struct neuronspi_op_buffer send_buf;
+    struct neuronspi_op_buffer recv_buf;
+    int ret_code;
+       struct neuronspi_driver_data *d_data = spi_get_drvdata(spi_dev);
+       s32 frequency = NEURONSPI_DEFAULT_FREQ;
+       if (d_data) {
+               frequency = d_data->ideal_frequency;
+       }
 
-void neuronspi_spi_iio_stm_ao_read_resistance(struct iio_dev *indio_dev, struct iio_chan_spec const *ch, int *val, int *val2, long mask)
-{
-       struct neuronspi_analog_data *ao_data = iio_priv(indio_dev);
-       struct spi_device *spi = ao_data->parent;
-       struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi);
-       u32 stm_aio_val = 0;
-       regmap_read(n_spi->reg_map, n_spi->regstart_table->stm_aio_val_reg, &stm_aio_val);
-       *val = stm_aio_val;
-       *val2 = 10;
+    send_buf.first_message[0] = 0x05;    // OP_WRITE_SINGLE_COIL
+    send_buf.first_message[1] = value ? 1 : 0;
+    *((u16*)(send_buf.first_message + 2)) = coil;
+    
+       ret_code = neuronspi_spi_send_op(spi_dev, &send_buf, &recv_buf, 0, frequency, 25,
+                                    UNIPISPI_OP_MODE_SEND_HEADER|UNIPISPI_OP_MODE_DO_CRC|UNIPISPI_OP_MODE_HAVE_CRC_SPACE, 0);
+    return ret_code;
 }
 
 
-void neuronspi_spi_iio_stm_ao_set_voltage(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int val, int val2, long mask)
+void neuronspi_spi_set_irqs(struct spi_device* spi_dev, u16 to)
 {
-       struct neuronspi_analog_data *ao_data = iio_priv(indio_dev);
-       struct spi_device *spi = ao_data->parent;
-       struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi);
-       u32 stm_v_int_ref = 0;
-       u32 stm_v_inp_ref = 0;
-       u32 stm_v_err = 0;
-       u32 stm_v_off = 0;
-       u64 stm_true_val = val;
-       u64 stm_true_val_fraction = val2 / 100;
-       u64 stm_true_ref = 0;
-       regmap_read(n_spi->reg_map, n_spi->regstart_table->vref_int, &stm_v_int_ref);
-       regmap_read(n_spi->reg_map, n_spi->regstart_table->vref_inp, &stm_v_inp_ref);
-       regmap_read(n_spi->reg_map, n_spi->regstart_table->stm_ao_vol_err, &stm_v_err);
-       regmap_read(n_spi->reg_map, n_spi->regstart_table->stm_ao_vol_off, &stm_v_off);
-       stm_true_ref = ((u64)stm_v_int_ref) * (99000 + stm_v_err) * 1000;
-       stm_v_inp_ref = stm_v_inp_ref * 10000;
-       stm_true_val = ((stm_true_val * 10000) + (stm_true_val_fraction) - stm_v_off) * 4095;
-       do_div(stm_true_ref, stm_v_inp_ref);
-       stm_v_inp_ref = stm_true_ref;
-       do_div(stm_true_val, stm_v_inp_ref);
-       do_div(stm_true_val, 10000);
-       if (stm_true_val > 4095) stm_true_val = 4095;
-       regmap_write(n_spi->reg_map, n_spi->regstart_table->stm_ao_val_reg, (unsigned int) stm_true_val);
+    unipispi_modbus_write_register(spi_dev, 1007, to);
+       unipi_spi_trace(KERN_INFO "UNIPISPI: SPI IRQ Set, Dev-CS:%d, to:%d\n", spi_dev->chip_select, to);
 }
 
-void neuronspi_spi_iio_stm_ao_set_current(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int val, int val2, long mask)
-{
-       struct neuronspi_analog_data *ao_data = iio_priv(indio_dev);
-       struct spi_device *spi = ao_data->parent;
-       struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi);
-       u32 stm_v_int_ref = 0;
-       u32 stm_v_inp_ref = 0;
-       u32 stm_i_err = 0;
-       u32 stm_i_off = 0;
-       u64 stm_true_val = val;
-       u64 stm_true_val_fraction = val2 / 100;
-       u64 stm_true_ref = 0;
-       regmap_read(n_spi->reg_map, n_spi->regstart_table->vref_int, &stm_v_int_ref);
-       regmap_read(n_spi->reg_map, n_spi->regstart_table->vref_inp, &stm_v_inp_ref);
-       regmap_read(n_spi->reg_map, n_spi->regstart_table->stm_ao_curr_err, &stm_i_err);
-       regmap_read(n_spi->reg_map, n_spi->regstart_table->stm_ao_curr_off, &stm_i_off);
-       stm_true_ref = ((u64)stm_v_int_ref) * (330000 + stm_i_err) * 100;
-       stm_v_inp_ref = stm_v_inp_ref * 1000;
-       stm_true_val = (((stm_true_val * 10000) + (stm_true_val_fraction)) - stm_i_off) * 4095;
-       do_div(stm_true_ref, stm_v_inp_ref);
-       stm_v_inp_ref = stm_true_ref;
-       do_div(stm_true_val, stm_v_inp_ref);
-       do_div(stm_true_val, 10);
-       if (stm_true_val > 4095) stm_true_val = 4095;
-       regmap_write(n_spi->reg_map, n_spi->regstart_table->stm_ao_val_reg, (unsigned int)stm_true_val);
-}
 
+
+/*
 int neuronspi_spi_send_message(struct spi_device* spi_dev, u8 *send_buf, u8 *recv_buf, s32 len, s32 freq, s32 delay, s32 send_header, u8 lock_val)
 {
        s32 i = 0;
@@ -663,24 +760,24 @@ int neuronspi_spi_send_message(struct spi_device* spi_dev, u8 *send_buf, u8 *rec
        u16 recv_crc1 = 0;
        u16 recv_crc2 = 0;
        u16 packet_crc = 0;
-       s32 trans_count = (len / NEURONSPI_MAX_TX) + 3; // number of transmissions
-       struct spi_message *s_msg;
+       s32 trans_count = (len<=0) ? 2 : ((len-1) / NEURONSPI_MAX_TX) + 3;      // number of transmissions
+       //struct spi_message *s_msg;
        struct neuronspi_driver_data *d_data;
     struct spi_transfer* s_trans;
        mutex_lock(&neuronspi_master_mutex);
+       //if ((len % NEURONSPI_MAX_TX) == 0) trans_count--;
     d_data = spi_get_drvdata(spi_dev);
        if (d_data != NULL && d_data->reserved_device && lock_val != d_data->reserved_device) {
                memset(&recv_buf, 0, len);
        } else {
                s_trans = kzalloc(sizeof(struct spi_transfer) * trans_count, GFP_ATOMIC);
-#if NEURONSPI_DETAILED_DEBUG > 1
-               printk(KERN_INFO "UNIPISPI: SPI Master Write, len:%d,\n %100ph\n", len, send_buf);
-#endif
+               unipi_spi_trace_1(KERN_INFO "UNIPISPI: SPI Master Write, len:%d,\n %100ph\n", len, send_buf);
+
                if (!send_header) {
                        trans_count -= 1;       // one less transmission as the header is omitted
                }
-               s_msg = kmalloc(sizeof(struct spi_message), GFP_ATOMIC);
-               spi_message_init(s_msg);
+               //s_msg = kmalloc(sizeof(struct spi_message), GFP_ATOMIC);
+               //spi_message_init(s_msg);
                for (i = 0; i < trans_count; i++) {
                        memset(&(s_trans[i]), 0, sizeof(s_trans[i]));
                        s_trans[i].delay_usecs = 0;
@@ -702,7 +799,8 @@ int neuronspi_spi_send_message(struct spi_device* spi_dev, u8 *send_buf, u8 *rec
                                if (send_header) {
                                        s_trans[i].tx_buf = &(send_buf[NEURONSPI_FIRST_MESSAGE_LENGTH + (NEURONSPI_MAX_TX * (i - 2))]);
                                        s_trans[i].rx_buf = &(recv_buf[NEURONSPI_FIRST_MESSAGE_LENGTH + (NEURONSPI_MAX_TX * (i - 2))]);
-                                       s_trans[i].len = ((NEURONSPI_MAX_TX * (i - 1)) - len) < 0 ? NEURONSPI_MAX_TX : (len - (NEURONSPI_MAX_TX * (i - 2)));
+                                       s_trans[i].len = (len - (NEURONSPI_MAX_TX * (i - 2)));
+                                       //s_trans[i].len = ((NEURONSPI_MAX_TX * (i - 1)) - len) < 0 ? NEURONSPI_MAX_TX : (len - (NEURONSPI_MAX_TX * (i - 2)));
                                } else {
                                        s_trans[i].tx_buf = &(send_buf[NEURONSPI_MAX_TX * (i - 1)]);
                                        s_trans[i].rx_buf = &(recv_buf[NEURONSPI_MAX_TX * (i - 1)]);
@@ -715,7 +813,8 @@ int neuronspi_spi_send_message(struct spi_device* spi_dev, u8 *send_buf, u8 *rec
                                if (send_header) {
                                        s_trans[i].tx_buf = &(send_buf[NEURONSPI_FIRST_MESSAGE_LENGTH + (NEURONSPI_MAX_TX * (i - 2))]);
                                        s_trans[i].rx_buf = &(recv_buf[NEURONSPI_FIRST_MESSAGE_LENGTH + (NEURONSPI_MAX_TX * (i - 2))]);
-                                       s_trans[i].len = ((NEURONSPI_MAX_TX * (i - 1)) - len) < 0 ? NEURONSPI_MAX_TX : (len - (NEURONSPI_MAX_TX * (i - 2)));
+                                       s_trans[i].len = NEURONSPI_MAX_TX;
+                                       //s_trans[i].len = ((NEURONSPI_MAX_TX * (i - 1)) - len) < 0 ? NEURONSPI_MAX_TX : (len - (NEURONSPI_MAX_TX * (i - 2)));
                                } else {
                                        s_trans[i].tx_buf = &(send_buf[NEURONSPI_MAX_TX * (i - 1)]);
                                        s_trans[i].rx_buf = &(recv_buf[NEURONSPI_MAX_TX * (i - 1)]);
@@ -724,73 +823,60 @@ int neuronspi_spi_send_message(struct spi_device* spi_dev, u8 *send_buf, u8 *rec
                                // If len is more than NEURONSPI_MAX_TX * i (+ optionally header), then chunk len is NEURONSPI_MAX_TX (+ optionally header),
                                // otherwise it's the remainder
                        }
-                       spi_message_add_tail(&(s_trans[i]), s_msg);
-               }
-               spi_sync(spi_dev, s_msg);
-               for (i = 0; i < trans_count; i++) {
-                       spi_transfer_del(&(s_trans[i]));
+                       //spi_message_add_tail(&(s_trans[i]), s_msg);
                }
+               //spi_sync(spi_dev, s_msg);
+               spi_sync_transfer(spi_dev, s_trans, trans_count);
+               //for (i = 0; i < trans_count; i++) {
+               //      spi_transfer_del(&(s_trans[i]));
+               //}
            kfree(s_trans);
-           kfree(s_msg);
-#if NEURONSPI_DETAILED_DEBUG > 1
-               printk(KERN_INFO "UNIPISPI: SPI Master Read - %d:\n\t%100ph\n\t%100ph\n\t%100ph\n\t%100ph\n", len,recv_buf, &recv_buf[64],
+           //kfree(s_msg);
+               unipi_spi_trace_1(KERN_INFO "UNIPISPI: SPI Master Read - %d:\n\t%100ph\n\t%100ph\n\t%100ph\n\t%100ph\n", len,recv_buf, &recv_buf[64],
                                &recv_buf[128], &recv_buf[192]);
-#endif
+
        }
     if (d_data == NULL || (d_data != NULL && !d_data->reserved_device)) {
                recv_crc1 = neuronspi_spi_crc(recv_buf, 4, 0);
                memcpy(&packet_crc, &recv_buf[4], 2);
-#if NEURONSPI_DETAILED_DEBUG > 1
-               printk(KERN_INFO "UNIPISPI: SPI CRC1: %x\t COMPUTED CRC1:%x\n", packet_crc, recv_crc1);
-#endif
+               unipi_spi_trace_1(KERN_INFO "UNIPISPI: SPI CRC1: %x\t COMPUTED CRC1:%x\n", packet_crc, recv_crc1);
+
                if (recv_crc1 == packet_crc) {
                // Signal the UART to issue character reads
-#if NEURONSPI_DETAILED_DEBUG > 1
-               printk(KERN_INFO "UNIPISPI: SPI CRC1 Correct");
-#endif
-                       mutex_lock(&neuronspi_uart_mutex);
-                       if (d_data && recv_buf[0] == 0x41) {
-                               d_data->uart_buf[0] = recv_buf[3];
-#if NEURONSPI_DETAILED_DEBUG > 0
-                               printk(KERN_INFO "UNIPISPI: Reading UART data for device %d\n", d_data->neuron_index);
-#endif
-                               for (i = 0; i < d_data->uart_data->p_count; i++) {
-                                       if (d_data->uart_data->p[i].dev_index == d_data->neuron_index) {
-                                               neuronspi_uart_handle_rx(&d_data->uart_data->p[i], 1, 1);
+            unipi_spi_trace_1(KERN_INFO "UNIPISPI: SPI CRC1 Correct");
+
+                       if (d_data && ((recv_buf[0] & 0xfd) == 0x41)) {
+                               unipi_spi_trace(KERN_INFO "UNIPISPI: Reading UART data for device %d\n", d_data->neuron_index);
+
+                           if (recv_buf[0] == 0x41) {
+                                       d_data->uart_buf[0] = recv_buf[3];
+                                       for (i = 0; i < d_data->uart_data->p_count; i++) {
+                                               if (d_data->uart_data->p[i].dev_index == d_data->neuron_index) {
+                                                       neuronspi_uart_handle_rx(&d_data->uart_data->p[i], 1, 1);
+                                               }
                                        }
                                }
                                if (!(d_data->uart_read) && (d_data->uart_count)) {
                                        d_data->uart_read = recv_buf[2];
                                        for (i = 0; i < d_data->uart_data->p_count; i++) {
-#if NEURONSPI_DETAILED_DEBUG > 0
-                                       printk(KERN_INFO "UNIPISPI: UART Buffer:%d, UART Local Port Count:%d, UART Global Port Count:%d\n", d_data->uart_read,
+                        unipi_spi_trace(KERN_INFO "UNIPISPI: UART Buffer:%d, UART Local Port Count:%d, UART Global Port Count:%d\n", d_data->uart_read,
                                                        d_data->uart_count,  d_data->uart_data->p_count);
-#endif
+
                                                if (d_data->uart_data->p[i].dev_index == d_data->neuron_index && !d_data->reserved_device) {
                                                        kthread_queue_work(&d_data->uart_data->kworker, &d_data->uart_data->p[i].rx_work);
                                                }
                                        }
                                }
                        }
-                       mutex_unlock(&neuronspi_uart_mutex);
-                       if (d_data && recv_buf[0] == 0x65) {
-                               mutex_lock(&neuronspi_uart_mutex);
-                       }
-               }
-#if NEURONSPI_DETAILED_DEBUG > 0
-               else {
-                       printk(KERN_INFO "UNIPISPI: SPI CRC1 Not Correct");
+               } else {
+                       unipi_spi_trace(KERN_INFO "UNIPISPI: SPI CRC1 Not Correct");
                }
-#endif
                recv_crc2 = neuronspi_spi_crc(&recv_buf[6], len - 8, recv_crc1);
                memcpy(&packet_crc, &recv_buf[len - 2], 2);
-#if NEURONSPI_DETAILED_DEBUG > 1
-               printk(KERN_INFO "UNIPISPI: SPI CRC2: %x\t COMPUTED CRC2:%x\n", packet_crc, recv_crc2);
-#endif
+               unipi_spi_trace_1(KERN_INFO "UNIPISPI: SPI CRC2: %x\t COMPUTED CRC2:%x\n", packet_crc, recv_crc2);
                if (recv_crc2 != packet_crc) {
-#if NEURONSPI_DETAILED_DEBUG > 0
-                       printk(KERN_INFO "UNIPISPI: SPI CRC2 Not Correct");
-#endif
+                       unipi_spi_trace(KERN_INFO "UNIPISPI: SPI CRC2 Not Correct");
+
                        recv_buf[0] = 0;
                        ret_code = 1;
                }
@@ -798,7 +884,7 @@ int neuronspi_spi_send_message(struct spi_device* spi_dev, u8 *send_buf, u8 *rec
     mutex_unlock(&neuronspi_master_mutex);
     return ret_code;
 }
-
+*/
 
 
 irqreturn_t neuronspi_spi_irq(s32 irq, void *dev_id)
@@ -809,9 +895,8 @@ irqreturn_t neuronspi_spi_irq(s32 irq, void *dev_id)
        struct neuronspi_uart_data *u_data;
        spi = (struct spi_device *)dev_id;
        d_data = spi_get_drvdata(spi);
-#if NEURONSPI_DETAILED_DEBUG > 0
-       printk(KERN_INFO "UNIPISPI: SPI IRQ\n");
-#endif
+       unipi_spi_trace(KERN_INFO "UNIPISPI: SPI IRQ\n");
+
        if (d_data->uart_count) {
                u_data = d_data->uart_data;
                for (i = 0; i < u_data->p_count; i++) {
@@ -824,95 +909,16 @@ irqreturn_t neuronspi_spi_irq(s32 irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-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 "UNIPISPI: 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_ATOMIC);
-       recv_buf = kzalloc(NEURONSPI_SPI_LED_SET_MESSAGE_LEN, GFP_ATOMIC);
-       memcpy(message_buf, NEURONSPI_SPI_LED_SET_MESSAGE, NEURONSPI_SPI_LED_SET_MESSAGE_LEN);
-       if (d_data->features != NULL) {
-               message_buf[2] = d_data->features->di_count + d_data->features->do_count + d_data->features->ro_count + id;
-       } else {
-               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, 0);
-       }
-       kfree(message_buf);
-       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_ATOMIC);
-       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);
-       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);
-       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);
-       return ret;
-}
-
-
 
 s32 neuronspi_spi_probe(struct spi_device *spi)
 {
        const struct neuronspi_devtype *devtype;
        struct neuronspi_driver_data *n_spi;
+    struct neuronspi_op_buffer recv_op;
        s32 ret, i, no_irq = 0;
        u8 uart_count = 0;
        unsigned long flags;
+    
        n_spi = kzalloc(sizeof *n_spi, GFP_ATOMIC);
        spin_lock_irqsave(neuronspi_probe_spinlock, flags);
        neuronspi_probe_count++;
@@ -923,9 +929,8 @@ s32 neuronspi_spi_probe(struct spi_device *spi)
        if (n_spi == NULL || spi == NULL) {
                return -8;
        }
-#if NEURONSPI_DETAILED_DEBUG > 0
-       printk(KERN_DEBUG "UNIPISPI: Chip Max Hz-%d\n",spi->master->max_speed_hz);
-#endif
+
+       unipi_spi_trace(KERN_DEBUG "UNIPISPI: Chip Max Hz-%d\n",spi->master->max_speed_hz);
        /* Setup SPI bus */
        spi->bits_per_word      = 8;
        spi->mode               = spi->mode ? spi->mode : SPI_MODE_0;
@@ -942,9 +947,8 @@ s32 neuronspi_spi_probe(struct spi_device *spi)
 
        if (ret)
                return ret;
-#if NEURONSPI_DETAILED_DEBUG > 0
-       printk(KERN_DEBUG "UNIPISPI: Chip Max Hz-%d %d\n", spi->master->max_speed_hz, spi->max_speed_hz);
-#endif
+
+       unipi_spi_trace(KERN_DEBUG "UNIPISPI: Chip Max Hz-%d %d\n", spi->master->max_speed_hz, spi->max_speed_hz);
        if (spi->dev.of_node) {
                const struct of_device_id *of_id =
                        of_match_device(neuronspi_id_match, &spi->dev);
@@ -956,9 +960,8 @@ s32 neuronspi_spi_probe(struct spi_device *spi)
                of_property_read_u32_array(spi->dev.of_node, "neuron-probe-always-succeeds", &(n_spi->probe_always_succeeds), 1);
                of_property_read_u32_array(spi->dev.of_node, "neuron-always-create-tty", &(n_spi->always_create_uart), 1);
                devtype = (struct neuronspi_devtype *)of_id->data;
-#if NEURONSPI_DETAILED_DEBUG > 0
-               printk(KERN_INFO "UNIPISPI: DEVICE TREE NODE FOUND %d\n", n_spi->neuron_index);
-#endif
+               unipi_spi_trace(KERN_INFO "UNIPISPI: DEVICE TREE NODE FOUND %d\n", n_spi->neuron_index);
+
        } else {
                const struct spi_device_id *id_entry = spi_get_device_id(spi);
                devtype = (struct neuronspi_devtype *)id_entry->driver_data;
@@ -974,41 +977,33 @@ s32 neuronspi_spi_probe(struct spi_device *spi)
        }
        sched_setscheduler(n_spi->primary_worker_task, SCHED_FIFO, &neuronspi_sched_param);
 
-
        // We perform an initial probe of registers 1000-1004 to identify the device, using a premade message
-       n_spi->recv_buf = kzalloc(NEURONSPI_BUFFER_MAX, GFP_ATOMIC);
-       n_spi->send_buf = kzalloc(NEURONSPI_BUFFER_MAX, GFP_ATOMIC);
-       n_spi->first_probe_reply = kzalloc(NEURONSPI_PROBE_MESSAGE_LEN, GFP_ATOMIC);    // allocate space for initial probe
-       n_spi->second_probe_reply = kzalloc(NEURONSPI_PROBE_MESSAGE_LEN, GFP_ATOMIC); // allocate space for uart probe
-       n_spi->lower_board_id = 0xFF;
-       n_spi->upper_board_id = 0xFF;
-       n_spi->combination_id = 0xFF;
+       n_spi->first_probe_reply = kzalloc(UNIPISPI_PROBE_MESSAGE_LEN, GFP_ATOMIC);     // allocate space for initial probe
+       n_spi->lower_board_id = n_spi->upper_board_id = n_spi->combination_id = 0xFF;
        n_spi->spi_driver = &neuronspi_spi_driver;
 
-       memcpy(n_spi->send_buf, &NEURONSPI_PROBE_MESSAGE, NEURONSPI_PROBE_MESSAGE_LEN);
-       neuronspi_spi_send_message(spi, n_spi->send_buf, n_spi->first_probe_reply, NEURONSPI_PROBE_MESSAGE_LEN, NEURONSPI_DEFAULT_FREQ, 25, 1, 0);
-
+       neuronspi_spi_send_const_op(spi, &UNIPISPI_IDLE_MESSAGE, &recv_op, 0, NEURONSPI_DEFAULT_FREQ, 25);
        // Throw away the first message - the associated SPI Master is sometimes not properly initialised at this point
+
+    recv_op.second_message = n_spi->first_probe_reply;
        i = 0;
        do {
-               memcpy(n_spi->send_buf, &NEURONSPI_PROBE_MESSAGE, NEURONSPI_PROBE_MESSAGE_LEN);
-               memset(n_spi->first_probe_reply, 0, NEURONSPI_PROBE_MESSAGE_LEN);
-               neuronspi_spi_send_message(spi, n_spi->send_buf, n_spi->first_probe_reply, NEURONSPI_PROBE_MESSAGE_LEN, NEURONSPI_DEFAULT_FREQ, 25, 1, 0);
+        neuronspi_spi_send_const_op(spi, &UNIPISPI_PROBE_MESSAGE, &recv_op, UNIPISPI_PROBE_MESSAGE_LEN, NEURONSPI_DEFAULT_FREQ, 25);
                i++;
-       } while (n_spi->first_probe_reply[0] == 0x41 && i < 1000);      // UART messages should be ignored
+       } while (n_spi->first_probe_reply[0] == 0 && i < 5);
 
        if (n_spi->first_probe_reply[0] != 0) {         // CRC error sets the first byte to 0
-               uart_count = n_spi->first_probe_reply[14] & 0x0f;
+               uart_count = n_spi->first_probe_reply[14-6] & 0x0f;
                for (i = 0; i < NEURONSPI_BOARDTABLE_LEN; i++) {
-                       if (n_spi->first_probe_reply[19] == NEURONSPI_BOARDTABLE[i].lower_board_id) {
+                       if (n_spi->first_probe_reply[19-6] == NEURONSPI_BOARDTABLE[i].lower_board_id) {
                                if (n_spi->combination_id == 0xFF && NEURONSPI_BOARDTABLE[i].upper_board_id == 0) {
                                        n_spi->combination_id = NEURONSPI_BOARDTABLE[i].index;
                                }
                                if (n_spi->lower_board_id == 0xFF) {
-                                       n_spi->lower_board_id = n_spi->first_probe_reply[17];
+                                       n_spi->lower_board_id = n_spi->first_probe_reply[17-6];
                                }
-                               if (n_spi->first_probe_reply[17] == NEURONSPI_BOARDTABLE[i].index) {
-                                       n_spi->combination_id = n_spi->first_probe_reply[17];
+                               if (n_spi->first_probe_reply[17-6] == NEURONSPI_BOARDTABLE[i].index) {
+                                       n_spi->combination_id = n_spi->first_probe_reply[17-6];
                                        n_spi->upper_board_id = NEURONSPI_BOARDTABLE[i].upper_board_id;
                                }
                        }
@@ -1031,7 +1026,7 @@ s32 neuronspi_spi_probe(struct spi_device *spi)
 
        n_spi->ideal_frequency = NEURONSPI_COMMON_FREQ;
        for (i = 0; i < NEURONSPI_SLOWER_MODELS_LEN; i++) {
-               if (NEURONSPI_SLOWER_MODELS[i] == (n_spi->first_probe_reply[19] << 8 | n_spi->first_probe_reply[18])) {
+               if (NEURONSPI_SLOWER_MODELS[i] == (n_spi->first_probe_reply[19-6] << 8 | n_spi->first_probe_reply[18-6])) {
                        n_spi->slower_model = 1;
                        n_spi->ideal_frequency = NEURONSPI_SLOWER_FREQ;
                }
@@ -1041,24 +1036,24 @@ s32 neuronspi_spi_probe(struct spi_device *spi)
 Uart count: %d - reg1000: %x, reg1001: %x, reg1002: %x, reg1003: %x, reg1004: %x\n",
                                NEURONSPI_BOARDTABLE[n_spi->combination_id].definition->combination_name,
                                n_spi->lower_board_id, n_spi->upper_board_id, n_spi->combination_id,  n_spi->neuron_index,
-                               n_spi->first_probe_reply[11],  n_spi->first_probe_reply[10], spi->chip_select, uart_count,
-                               n_spi->first_probe_reply[11] << 8 | n_spi->first_probe_reply[10],
-                               n_spi->first_probe_reply[13] << 8 | n_spi->first_probe_reply[12], n_spi->first_probe_reply[15] << 8 | n_spi->first_probe_reply[14],
-                               n_spi->first_probe_reply[17] << 8 | n_spi->first_probe_reply[16], n_spi->first_probe_reply[19] << 8 | n_spi->first_probe_reply[18]);
+                               n_spi->first_probe_reply[11-6],  n_spi->first_probe_reply[10-6], spi->chip_select, uart_count,
+                               n_spi->first_probe_reply[11-6] << 8 | n_spi->first_probe_reply[10-6],
+                               n_spi->first_probe_reply[13-6] << 8 | n_spi->first_probe_reply[12-6], n_spi->first_probe_reply[15-6] << 8 | n_spi->first_probe_reply[14-6],
+                               n_spi->first_probe_reply[17-6] << 8 | n_spi->first_probe_reply[16-6], n_spi->first_probe_reply[19-6] << 8 | n_spi->first_probe_reply[18-6]);
        } else if (n_spi->lower_board_id != 0xFF) {
                printk(KERN_INFO "UNIPISPI: Probe detected UniPi Board L:%x C:??? Index: %d Fw: v%d.%d on CS %d, Uart count: %d - reg1000: %x, \
 reg1001: %x, reg1002: %x, reg1003: %x, reg1004: %x\n",
-                               n_spi->lower_board_id, n_spi->neuron_index, n_spi->first_probe_reply[11],  n_spi->first_probe_reply[10],
-                               spi->chip_select, uart_count, n_spi->first_probe_reply[11] << 8 | n_spi->first_probe_reply[10],
-                               n_spi->first_probe_reply[13] << 8 | n_spi->first_probe_reply[12], n_spi->first_probe_reply[15] << 8 | n_spi->first_probe_reply[14],
-                               n_spi->first_probe_reply[17] << 8 | n_spi->first_probe_reply[16], n_spi->first_probe_reply[19] << 8 | n_spi->first_probe_reply[18]);
+                               n_spi->lower_board_id, n_spi->neuron_index, n_spi->first_probe_reply[11-6],  n_spi->first_probe_reply[10-6],
+                               spi->chip_select, uart_count, n_spi->first_probe_reply[11-6] << 8 | n_spi->first_probe_reply[10-6],
+                               n_spi->first_probe_reply[13-6] << 8 | n_spi->first_probe_reply[12-6], n_spi->first_probe_reply[15-6] << 8 | n_spi->first_probe_reply[14-6],
+                               n_spi->first_probe_reply[17-6] << 8 | n_spi->first_probe_reply[16-6], n_spi->first_probe_reply[19-6] << 8 | n_spi->first_probe_reply[18-6]);
        } else {
                printk(KERN_INFO "UNIPISPI: Probe detected UniPi Board L:??? C:??? Index: %d Fw: v%d.%d on CS %d, Uart count: %d - reg1000: %x, \
 reg1001: %x, reg1002: %x, reg1003: %x, reg1004: %x\n",
-                               n_spi->neuron_index, n_spi->first_probe_reply[11],  n_spi->first_probe_reply[10], spi->chip_select, uart_count,
-                               n_spi->first_probe_reply[11] << 8 | n_spi->first_probe_reply[10], n_spi->first_probe_reply[13] << 8 | n_spi->first_probe_reply[12],
-                               n_spi->first_probe_reply[15] << 8 | n_spi->first_probe_reply[14], n_spi->first_probe_reply[17] << 8 | n_spi->first_probe_reply[16],
-                               n_spi->first_probe_reply[19] << 8 | n_spi->first_probe_reply[18]);
+                               n_spi->neuron_index, n_spi->first_probe_reply[11-6],  n_spi->first_probe_reply[10-6], spi->chip_select, uart_count,
+                               n_spi->first_probe_reply[11-6] << 8 | n_spi->first_probe_reply[10-6], n_spi->first_probe_reply[13-6] << 8 | n_spi->first_probe_reply[12-6],
+                               n_spi->first_probe_reply[15-6] << 8 | n_spi->first_probe_reply[14-6], n_spi->first_probe_reply[17-6] << 8 | n_spi->first_probe_reply[16-6],
+                               n_spi->first_probe_reply[19-6] << 8 | n_spi->first_probe_reply[18-6]);
        }
        if (n_spi->combination_id != 0xFF) {
                printk(KERN_INFO "UNIPISPI: UniPi device %s on CS %d uses SPI communication freq. %d Hz\n",
@@ -1097,17 +1092,15 @@ reg1001: %x, reg1002: %x, reg1003: %x, reg1004: %x\n",
                if (ret) {
                        printk(KERN_ERR "UNIPISPI: Failed to register the neuronspi uart driver, ERR:%d\n", ret);
                } else {
-#if NEURONSPI_DETAILED_DEBUG > 0
-                       printk(KERN_DEBUG "UNIPISPI: UART driver registered successfully!\n");
-#endif
+                       unipi_spi_trace(KERN_DEBUG "UNIPISPI: UART driver registered successfully!\n");
+
                }
                if (neuronspi_uart_glob_data != NULL) {
                        printk(KERN_ERR "UNIPISPI: Uart data already allocated!\n");
                } else {
                        neuronspi_uart_glob_data = kzalloc(sizeof(struct neuronspi_uart_data), GFP_ATOMIC);
-#if NEURONSPI_DETAILED_DEBUG > 0
-                       printk(KERN_DEBUG "UNIPISPI: UART driver data allocated successfully!\n");
-#endif
+                       unipi_spi_trace(KERN_DEBUG "UNIPISPI: UART driver data allocated successfully!\n");
+
                }
 
        }
@@ -1122,9 +1115,8 @@ reg1001: %x, reg1002: %x, reg1003: %x, reg1004: %x\n",
        }
        n_spi->uart_count = uart_count;
 
-#if NEURONSPI_DETAILED_DEBUG > 0
-       printk(KERN_DEBUG "UNIPISPI: CHIP SELECT %d\n", spi->chip_select);
-#endif
+       unipi_spi_trace(KERN_DEBUG "UNIPISPI: CHIP SELECT %d\n", spi->chip_select);
+
        spin_lock_irqsave(neuronspi_probe_spinlock, flags);
        neuronspi_s_dev[n_spi->neuron_index] = spi;
        spi_set_drvdata(neuronspi_s_dev[n_spi->neuron_index], n_spi);
@@ -1135,9 +1127,8 @@ reg1001: %x, reg1002: %x, reg1003: %x, reg1004: %x\n",
        if (neuronspi_model_id != -1) {
                printk(KERN_INFO "UNIPISPI: Detected UniPi board combination corresponding to %s\n", NEURONSPI_MODELTABLE[neuronspi_model_id].model_name);
        }
-#if NEURONSPI_DETAILED_DEBUG > 0
-       printk(KERN_DEBUG "UNIPISPI: SPI IRQ: %d", spi->irq);
-#endif
+
+       unipi_spi_trace(KERN_DEBUG "UNIPISPI: SPI IRQ: %d", spi->irq);
        strcpy(n_spi->platform_name, "io_group0");
        n_spi->platform_name[8] = n_spi->neuron_index + '1';
        n_spi->board_device = platform_device_alloc(n_spi->platform_name, -1);
@@ -1326,21 +1317,17 @@ reg1001: %x, reg1002: %x, reg1003: %x, reg1004: %x\n",
        }
 
        if (uart_count) {
-#if NEURONSPI_DETAILED_DEBUG > 0
-               printk(KERN_DEBUG "UNIPISPI: UART registration 1\n");
-#endif
+               unipi_spi_trace(KERN_DEBUG "UNIPISPI: UART registration 1\n");
+
                n_spi->uart_buf = kzalloc(NEURONSPI_FIFO_SIZE, GFP_ATOMIC);
                neuronspi_uart_probe(spi, n_spi->neuron_index);
-#if NEURONSPI_DETAILED_DEBUG > 0
-               printk(KERN_DEBUG "UNIPISPI: UART PROBE MCTRL:%d\n", neuronspi_spi_uart_get_cflag(spi, 0));
-#endif
+               //unipi_spi_trace(KERN_DEBUG "UNIPISPI: UART PROBE MCTRL:%d\n", neuronspi_spi_uart_get_cflag(spi, 0));
        }
-#if NEURONSPI_DETAILED_DEBUG > 0
-       printk(KERN_DEBUG "UNIPISPI: UART registration\n");
-#endif
+       unipi_spi_trace(KERN_DEBUG "UNIPISPI: UART registration\n");
+
        neuronspi_spi_set_irqs(spi, 0x5);
        for (i = 0; i < NEURONSPI_NO_INTERRUPT_MODELS_LEN; i++) {
-               if (NEURONSPI_NO_INTERRUPT_MODELS[i] == (n_spi->first_probe_reply[17] << 8 | n_spi->first_probe_reply[16])) {
+               if (NEURONSPI_NO_INTERRUPT_MODELS[i] == (n_spi->first_probe_reply[17-6] << 8 | n_spi->first_probe_reply[16-6])) {
                        no_irq = 1;
                }
        }
@@ -1349,48 +1336,15 @@ reg1001: %x, reg1002: %x, reg1003: %x, reg1004: %x\n",
        if (!no_irq) {
                n_spi->no_irq = 0;
                ret = devm_request_irq(&(spi->dev), spi->irq, neuronspi_spi_irq, 0x81, dev_name(&(spi->dev)), spi);
-#if NEURONSPI_DETAILED_DEBUG > 0
-               printk(KERN_DEBUG "UNIPISPI: IRQ registration, ret:%d\n", ret);
-#endif
+               unipi_spi_trace(KERN_DEBUG "UNIPISPI: IRQ registration, ret:%d\n", ret);
        } else {
                n_spi->no_irq = 1;
-#if NEURONSPI_DETAILED_DEBUG > 0
-               printk(KERN_DEBUG "UNIPISPI: NO IRQ ON THIS MODEL !!\n");
-#endif
+               unipi_spi_trace(KERN_DEBUG "UNIPISPI: NO IRQ ON THIS MODEL !!\n");
        }
 
        return ret;
 }
 
-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_ATOMIC);
-       recv_buf = kzalloc(NEURONSPI_SPI_UART_GET_CFLAG_MESSAGE_LEN, GFP_ATOMIC);
-       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, 0);
-       }
-       ret = ((u32*)recv_buf)[5];
-#if NEURONSPI_DETAILED_DEBUG > 0
-       printk(KERN_INFO "UNIPISPI: 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;
@@ -1454,14 +1408,6 @@ s32 neuronspi_spi_remove(struct spi_device *spi)
                        n_spi->sec_ao_driver = NULL;
                }
                printk(KERN_INFO "UNIPISPI: IIO DRIVER UNREGISTERED\n");
-               if (n_spi->send_buf) {
-                       kfree(n_spi->send_buf);
-                       n_spi->send_buf = NULL;
-               }
-               if (n_spi->recv_buf) {
-                       kfree(n_spi->recv_buf);
-                       n_spi->recv_buf = NULL;
-               }
                if (n_spi->uart_buf) {
                        kfree(n_spi->uart_buf);
                        n_spi->uart_buf = NULL;
@@ -1481,17 +1427,14 @@ s32 char_register_driver(void)
        s32 ret = 0;
 
        // Character device registration
-#if NEURONSPI_DETAILED_DEBUG > 0
-       printk(KERN_DEBUG "UNIPISPI: Initialising Character Device\n");
-#endif
+       unipi_spi_trace(KERN_DEBUG "UNIPISPI: Initialising Character Device\n");
+
        neuronspi_cdrv.major_number = register_chrdev(0, NEURON_DEVICE_NAME, &file_ops);
        if (neuronspi_cdrv.major_number < 0){
           printk(KERN_ALERT "NEURONSPI: failed to register a major number\n");
           return neuronspi_cdrv.major_number;
        }
-#if NEURONSPI_DETAILED_DEBUG > 0
-       printk(KERN_DEBUG "UNIPISPI: registered correctly with major number %d\n", neuronspi_cdrv.major_number);
-#endif
+       unipi_spi_trace(KERN_DEBUG "UNIPISPI: registered correctly with major number %d\n", neuronspi_cdrv.major_number);
 
        // Character class registration
        neuronspi_cdrv.driver_class = class_create(THIS_MODULE, NEURON_DEVICE_CLASS);
@@ -1500,9 +1443,7 @@ s32 char_register_driver(void)
                printk(KERN_ALERT "NEURONSPI: Failed to register device class\n");
                return PTR_ERR(neuronspi_cdrv.driver_class);
        }
-#if NEURONSPI_DETAILED_DEBUG > 0
-       printk(KERN_DEBUG "UNIPISPI: device class registered correctly\n");
-#endif
+       unipi_spi_trace(KERN_DEBUG "UNIPISPI: device class registered correctly\n");
 
        // Device driver registration
        neuronspi_cdrv.dev = device_create_with_groups(neuronspi_cdrv.driver_class, &(neuron_plc_dev->dev), MKDEV(neuronspi_cdrv.major_number, 0), NULL, neuron_plc_attr_groups, NEURON_DEVICE_NAME);
@@ -1512,9 +1453,8 @@ s32 char_register_driver(void)
                printk(KERN_ALERT "NEURONSPI: Failed to create the device\n");
                return PTR_ERR(neuronspi_cdrv.dev);
        }
-#if NEURONSPI_DETAILED_DEBUG > 0
-       printk(KERN_DEBUG "UNIPISPI: device class created correctly\n");
-#endif
+       unipi_spi_trace(KERN_DEBUG "UNIPISPI: device class created correctly\n");
+
        return ret;
 }
 
@@ -1537,12 +1477,9 @@ MODULE_ALIAS("spi:unipispi");
 static s32 __init neuronspi_init(void)
 {
        s32 ret = 0;
-       neuronspi_spi_w_spinlock = kzalloc(sizeof(struct spinlock), GFP_ATOMIC);
-       spin_lock_init(neuronspi_spi_w_spinlock);
        neuronspi_probe_spinlock = kzalloc(sizeof(struct spinlock), GFP_ATOMIC);
        spin_lock_init(neuronspi_probe_spinlock);
        mutex_init(&neuronspi_master_mutex);
-       mutex_init(&neuronspi_uart_mutex);
        mutex_init(&unipi_inv_speed_mutex);
        memset(&neuronspi_s_dev, 0, sizeof(neuronspi_s_dev));
        ret = spi_register_driver(&neuronspi_spi_driver);
@@ -1568,9 +1505,8 @@ module_init(neuronspi_init);
 
 static void __exit neuronspi_exit(void)
 {
-#if NEURONSPI_DETAILED_DEBUG > 0
-       printk(KERN_INFO "UNIPISPI: Open Counter is %d\n", neuronspi_cdrv.open_counter);
-#endif
+       unipi_spi_trace(KERN_INFO "UNIPISPI: Open Counter is %d\n", neuronspi_cdrv.open_counter);
+
        if (neuronspi_invalidate_thread) {
                kthread_stop(neuronspi_invalidate_thread);
        }
@@ -1585,7 +1521,6 @@ static void __exit neuronspi_exit(void)
        if (neuron_plc_dev) {
                platform_device_unregister(neuron_plc_dev);
        }
-       kfree(neuronspi_spi_w_spinlock);
        printk(KERN_INFO "UNIPISPI: SPI Driver Unregistered\n");
 }
 module_exit(neuronspi_exit);
index ea8fab986c6ee22a0e7c7acd48b248d06405321f..2a881de48e9095f857900b065fb241d3da5f4f34 100644 (file)
@@ -33,6 +33,7 @@ static const u16 NEURONSPI_SLOWER_MODELS[NEURONSPI_SLOWER_MODELS_LEN] = {
                0xb10, 0xc10, 0xf10
 };
 
+/*
 #define NEURONSPI_PROBE_MESSAGE_LEN                                            22
 static const u8 NEURONSPI_PROBE_MESSAGE[NEURONSPI_PROBE_MESSAGE_LEN] = {
                0x04, 0x0e, 0xe8, 0x03, 0xa0, 0xdd,
@@ -40,12 +41,29 @@ static const u8 NEURONSPI_PROBE_MESSAGE[NEURONSPI_PROBE_MESSAGE_LEN] = {
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00,     0x12, 0x16
 };
+*/
+
+#define UNIPISPI_PROBE_MESSAGE_LEN                                             16
+static u8 _probe_message_second[UNIPISPI_PROBE_MESSAGE_LEN] = 
+                   {0x04, 0x00, 0xe8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x16};
+static const struct neuronspi_op_buffer UNIPISPI_PROBE_MESSAGE = {
+    first_message: {0x04, 0x0e, 0xe8, 0x03, 0xa0, 0xdd},
+    second_message: _probe_message_second,
+};
 
+/*
 #define NEURONSPI_UART_PROBE_MESSAGE_LEN                               6
 static const u8 NEURONSPI_UART_PROBE_MESSAGE[NEURONSPI_UART_PROBE_MESSAGE_LEN] = {
                0xfa, 0x00, 0x55, 0x0e, 0xb6, 0x0a
 };
+*/
+
+static const struct neuronspi_op_buffer UNIPISPI_IDLE_MESSAGE = {
+    first_message: {0xfa, 0x00, 0x55, 0x0e, 0xb6, 0x0a},
+    second_message: NULL,
+};
 
+/*
 #define NEURONSPI_SPI_UART_SHORT_MESSAGE_LEN                   6
 static const u8 NEURONSPI_SPI_UART_SHORT_MESSAGE[NEURONSPI_SPI_UART_SHORT_MESSAGE_LEN] = {
                0x41, 0x00, 0x00, 0x00, 0x00, 0x00
@@ -64,8 +82,15 @@ static const u8 NEURONSPI_SPI_UART_READ_MESSAGE[NEURONSPI_SPI_UART_READ_MESSAGE_
                0x6a, 0x0c
 };
 
+#define NEURONSPI_SPI_UART_READ_MESSAGE0_LEN                           14
+static const u8 NEURONSPI_SPI_UART_READ_MESSAGE0[NEURONSPI_SPI_UART_READ_MESSAGE0_LEN] = {
+               0x68, 0x06, 0x00, 0x00, 0x00, 0x00,
+               0x65, 0x03, 0x00, 0x00, 0x00, 0x05,
+               0x6a, 0x0c
+};
+
 #define NEURONSPI_SPI_IRQ_SET_MESSAGE_LEN                              14
-static const u8 NEURONSPI_SPI_IRQ_SET_MESSAGE[NEURONSPI_SPI_UART_READ_MESSAGE_LEN] = {
+static const u8 NEURONSPI_SPI_IRQ_SET_MESSAGE[NEURONSPI_SPI_IRQ_SET_MESSAGE_LEN] = {
                0x06, 0x06, 0xef, 0x03, 0x00, 0x00,
                0x06, 0x01, 0xef, 0x03, 0x05, 0x00,
                0x00, 0x00
@@ -96,6 +121,7 @@ static const u8 NEURONSPI_SPI_UART_SET_CFLAG_MESSAGE[NEURONSPI_SPI_UART_SET_CFLA
 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
 static const u16 NEURONSPI_CRC16TABLE[NEURONSPI_CRC16TABLE_LEN] = {
@@ -147,7 +173,7 @@ static const struct of_device_id neuronspi_id_match[] = {
 #define NEURONSPI_RECONF_IER                           (1 << 1)
 #define NEURONSPI_RECONF_RS485                         (1 << 2)
 
-#define MODBUS_FIRST_DATA_BYTE                         10
+//#define MODBUS_FIRST_DATA_BYTE                               10
 
 #define MODBUS_MAX_READ_BITS                2000
 #define MODBUS_MAX_WRITE_BITS               1968
@@ -156,6 +182,10 @@ static const struct of_device_id neuronspi_id_match[] = {
 #define MODBUS_MAX_WR_WRITE_REGISTERS       121
 #define MODBUS_MAX_WR_READ_REGISTERS        125
 
+#define UNIPISPI_OP_MODE_SEND_HEADER        0x1
+#define UNIPISPI_OP_MODE_DO_CRC             0x2
+#define UNIPISPI_OP_MODE_HAVE_CRC_SPACE     0x4
+
 /*************************
  * Function Declarations *
  *************************/
@@ -169,10 +199,28 @@ s32 char_unregister_driver(void);
 irqreturn_t neuronspi_spi_irq(s32 irq, void *dev_id);
 s32 neuronspi_spi_probe(struct spi_device *spi);
 s32 neuronspi_spi_remove(struct spi_device *spi);
-int neuronspi_spi_send_message(struct spi_device *spi_dev, u8 *send_buf, u8 *recv_buf, s32 len, s32 freq, s32 delay, s32 send_header, u8 lock_val);
-s32 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, s32 len, u8 uart_index);
+
+int neuronspi_spi_send_const_op(struct spi_device* spi_dev, const struct neuronspi_op_buffer* send_buf,
+                            struct neuronspi_op_buffer* recv_buf, s32 len, 
+                            s32 freq, s32 delay);
+int neuronspi_spi_send_op(struct spi_device* spi_dev, struct neuronspi_op_buffer* send_buf, 
+                            struct neuronspi_op_buffer* recv_buf, s32 len, 
+                            s32 freq, s32 delay, s32 send_header, u8 lock_val);
+//int neuronspi_spi_send_message_crc(struct spi_device* spi_dev, struct neuronspi_op_buffer* send_buf, struct neuronspi_op_buffer* recv_buf, s32 len, s32 freq, s32 delay);
+//int neuronspi_spi_send_message(struct spi_device *spi_dev, u8 *send_buf, u8 *recv_buf, s32 len, s32 freq, s32 delay, s32 send_header, u8 lock_val);
+s32 neuronspi_spi_uart_write(struct spi_device *spi, u8 *send_buf, int length, u8 uart_index);
+//void neuronspi_spi_uart_read(struct spi_device* spi_dev, u8 *send_buf, u8 *recv_buf, s32 len, u8 uart_index);
+void neuronspi_spi_uart_read(struct spi_device* spi_dev, u8 *recv_buf, s32 len, u8 uart_index);
+int unipispi_modbus_read_register(struct spi_device* spi_dev, u16 reg, u16* value);
+int unipispi_modbus_read_u32(struct spi_device* spi_dev, u16 reg, u32* value);
+int unipispi_modbus_read_many(struct spi_device* spi_dev, u16 reg, u16* value, int register_count);
+int unipispi_modbus_write_register(struct spi_device* spi_dev, u16 reg, u16 value);
+int unipispi_modbus_write_u32(struct spi_device* spi_dev, u16 reg, u32 value);
+int unipispi_modbus_write_many(struct spi_device* spi_dev, u16 reg, u16* value, int register_count);
+int unipispi_modbus_write_coil(struct spi_device* spi_dev, u16 coil, int value);
+
 void neuronspi_spi_set_irqs(struct spi_device* spi_dev, u16 to);
+/*
 void neuronspi_spi_led_set_brightness(struct spi_device* spi_dev, enum led_brightness brightness, int id);
 void neuronspi_spi_iio_stm_ai_read_voltage(struct iio_dev *iio_dev, struct iio_chan_spec const *ch, int *val, int *val2, long mask);
 void neuronspi_spi_iio_stm_ai_read_current(struct iio_dev *iio_dev, struct iio_chan_spec const *ch, int *val, int *val2, long mask);
@@ -183,6 +231,7 @@ void neuronspi_spi_iio_sec_ai_read_voltage(struct iio_dev *iio_dev, struct iio_c
 void neuronspi_spi_iio_sec_ai_read_current(struct iio_dev *iio_dev, struct iio_chan_spec const *ch, int *val, int *val2, long mask);
 void neuronspi_spi_iio_sec_ai_read_resistance(struct iio_dev *iio_dev, struct iio_chan_spec const *ch, int *val, int *val2, long mask);
 void neuronspi_spi_iio_sec_ao_set_voltage(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int val, int val2, long mask);
+ */ 
 int neuronspi_spi_gpio_do_set(struct spi_device* spi_dev, u32 id, int value);
 int neuronspi_spi_gpio_ro_set(struct spi_device* spi_dev, u32 id, int value);
 int neuronspi_spi_gpio_di_get(struct spi_device* spi_dev, u32 id);
@@ -197,7 +246,6 @@ extern struct spi_driver neuronspi_spi_driver;
 extern struct file_operations file_ops;
 
 extern struct mutex unipi_inv_speed_mutex;
-extern struct mutex neuronspi_uart_mutex;
 
 static const struct regmap_bus neuronspi_regmap_bus =
 {
@@ -347,6 +395,7 @@ static __always_inline u16 neuronspi_spi_crc(u8* inputstring, s32 length, u16 in
     return result;
 }
 
+/*
 static __always_inline size_t neuronspi_spi_compose_single_coil_write(u16 start, u8 **buf_inp, u8 **buf_outp, u8 data)
 {
        u16 crc1;
@@ -487,5 +536,6 @@ static __always_inline size_t neuronspi_spi_compose_multiple_register_read(u8 nu
        memcpy(&(*buf_inp)[10 + (number * 2)], &crc2, 2);
        return 12 + (number * 2);
 }
+*/
 
 #endif /* MODULES_NEURON_SPI_SRC_UNIPI_SPI_H_ */
index 10c12614394546c42d1814a814c8e0e3a66f84c8..67b5fa21eb81b6f87a3419f18ac74707d3edc06b 100644 (file)
@@ -193,9 +193,10 @@ err_end:
 static ssize_t neuronspi_spi_show_uart_timeout(struct device *dev, struct device_attribute *attr, char *buf)
 {
        ssize_t ret = 0;
-       u32 val = 0;
+       u16 value = 0;
+/*     u32 val = 0;
        u8 *inp_buf, *outp_buf;
-       int read_length;
+       int read_length; */
        struct spi_device *spi;
        struct neuronspi_driver_data *n_spi;
        struct platform_device *plat = to_platform_device(dev);
@@ -205,13 +206,18 @@ static ssize_t neuronspi_spi_show_uart_timeout(struct device *dev, struct device
 #endif
        spi = neuronspi_s_dev[n_spi->neuron_index];
        if (n_spi && n_spi->combination_id != 0xFF && n_spi->reg_map && n_spi->regstart_table->uart_conf_reg) {
+        if (unipispi_modbus_read_register(spi, 504, &value) == 0) {
+             ret = scnprintf(buf, 255, "%d\n", value);
+        }
+        /*
                read_length = neuronspi_spi_compose_single_register_read(504, &inp_buf, &outp_buf);
-               neuronspi_spi_send_message(spi, inp_buf, outp_buf, read_length, n_spi->ideal_frequency, 25, 1, 0);
+               neuronspi___spi_send_message(spi, inp_buf, outp_buf, read_length, n_spi->ideal_frequency, 25, 1, 0);
                val = outp_buf[11];
                memcpy(&val, &outp_buf[NEURONSPI_HEADER_LENGTH], sizeof(u16));
                kfree(inp_buf);
                kfree(outp_buf);
                ret = scnprintf(buf, 255, "%d\n", val);
+         */ 
        }
        return ret;
 }
@@ -220,8 +226,8 @@ static ssize_t neuronspi_spi_store_uart_timeout(struct device *dev, struct devic
 {
        ssize_t err = 0;
        unsigned int val = 0;
-       u8 *inp_buf, *outp_buf;
-       int write_length;
+/*     u8 *inp_buf, *outp_buf;
+       int write_length;*/
        struct spi_device *spi;
        struct neuronspi_driver_data *n_spi;
        struct platform_device *plat = to_platform_device(dev);
@@ -233,10 +239,13 @@ static ssize_t neuronspi_spi_store_uart_timeout(struct device *dev, struct devic
        err = kstrtouint(buf, 0, &val);
        if (err < 0) goto err_end;
        if (n_spi && n_spi->combination_id != 0xFF && n_spi->reg_map && n_spi->regstart_table->uart_conf_reg) {
+        unipispi_modbus_write_register(spi, 504, val);
+/*
                write_length = neuronspi_spi_compose_single_register_write(504, &inp_buf, &outp_buf, val);
-               neuronspi_spi_send_message(spi, inp_buf, outp_buf, write_length, n_spi->ideal_frequency, 25, 1, 0);
+               neuronspi___spi_send_message(spi, inp_buf, outp_buf, write_length, n_spi->ideal_frequency, 25, 1, 0);
                kfree(inp_buf);
                kfree(outp_buf);
+*/
        }
 err_end:
        return count;
@@ -286,6 +295,7 @@ static ssize_t neuronspi_spi_show_watchdog_timeout(struct device *dev, struct de
        return ret;
 }
 
+#if 1
 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;
@@ -296,11 +306,36 @@ static ssize_t neuronspi_spi_store_watchdog_timeout(struct device *dev, struct d
        err = kstrtouint(buf, 0, &val);
        if (err < 0) goto err_end;
        if (n_spi && n_spi->combination_id != 0xFF && n_spi->reg_map) {
+        if (val > 0xffff) val = 0xffff;
                regmap_write(n_spi->reg_map, n_spi->regstart_table->wd_timeout_reg, val);
        }
 err_end:
        return count;
 }
+#else
+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 spi_device *spi;
+       struct neuronspi_driver_data *n_spi;
+       struct platform_device *plat = to_platform_device(dev);
+       n_spi = platform_get_drvdata(plat);
+#if NEURONSPI_DETAILED_DEBUG > 0
+       printk(KERN_INFO "UNIPISPI: Index %d\n", n_spi->neuron_index);
+#endif
+       spi = neuronspi_s_dev[n_spi->neuron_index];
+       err = kstrtouint(buf, 0, &val);
+       if ((err < 0) || (val < 0)) goto err_end;
+       if (n_spi && n_spi->combination_id != 0xFF && n_spi->reg_map) {
+        if (val > 0xffff) val = 0xffff;
+        unipispi_modbus_write_register(spi, n_spi->regstart_table->wd_timeout_reg, val);
+       }
+err_end:
+       return count;
+}
+#endif
+
 
 static ssize_t neuronspi_spi_gpio_show_pwm_presc(struct device *dev, struct device_attribute *attr, char *buf)
 {
@@ -713,10 +748,11 @@ err_end:
 
 static ssize_t neuronspi_spi_show_register(struct device *dev, struct device_attribute *attr, char *buf)
 {
-       u8 *inp_buf, *outp_buf;
-       int read_length;
+       /*u8 *inp_buf, *outp_buf;
+       int read_length;*/
        ssize_t ret = 0;
        u16 val = 0;
+    u16 reg;
        unsigned long flags;
        struct neuronspi_driver_data *n_spi;
        struct spi_device *spi;
@@ -725,53 +761,61 @@ static ssize_t neuronspi_spi_show_register(struct device *dev, struct device_att
        spi = neuronspi_s_dev[n_spi->neuron_index];
        if (n_spi && n_spi->reg_map) {
                spin_lock_irqsave(&n_spi->sysfs_regmap_lock, flags);
-               read_length = neuronspi_spi_compose_single_register_read(n_spi->sysfs_register_target, &inp_buf, &outp_buf);
+        reg = n_spi->sysfs_register_target;
+               /*read_length = neuronspi_spi_compose_single_register_read(n_spi->sysfs_register_target, &inp_buf, &outp_buf);*/
                spin_unlock_irqrestore(&n_spi->sysfs_regmap_lock, flags);
-               neuronspi_spi_send_message(spi, inp_buf, outp_buf, read_length, n_spi->ideal_frequency, 125, 1, 0);
+        if (unipispi_modbus_read_register(spi, reg, &val)==0) {
+            ret = scnprintf(buf, 255, "%x\n", (u32)val);
+        }
+        /*neuronspi___spi_send_message(spi, inp_buf, outp_buf, read_length, n_spi->ideal_frequency, 125, 1, 0);
                memcpy(&val, &outp_buf[NEURONSPI_HEADER_LENGTH], sizeof(u16));
-               ret = scnprintf(buf, 255, "%x\n", (u32)val);
+               ret = scnprintf(buf, 255, "%x\n", (u32)val); */
        }
        return ret;
 }
 
-static ssize_t neuronspi_spi_store_register(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+static ssize_t neuronspi_spi_store_register_value(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
+       /*u8 *inp_buf, *outp_buf;
+       int write_length;*/
        ssize_t err = 0;
        unsigned int val = 0;
+    u16 reg;
        unsigned long flags;
        struct neuronspi_driver_data *n_spi;
+       struct spi_device *spi;
        struct platform_device *plat = to_platform_device(dev);
        n_spi = platform_get_drvdata(plat);
+       spi = neuronspi_s_dev[n_spi->neuron_index];
        err = kstrtouint(buf, 0, &val);
        if (err < 0) goto err_end;
-       if (n_spi && n_spi->reg_map && val < 65536) {
+       if (n_spi && n_spi->reg_map && (val < 65536) && (val >= 0)) {
                spin_lock_irqsave(&n_spi->sysfs_regmap_lock, flags);
-               n_spi->sysfs_register_target = val;
+        reg = n_spi->sysfs_register_target;
+               //write_length = neuronspi_spi_compose_single_register_read(n_spi->sysfs_register_target, &inp_buf, &outp_buf);
                spin_unlock_irqrestore(&n_spi->sysfs_regmap_lock, flags);
+        unipispi_modbus_write_register(spi, reg, val);
+               //neuronspi___spi_send_message(spi, inp_buf, outp_buf, write_length, n_spi->ideal_frequency, 125, 1, 0);
        }
 err_end:
        return count;
 }
 
-static ssize_t neuronspi_spi_store_register_value(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+
+static ssize_t neuronspi_spi_store_register(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
-       u8 *inp_buf, *outp_buf;
-       int write_length;
        ssize_t err = 0;
        unsigned int val = 0;
        unsigned long flags;
        struct neuronspi_driver_data *n_spi;
-       struct spi_device *spi;
        struct platform_device *plat = to_platform_device(dev);
        n_spi = platform_get_drvdata(plat);
-       spi = neuronspi_s_dev[n_spi->neuron_index];
        err = kstrtouint(buf, 0, &val);
        if (err < 0) goto err_end;
        if (n_spi && n_spi->reg_map && val < 65536) {
                spin_lock_irqsave(&n_spi->sysfs_regmap_lock, flags);
-               write_length = neuronspi_spi_compose_single_register_read(n_spi->sysfs_register_target, &inp_buf, &outp_buf);
+               n_spi->sysfs_register_target = val;
                spin_unlock_irqrestore(&n_spi->sysfs_regmap_lock, flags);
-               neuronspi_spi_send_message(spi, inp_buf, outp_buf, write_length, n_spi->ideal_frequency, 125, 1, 0);
        }
 err_end:
        return count;
@@ -1098,7 +1142,7 @@ static ssize_t neuronspi_iio_store_external_ai_mode(struct device *dev, struct d
 err_end:
        return count;
 }
-
+/*
 static ssize_t neuronspi_iio_show_external_ao_mode(struct device *dev, struct device_attribute *attr, char *buf)
 {
        int ret = 0;
@@ -1128,6 +1172,7 @@ static ssize_t neuronspi_iio_store_external_ao_mode(struct device *dev, struct d
 err_end:
        return count;
 }
+*/
 
 /**********************************
  * Function Structure Definitions *
index a6aa074157fe0e1c73b810c72a12860522319ee9..1e21a115fb6ef8eeb5f4a94646c4d8a90f7c0886 100644 (file)
@@ -69,7 +69,7 @@
 
 
 // #undef UNIPI_TTY_TRACE
-#ifdef NEURONSPI_DETAILED_DEBUG
+#if NEURONSPI_DETAILED_DEBUG > 0
 # define unipi_tty_trace(f, args...)   trace_printk(f, ##args)
 #else
 # define unipi_tty_trace(f, args...)
index 56e7b9c6b6f11f7d2b86c59ee873aa4c0ccb75c7..96d50fef65aaa081805121e59eb24021a97e8c46 100644 (file)
 #include "unipi_uart.h"
 #include "unipi_spi.h"
 
+#if NEURONSPI_DETAILED_DEBUG > 2
+# define unipi_uart_trace_2(f, args...)        printk(f, ##args)
+#else
+# define unipi_uart_trace_2(f, args...)
+#endif
+
+#if NEURONSPI_DETAILED_DEBUG > 1
+# define unipi_uart_trace_1(f, args...)        printk(f, ##args)
+#else
+# define unipi_uart_trace_1(f, args...)
+#endif
+
+#if NEURONSPI_DETAILED_DEBUG > 0
+# define unipi_uart_trace(f, args...)  printk(f, ##args)
+#else
+# define unipi_uart_trace(f, args...)
+#endif
+
 /********************
  * Data Definitions *
  ********************/
@@ -32,47 +50,54 @@ static struct sched_param neuronspi_sched_param = { .sched_priority = MAX_RT_PRI
 /********************
  * Static Functions *
  ********************/
+void neuronspi_uart_update_timeout(struct neuronspi_port *n_port, unsigned int cflag, unsigned int baud);
+
+void neuronspi_uart_set_cflag(struct spi_device* spi_dev, u8 port, u32 to)
+{
+    unipispi_modbus_write_u32(spi_dev, 500, to);
+       unipi_uart_trace(KERN_INFO "UNIPI_UART: TERMIOS cflag SET, Dev-CS:%d, to:%08x\n", spi_dev->chip_select, to);
+}
+
 
 static void neuronspi_uart_set_iflags(struct uart_port *port, int to)
 {
-       u8 *inp_buf, *outp_buf;
-       int write_length;
        struct neuronspi_port *n_port;
        struct spi_device *spi;
-       struct neuronspi_driver_data *n_spi;
        n_port = to_neuronspi_port(port, port);
        spi = neuronspi_s_dev[n_port->dev_index];
-       n_spi = spi_get_drvdata(spi);
-#if NEURONSPI_DETAILED_DEBUG > 0
-       printk(KERN_INFO "UNIPISPI: SET PARMRK to %d\n", to);
-#endif
+       //n_spi = spi_get_drvdata(spi);
+       unipi_uart_trace(KERN_INFO "UNIPI_UART: TERMIOS iflag SET: %s\n", to ? "PARMRK" : "0");
+
+    unipispi_modbus_write_register(spi, NEURONSPI_UART_IFLAGS_REGISTER, to);
+/*
        write_length = neuronspi_spi_compose_single_register_write(NEURONSPI_UART_IFLAGS_REGISTER, &inp_buf, &outp_buf, to);
-       neuronspi_spi_send_message(spi, inp_buf, outp_buf, write_length, n_spi->ideal_frequency, 25, 1, 0);
+       neuronspi___spi_send_message(spi, inp_buf, outp_buf, write_length, n_spi->ideal_frequency, 25, 1, 0);
        kfree(inp_buf);
-       kfree(outp_buf);
+       kfree(outp_buf); */
 }
 
 /************************
  * Non-static Functions *
  ************************/
+u32 neuronspi_spi_uart_get_cflag(struct spi_device* spi_dev, u8 port)
+{
+    u32 value;
+    unipispi_modbus_read_u32(spi_dev, 500, &value);
+       unipi_uart_trace_1(KERN_INFO "UNIPI_UART: SPI TERMIOS cflag GET, Dev-CS:%d, val:%08x\n", spi_dev->chip_select, value);
+    return value;
+}
+
 
 void neuronspi_uart_set_ldisc(struct uart_port *port, struct ktermios *kterm)
 {
-       u8 *inp_buf, *outp_buf;
-       int write_length;
        struct neuronspi_port *n_port;
        struct spi_device *spi;
-       struct neuronspi_driver_data *n_spi;
        n_port = to_neuronspi_port(port, port);
        spi = neuronspi_s_dev[n_port->dev_index];
-       n_spi = spi_get_drvdata(spi);
-#if NEURONSPI_DETAILED_DEBUG > 0
-       printk(KERN_INFO "UNIPISPI: line discipline set\n");
-#endif
-       write_length = neuronspi_spi_compose_single_register_write(NEURONSPI_UART_LDISC_REGISTER, &inp_buf, &outp_buf, kterm->c_line);
-       neuronspi_spi_send_message(spi, inp_buf, outp_buf, write_length, n_spi->ideal_frequency, 25, 1, 0);
-       kfree(inp_buf);
-       kfree(outp_buf);
+       unipi_uart_trace(KERN_INFO "UNIPI_UART: TERMIOS ldisc SET: dsc=%d\n", kterm->c_line);
+
+    unipispi_modbus_write_register(spi, NEURONSPI_UART_LDISC_REGISTER, kterm->c_line);
 }
 
 void neuronspi_uart_tx_proc(struct kthread_work *ws)
@@ -88,24 +113,19 @@ void neuronspi_uart_tx_proc(struct kthread_work *ws)
 
 u32 neuronspi_uart_tx_empty(struct uart_port *port)
 {
-#if NEURONSPI_DETAILED_DEBUG > 0
-       printk(KERN_INFO "UNIPISPI: UART TX Empty\n");
-#endif
+       unipi_uart_trace(KERN_INFO "UNIPISPI: UART TX Empty\n");
        return TIOCSER_TEMT;
 }
 
 u32 neuronspi_uart_get_mctrl(struct uart_port *port)
 {
-#if NEURONSPI_DETAILED_DEBUG > 0
-       printk(KERN_DEBUG "UNIPISPI: UART MCTRL Get\n");
-#endif
+       unipi_uart_trace(KERN_DEBUG "UNIPISPI: UART MCTRL Get\n");
        return TIOCM_DSR | TIOCM_CAR;
 }
 
 int    neuronspi_uart_ioctl (struct uart_port *port, unsigned int ioctl_code, unsigned long ioctl_arg)
 {
-       u8 *inp_buf, *outp_buf;
-       int write_length;
+    u32 value;
        struct neuronspi_port *n_port;
        struct spi_device *spi;
        struct neuronspi_driver_data *n_spi;
@@ -114,35 +134,21 @@ int       neuronspi_uart_ioctl (struct uart_port *port, unsigned int ioctl_code, unsig
        n_spi = spi_get_drvdata(spi);
        switch (ioctl_code) {
        case TIOCSETD: {
-#if NEURONSPI_DETAILED_DEBUG > 0
-               printk(KERN_INFO "UNIPISPI: IOCTL TIOCSETD (processed via set_termios)\n");
-#endif
+               unipi_uart_trace(KERN_INFO "UNIPISPI: IOCTL TIOCSETD (processed via set_termios)\n");
                return 1;
        }
        case 0x5481: {
-#if NEURONSPI_DETAILED_DEBUG > 0
-               printk(KERN_INFO "UNIPISPI: IOCTL 0x5481\n");
-#endif
-               write_length = neuronspi_spi_compose_single_register_write(NEURONSPI_UART_TIMEOUT_REGISTER, &inp_buf, &outp_buf, (ioctl_arg * 1000000) / n_port->baud);
-#if NEURONSPI_DETAILED_DEBUG > 0
-               printk(KERN_INFO "UNIPISPI: val_upper: 0x%x, val_lower: 0x%x", inp_buf[10], inp_buf[11]);
-#endif
-               neuronspi_spi_send_message(spi, inp_buf, outp_buf, write_length, n_spi->ideal_frequency, 25, 1, 0);
-               kfree(inp_buf);
-               kfree(outp_buf);
+        value = ((ioctl_arg * 1000000) / n_port->baud);
+        if (value > 0xffff) value = 0xffff;
+               unipi_uart_trace(KERN_INFO "UNIPISPI: IOCTL 0x5481 timeout=%d\n", value);
+        unipispi_modbus_write_register(spi, NEURONSPI_UART_TIMEOUT_REGISTER, value);
                return 0;
        }
        case 0x5480: {
-#if NEURONSPI_DETAILED_DEBUG > 0
-               printk(KERN_INFO "UNIPISPI: IOCTL 0x5480\n");
-#endif
-               write_length = neuronspi_spi_compose_single_register_write(NEURONSPI_UART_TIMEOUT_REGISTER, &inp_buf, &outp_buf, ioctl_arg * 10);
-#if NEURONSPI_DETAILED_DEBUG > 0
-               printk(KERN_INFO "UNIPISPI: val_upper: 0x%x, val_lower: 0x%x", inp_buf[10], inp_buf[11]);
-#endif
-               neuronspi_spi_send_message(spi, inp_buf, outp_buf, write_length, n_spi->ideal_frequency, 25, 1, 0);
-               kfree(inp_buf);
-               kfree(outp_buf);
+        value = (ioctl_arg * 10);
+        if (value > 0xffff) value = 0xffff;
+               unipi_uart_trace(KERN_INFO "UNIPISPI: IOCTL 0x5480 timeout=%d\n", value);
+        unipispi_modbus_write_register(spi, NEURONSPI_UART_TIMEOUT_REGISTER, value);
                return 0;
        }
        default: {
@@ -152,37 +158,33 @@ int       neuronspi_uart_ioctl (struct uart_port *port, unsigned int ioctl_code, unsig
 }
 
 
-
 void neuronspi_uart_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old)
 {
        struct neuronspi_port *n_port;
        n_port = to_neuronspi_port(port, port);
 
-#if NEURONSPI_DETAILED_DEBUG > 0
-       if (old && old->c_iflag && old->c_iflag != termios->c_iflag) {
-               printk(KERN_INFO "UNIPI_UART: c_iflag termios:%d\n", termios->c_iflag);
-       }
-       printk(KERN_INFO "UNIPI_UART: Termios port:%d new:0x%x %x %x %x", port->line,\
-         termios->c_lflag, termios->c_iflag, \
-         termios->c_oflag,  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 (old) {
+        unipi_uart_trace(KERN_INFO "UNIPI_UART: Termios port:%d old:0x%04x %04x %04x %04x ldisc:%d", port->line,\
+         old->c_cflag, old->c_iflag, \
+         old->c_oflag, old->c_lflag, old->c_line);
+    }
+    if (termios) {
+        unipi_uart_trace(KERN_INFO "UNIPI_UART: Termios port:%d new:0x%04x %04x %04x %04x ldisc:%d", port->line,\
+         termios->c_cflag, termios->c_iflag, \
+         termios->c_oflag, termios->c_lflag, termios->c_line);
+    }
+
+       neuronspi_uart_set_cflag(neuronspi_s_dev[n_port->dev_index], n_port->dev_port, termios->c_cflag);
+       if (termios && (!old || ((old->c_iflag & PARMRK) != (termios->c_iflag & PARMRK)))) {
                neuronspi_uart_set_iflags(port, termios->c_iflag);
-#if 0
-               /* No more required to disable PARMRK */
-               if (termios->c_iflag & PARMRK) {
-                       termios->c_iflag &= ~PARMRK;
-               }
-#endif
        }
-       if (termios) { 
-               if (!old || old->c_line != termios->c_line) {
-                       neuronspi_uart_set_ldisc(port, termios);
-               }
+       if (termios && !old) {
+        // set line discipline only in case of new setting - Mervis behavior
+        neuronspi_uart_set_ldisc(port, termios);
        }
        n_port->baud = uart_get_baud_rate(port, termios, old, 134, 115200);
        uart_update_timeout(port, termios->c_cflag, n_port->baud);
+    neuronspi_uart_update_timeout(n_port, termios->c_cflag, n_port->baud);
 }
 
 s32 neuronspi_uart_config_rs485(struct uart_port *port, struct serial_rs485 *rs485)
@@ -191,6 +193,37 @@ s32 neuronspi_uart_config_rs485(struct uart_port *port, struct serial_rs485 *rs4
        return 0;
 }
 
+
+void neuronspi_uart_update_timeout(struct neuronspi_port *n_port, unsigned int cflag, unsigned int baud)
+{
+       unsigned int bits;
+
+       /* byte size and parity */
+       switch (cflag & CSIZE) {
+       case CS5:
+               bits = 7;
+               break;
+       case CS6:
+               bits = 8;
+               break;
+       case CS7:
+               bits = 9;
+               break;
+       default:
+               bits = 10;
+               break; /* CS8 */
+       }
+
+       if (cflag & CSTOPB)
+               bits++;
+       if (cflag & PARENB)
+               bits++;
+       /*
+        * time in microseconds for sending one character
+        */
+       n_port->one_char_usec = (1000000 * bits) / baud;
+}
+
 const char* neuronspi_uart_type(struct uart_port *port)
 {
        return port->type == PORT_NEURONSPI ? "UNIPISPI_NAME" : NULL;
@@ -198,9 +231,7 @@ const char* neuronspi_uart_type(struct uart_port *port)
 
 s32 neuronspi_uart_request_port(struct uart_port *port)
 {
-#if NEURONSPI_DETAILED_DEBUG > 0
-       printk(KERN_DEBUG "UNIPISPI: UART requested port %d\n", port->line);
-#endif
+       unipi_uart_trace(KERN_DEBUG "UNIPISPI: UART requested port %d\n", port->line);
        return 0;
 }
 
@@ -209,50 +240,47 @@ void neuronspi_uart_fifo_read(struct uart_port *port, u32 rxlen)
        s32 i;
        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 > 2
-       printk(KERN_INFO "UNIPISPI: FIFO Read len:%d\n", rxlen);
-#endif
+       unipi_uart_trace_1(KERN_INFO "UNIPISPI: FIFO Read len:%d\n", rxlen);
+
     memcpy(s->buf, d_data->uart_buf, rxlen);
        for (i = 0; i < rxlen; i++) {
-#if NEURONSPI_DETAILED_DEBUG > 2
-               printk(KERN_INFO "UNIPISPI: UART Char Read: %x\n", d_data->uart_buf[i]);
-#endif
+               unipi_uart_trace_2(KERN_INFO "UNIPISPI: UART Char Read: %x\n", d_data->uart_buf[i]);
        }
 }
 
-int static neuronspi_uart_get_charcount(struct neuronspi_port *port) {
-       u8 *inp_buf, *outp_buf;
-       int read_length;
+int static neuronspi_uart_get_charcount(struct neuronspi_port *port) 
+{
+    u16 read_length16;
        struct spi_device *spi;
        struct neuronspi_driver_data *n_spi;
        int ret = 0;
+    
        spi = neuronspi_s_dev[port->dev_index];
        n_spi = spi_get_drvdata(spi);
        if (n_spi && n_spi->combination_id != 0xFF && n_spi->reg_map && n_spi->regstart_table->uart_queue_reg) {
-               read_length = neuronspi_spi_compose_single_register_read(n_spi->regstart_table->uart_queue_reg, &inp_buf, &outp_buf);
-               neuronspi_spi_send_message(spi, inp_buf, outp_buf, read_length, n_spi->ideal_frequency, 35, 1, 0);
-               ret = outp_buf[MODBUS_FIRST_DATA_BYTE + 1];
-               kfree(inp_buf);
-               kfree(outp_buf);
+        if (unipispi_modbus_read_register(spi, n_spi->regstart_table->uart_queue_reg, &read_length16) == 0) {
+            ret = read_length16;
+        }
        }
+       unipi_uart_trace(KERN_INFO "UNIPI_UART: GET Char count:%d\n", ret);
        return ret;
 }
 
-void neuronspi_uart_fifo_write(struct neuronspi_port *port, u8 to_send)
+void neuronspi_uart_fifo_write(struct neuronspi_port *n_port, u8 to_send)
 {
-       s32 i;
-#if NEURONSPI_DETAILED_DEBUG > 2
-       printk(KERN_INFO "UNIPISPI: FIFO Write to_send:%d\n", to_send);
-#endif
+       int i, in_queue, need;
+
+       unipi_uart_trace_2(KERN_INFO "UNIPISPI: FIFO Write to_send:%d\n", to_send);
        for (i = 0; i < to_send; i++) {
-#if NEURONSPI_DETAILED_DEBUG > 2
-               printk(KERN_INFO "UNIPISPI: UART Char Send: %x\n", port->buf[i]);
-#endif
+               unipi_uart_trace_2(KERN_INFO "UNIPISPI: UART Char Send: %x\n", n_port->buf[i]);
        }
-       while(neuronspi_uart_get_charcount(port) > 50) {
-               msleep(1);
-       }
-    neuronspi_spi_uart_write(neuronspi_s_dev[port->dev_index], port->buf, to_send, port->dev_port);
+    do {
+        in_queue = neuronspi_uart_get_charcount(n_port);
+        need = (int)to_send - (NEURONSPI_FIFO_SIZE - in_queue);
+        if (need <= 0)  break;
+        usleep_range(need * n_port->one_char_usec, (need + NEURONSPI_FIFO_SIZE/4) * n_port->one_char_usec);
+    } while(1);
+    neuronspi_spi_uart_write(neuronspi_s_dev[n_port->dev_index], n_port->buf, to_send, n_port->dev_port);
 }
 
 s32 neuronspi_uart_alloc_line(void)
@@ -278,9 +306,8 @@ void neuronspi_uart_handle_rx(struct neuronspi_port *port, u32 rxlen, u32 iir)
                port->port.icount.rx++;
                flag = TTY_NORMAL;
                for (i = 0; i < bytes_read; ++i) {
-#if NEURONSPI_DETAILED_DEBUG > 0
-                       printk(KERN_INFO "UNIPISPI: UART Insert Char:%x\n", port->buf[i]);
-#endif
+                       unipi_uart_trace(KERN_INFO "UNIPISPI: UART Insert Char:%x\n", port->buf[i]);
+
                        ch = port->buf[i];
                        if (uart_handle_sysrq_char(port, ch))
                                continue;
@@ -295,17 +322,15 @@ void neuronspi_uart_handle_rx(struct neuronspi_port *port, u32 rxlen, u32 iir)
 
 void neuronspi_uart_handle_tx(struct neuronspi_port *port)
 {
-       s32 max_txlen, to_send, to_send_packet, i;
+       s32 max_txlen, to_send, to_send_packet;//, i;
        unsigned long flags;
        struct spi_device *spi;
        struct neuronspi_driver_data *d_data;
        struct circ_buf *xmit;
+       int new_tail;
 
        spi = neuronspi_s_dev[port->dev_index];
        d_data = spi_get_drvdata(spi);
-       spin_lock_irqsave(&port->port.lock, flags);
-       xmit = &port->port.state->xmit;
-       spin_unlock_irqrestore(&port->port.lock, flags);
 
        if (unlikely(port->port.x_char)) {
                neuronspi_spi_uart_write(spi, &port->port.x_char, 1, port->dev_port);
@@ -316,6 +341,9 @@ void neuronspi_uart_handle_tx(struct neuronspi_port *port)
                return;
        }
 
+       //spin_lock_irqsave(&port->port.lock, flags);
+       xmit = &port->port.state->xmit;
+       //spin_unlock_irqrestore(&port->port.lock, flags);
        spin_lock_irqsave(&port->port.lock, flags);
        if (uart_circ_empty(xmit) || uart_tx_stopped(&port->port)) {
                spin_unlock_irqrestore(&port->port.lock, flags);
@@ -324,69 +352,57 @@ void neuronspi_uart_handle_tx(struct neuronspi_port *port)
        spin_unlock_irqrestore(&port->port.lock, flags);
 
        /* Get length of data pending in circular buffer */
-       spin_lock_irqsave(&port->port.lock, flags);
        to_send = uart_circ_chars_pending(xmit);
-       spin_unlock_irqrestore(&port->port.lock, flags);
-#if NEURONSPI_DETAILED_DEBUG > 0
-       printk(KERN_INFO "UNIPISPI: UART_HANDLE_TX A, to_send:%d", to_send);
-#endif
+       unipi_uart_trace(KERN_INFO "UNIPISPI: UART_HANDLE_TX A, to_send:%d", to_send);
+
        if (likely(to_send)) {
                /* Limit to size of (TX FIFO / 2) */
-               max_txlen = NEURONSPI_FIFO_SIZE >> 2;
-               while (to_send > max_txlen) {
+               max_txlen = NEURONSPI_FIFO_SIZE >> 1;
+               while (to_send > 0) {
                        to_send_packet = (to_send > max_txlen) ? max_txlen : to_send;
 
                        /* Add data to send */
-                       spin_lock_irqsave(&port->port.lock, flags);
                        port->port.icount.tx += to_send_packet;
-                       /* Convert to linear buffer */
-                       for (i = 0; i < to_send_packet; ++i) {
-                               port->buf[i] = xmit->buf[xmit->tail];
-                               xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+                       new_tail = (xmit->tail + to_send_packet) & (UART_XMIT_SIZE - 1);
+                       if (new_tail <= xmit->tail) {
+                               memcpy(port->buf, xmit->buf+xmit->tail, UART_XMIT_SIZE - xmit->tail);
+                               memcpy(port->buf+UART_XMIT_SIZE - xmit->tail, xmit->buf, new_tail);
+                       } else {
+                               memcpy(port->buf, xmit->buf+xmit->tail, to_send_packet);
                        }
-                       spin_unlock_irqrestore(&port->port.lock, flags);
-#if NEURONSPI_DETAILED_DEBUG > 0
-                       printk(KERN_INFO "UNIPISPI: UART_HANDLE_TX B, to_send:%d", to_send_packet);
-#endif
+                       xmit->tail = new_tail;
+
+                       /* Convert to linear buffer */
+                       //for (i = 0; i < to_send_packet; ++i) {
+                       //      port->buf[i] = xmit->buf[xmit->tail];
+                       //      xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+                       //}
+                       unipi_uart_trace(KERN_INFO "UNIPISPI: UART_HANDLE_TX B, to_send:%d", to_send_packet);
                        neuronspi_uart_fifo_write(port, to_send_packet);
+
                        spin_lock_irqsave(&port->port.lock, flags);
                        to_send = uart_circ_chars_pending(xmit);
+                       if (to_send < WAKEUP_CHARS) {
+                               uart_write_wakeup(&port->port);
+                       }
                        spin_unlock_irqrestore(&port->port.lock, flags);
                }
-               spin_lock_irqsave(&port->port.lock, flags);
-               to_send = uart_circ_chars_pending(xmit);
-               to_send_packet = (to_send > max_txlen) ? max_txlen : to_send;
-               /* Add data to send */
-               port->port.icount.tx += to_send_packet;
-               /* Convert to linear buffer */
-               for (i = 0; i < to_send_packet; ++i) {
-                       port->buf[i] = xmit->buf[xmit->tail];
-                       xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
-               }
-               spin_unlock_irqrestore(&port->port.lock, flags);
-#if NEURONSPI_DETAILED_DEBUG > 0
-               printk(KERN_INFO "UNIPISPI: UART_HANDLE_TX C, to_send:%d", to_send_packet);
-#endif
-               neuronspi_uart_fifo_write(port, to_send_packet);
        }
-
+/*
        spin_lock_irqsave(&port->port.lock, flags);
        if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) {
                uart_write_wakeup(&port->port);
        }
        spin_unlock_irqrestore(&port->port.lock, flags);
+*/
 }
 
 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_ATOMIC);
-       u8 *recv_buf = kzalloc(NEURONSPI_UART_PROBE_MESSAGE_LEN, GFP_ATOMIC);
-       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, 0);
-       kfree(send_buf);
-       kfree(recv_buf);
+    struct neuronspi_op_buffer recv_buf;
+       neuronspi_spi_send_const_op(spi, &UNIPISPI_IDLE_MESSAGE, &recv_buf, 0, NEURONSPI_DEFAULT_FREQ, 25);
 }
 
 void neuronspi_uart_ist(struct kthread_work *ws)
@@ -430,9 +446,7 @@ s32 neuronspi_uart_probe(struct spi_device* dev, u8 device_index)
                for (i = 0; i < NEURONSPI_MAX_UART; i++) {
                        uart_data->p[i].parent = uart_data;
                }
-#if NEURONSPI_DETAILED_DEBUG > 0
-               printk(KERN_DEBUG "UNIPISPI: Allocated port structure for %d potential UART devices", NEURONSPI_MAX_UART);
-#endif
+               unipi_uart_trace(KERN_DEBUG "UNIPISPI: Allocated port structure for %d potential UART devices", NEURONSPI_MAX_UART);
        }
 
        new_uart_count = driver_data->uart_count + uart_data->p_count;
@@ -445,7 +459,7 @@ s32 neuronspi_uart_probe(struct spi_device* dev, u8 device_index)
                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.fifosize   = NEURONSPI_FIFO_SIZE*8;
                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;
@@ -460,9 +474,7 @@ s32 neuronspi_uart_probe(struct spi_device* dev, u8 device_index)
                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);
-#if NEURONSPI_DETAILED_DEBUG > 0
-               printk(KERN_INFO "UNIPISPI: Added UART port %d\n", i);
-#endif
+               unipi_uart_trace(KERN_INFO "UNIPISPI: Added UART port %d\n", i);
        }
 
        // For ports on multiple SPI devices renumber the ports to correspond to SPI chip-select numbering
@@ -477,9 +489,7 @@ s32 neuronspi_uart_probe(struct spi_device* dev, u8 device_index)
                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 "UNIPISPI: Renumber not NULL %d UC:%d\n", i, driver_data->uart_count);
-#endif
+                               unipi_uart_trace(KERN_DEBUG "UNIPISPI: Renumber not NULL %d UC:%d\n", i, driver_data->uart_count);
                                if (driver_data->uart_count) {
                                        for (j = 0; j < new_uart_count; j++) {
                                                if (uart_data->p[j].dev_index == i) {
@@ -494,9 +504,7 @@ s32 neuronspi_uart_probe(struct spi_device* dev, u8 device_index)
                                                        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 "UNIPISPI: Added UART port %d\n", j);
-#endif
+                                                       unipi_uart_trace(KERN_DEBUG "UNIPISPI: Added UART port %d\n", j);
                                                }
                                        }
                                }
@@ -506,9 +514,7 @@ s32 neuronspi_uart_probe(struct spi_device* dev, u8 device_index)
 
        uart_data->p_count = new_uart_count;
        if (uart_data->kworker_task == NULL) {
-#if NEURONSPI_DETAILED_DEBUG > 0
-               printk(KERN_DEBUG "UNIPISPI: KWorker Task is NULL\n");
-#endif
+               unipi_uart_trace(KERN_DEBUG "UNIPISPI: KWorker Task is NULL\n");
 
                kthread_init_worker(&uart_data->kworker);
 
@@ -519,6 +525,8 @@ s32 neuronspi_uart_probe(struct spi_device* dev, u8 device_index)
                }
                sched_setscheduler(uart_data->kworker_task, SCHED_FIFO, &neuronspi_sched_param);
        }
+    
+    unipi_uart_trace(KERN_DEBUG "UNIPISPI: UART PROBE MCTRL:%d\n", neuronspi_spi_uart_get_cflag(dev, 0));
        return ret;
 }
 
@@ -555,7 +563,7 @@ void neuronspi_uart_rx_proc(struct kthread_work *ws)
        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_ATOMIC);
+       //u8 *send_buf = kzalloc(NEURONSPI_BUFFER_MAX, GFP_ATOMIC);
        u8 *recv_buf = kzalloc(NEURONSPI_BUFFER_MAX, GFP_ATOMIC);
 
        mutex_lock(&neuronspi_master_mutex);
@@ -564,37 +572,42 @@ void neuronspi_uart_rx_proc(struct kthread_work *ws)
 
        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]);
-                       mutex_unlock(&neuronspi_master_mutex);
-                       neuronspi_uart_handle_rx(n_port, recv_buf[7], 1);
-                       mutex_lock(&neuronspi_master_mutex);
-                       read_count = recv_buf[9];
-                       mutex_unlock(&neuronspi_master_mutex);
-               } else if (recv_buf[0] != 0x41) {
+               //neuronspi_spi_uart_read(spi, send_buf, recv_buf, read_count, n_port->dev_port);
+               neuronspi_spi_uart_read(spi, recv_buf, read_count, n_port->dev_port);
+               if (((recv_buf[0] == 0x65) || (recv_buf[0] == 0x68))) {
+                       if (recv_buf[1] > 0) {
+                               mutex_lock(&neuronspi_master_mutex);
+                               memcpy(&d_data->uart_buf[0], &recv_buf[4], recv_buf[1]);
+                               mutex_unlock(&neuronspi_master_mutex);
+                               neuronspi_uart_handle_rx(n_port, recv_buf[1], 1);
+                       }
+                       //mutex_lock(&neuronspi_master_mutex);
+                       if ((read_count == 0) && ( recv_buf[3] == 0)) {
+                               mutex_lock(&neuronspi_master_mutex);
+                               d_data->uart_read = 0;
+                               end_flag = 1;
+                               mutex_unlock(&neuronspi_master_mutex);
+                       } else {
+                               read_count = recv_buf[3];
+                       }
+                       //mutex_unlock(&neuronspi_master_mutex);
+               } else { //if ((recv_buf[0]&0xfd) != 0x41) {
                        mutex_lock(&neuronspi_master_mutex);
                        d_data->uart_read = 0;
                        end_flag = 1;
                        mutex_unlock(&neuronspi_master_mutex);
                }
-               mutex_unlock(&neuronspi_uart_mutex);
        }
        kfree(recv_buf);
-       kfree(send_buf);
+       //kfree(send_buf);
 }
 
 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 "UNIPISPI: Start TX\n");
-#endif
+       unipi_uart_trace(KERN_INFO "UNIPISPI: Start TX\n");
        if (!kthread_queue_work(&n_port->parent->kworker, &n_port->tx_work)) {
-#if NEURONSPI_DETAILED_DEBUG > 0
-               printk(KERN_INFO "UNIPISPI: TX WORK OVERFLOW\n");
-#endif
+               unipi_uart_trace(KERN_INFO "UNIPISPI: TX WORK OVERFLOW\n");
        }
 }
 
@@ -632,9 +645,7 @@ s32 neuronspi_uart_startup(struct uart_port *port)
        }
        neuronspi_uart_power(port, 1);
        // TODO: /* Reset FIFOs*/
-#if NEURONSPI_DETAILED_DEBUG > 0
-       printk(KERN_DEBUG "UNIPISPI: UART Startup\n");
-#endif
+       unipi_uart_trace(KERN_DEBUG "UNIPISPI: UART Startup\n");
        return 0;
 }