From 75f3439bac06ca3c30f6545930c8a02f51e0dcda Mon Sep 17 00:00:00 2001 From: Miroslav Ondra Date: Tue, 28 Aug 2018 12:18:08 +0200 Subject: [PATCH] changed neuronspi_spi_send_message to neuronspi_spi_send_op using structured buffers 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 | 15 + modules/unipi/src/unipi_common.h | 36 +- modules/unipi/src/unipi_gpio.c | 46 + modules/unipi/src/unipi_iio.c | 211 +++++ modules/unipi/src/unipi_misc.c | 17 + modules/unipi/src/unipi_platform.c | 82 +- modules/unipi/src/unipi_spi.c | 1311 +++++++++++++--------------- modules/unipi/src/unipi_spi.h | 62 +- modules/unipi/src/unipi_sysfs.c | 89 +- modules/unipi/src/unipi_tty.c | 2 +- modules/unipi/src/unipi_uart.c | 379 ++++---- 11 files changed, 1319 insertions(+), 931 deletions(-) create mode 100755 modules/unipi/current diff --git a/modules/unipi/current b/modules/unipi/current new file mode 100755 index 0000000..2a3d334 --- /dev/null +++ b/modules/unipi/current @@ -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} diff --git a/modules/unipi/src/unipi_common.h b/modules/unipi/src/unipi_common.h index bcfe71a..8c76cf2 100644 --- a/modules/unipi/src/unipi_common.h +++ b/modules/unipi/src/unipi_common.h @@ -58,16 +58,18 @@ #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_ */ diff --git a/modules/unipi/src/unipi_gpio.c b/modules/unipi/src/unipi_gpio.c index e53ed70..3cfab5b 100644 --- a/modules/unipi/src/unipi_gpio.c +++ b/modules/unipi/src/unipi_gpio.c @@ -23,6 +23,52 @@ * 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, ¤t_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, ¤t_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; } diff --git a/modules/unipi/src/unipi_iio.c b/modules/unipi/src/unipi_iio.c index fc4d39b..a22cee3 100644 --- a/modules/unipi/src/unipi_iio.c +++ b/modules/unipi/src/unipi_iio.c @@ -22,6 +22,217 @@ /************************ * 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); diff --git a/modules/unipi/src/unipi_misc.c b/modules/unipi/src/unipi_misc.c index 3b6ac08..0168712 100644 --- a/modules/unipi/src/unipi_misc.c +++ b/modules/unipi/src/unipi_misc.c @@ -23,6 +23,23 @@ * 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); diff --git a/modules/unipi/src/unipi_platform.c b/modules/unipi/src/unipi_platform.c index 0486ffe..ce1fc0d 100644 --- a/modules/unipi/src/unipi_platform.c +++ b/modules/unipi/src/unipi_platform.c @@ -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) diff --git a/modules/unipi/src/unipi_spi.c b/modules/unipi/src/unipi_spi.c index 592bfbd..04f893c 100644 --- a/modules/unipi/src/unipi_spi.c +++ b/modules/unipi/src/unipi_spi.c @@ -28,6 +28,21 @@ #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, ¤t_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, ¤t_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); diff --git a/modules/unipi/src/unipi_spi.h b/modules/unipi/src/unipi_spi.h index ea8fab9..2a881de 100644 --- a/modules/unipi/src/unipi_spi.h +++ b/modules/unipi/src/unipi_spi.h @@ -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_ */ diff --git a/modules/unipi/src/unipi_sysfs.c b/modules/unipi/src/unipi_sysfs.c index 10c1261..67b5fa2 100644 --- a/modules/unipi/src/unipi_sysfs.c +++ b/modules/unipi/src/unipi_sysfs.c @@ -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 * diff --git a/modules/unipi/src/unipi_tty.c b/modules/unipi/src/unipi_tty.c index a6aa074..1e21a11 100644 --- a/modules/unipi/src/unipi_tty.c +++ b/modules/unipi/src/unipi_tty.c @@ -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...) diff --git a/modules/unipi/src/unipi_uart.c b/modules/unipi/src/unipi_uart.c index 56e7b9c..96d50fe 100644 --- a/modules/unipi/src/unipi_uart.c +++ b/modules/unipi/src/unipi_uart.c @@ -19,6 +19,24 @@ #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; } -- 2.34.1