From: Tom Knot Date: Fri, 2 Mar 2018 12:16:28 +0000 (+0100) Subject: Fixed directory structure to correspond to the new module name X-Git-Url: http://git.graph-it.com/?a=commitdiff_plain;h=f2b06899467e2b91e9f996ceeef9915227e05502;p=graphit%2Funipi-kernel.git Fixed directory structure to correspond to the new module name --- diff --git a/modules/neuron_spi/Makefile b/modules/neuron_spi/Makefile deleted file mode 100644 index 321946c..0000000 --- a/modules/neuron_spi/Makefile +++ /dev/null @@ -1,69 +0,0 @@ -# Note: Compiling kernel modules requires creating symlinks, which is not possible on certain -# filesystems (notably VirtualBox vmfs); therefore we allow using /run/ through the 'symlink' target, -# if necessary. - -SYMLINK_DIR_PATH = /run/kernel/neuron_spi -LINUX_DIR_PATH = /root/bokula/linux -SRC_DIR_PATH = $(PWD)/src -BIN_DIR_PATH = $(PWD)/bin - -MODULE_MAKE_FILE = Makefile - -C_SRC_FILES = unipi_spi.c -C_SRC_FILES += unipi_iio.c -C_SRC_FILES += unipi_gpio.c -C_SRC_FILES += unipi_uart.c -C_SRC_FILES += unipi_sysfs.c -C_SRC_FILES += unipi_misc.c -C_SRC_FILES += unipi_platform.c - -H_SRC_FILES = unipi_spi.h -H_SRC_FILES += unipi_iio.h -H_SRC_FILES += unipi_gpio.h -H_SRC_FILES += unipi_uart.h -H_SRC_FILES += unipi_sysfs.h -H_SRC_FILES += unipi_misc.h -H_SRC_FILES += unipi_platform.h -H_SRC_FILES += unipi_common.h - -OBJ_FILES = src/unipi_spi.o -OBJ_FILES += src/unipi_iio.o -OBJ_FILES += src/unipi_gpio.o -OBJ_FILES += src/unipi_uart.o -OBJ_FILES += src/unipi_sysfs.o -OBJ_FILES += src/unipi_misc.o -OBJ_FILES += src/unipi_platform.o - -KERNEL_MODULE_NAME = unipi -obj-m += ${KERNEL_MODULE_NAME}.o -unipi-objs := ${OBJ_FILES} - -TARGET_PLC_PATH = tomunipi:/root/ - -.PHONY: default -default: symlink ; - -all: - make ARCH=arm CROSS_COMPILE=${CCPREFIX} -C ${LINUX_DIR_PATH} M=${PWD} modules - -clean: - make -C ${LINUX_DIR_PATH} M=$(PWD) clean - rm -f ${BIN_DIR_PATH}/${KERNEL_MODULE_NAME}.ko - -transfer: clean symlink - scp ${BIN_DIR_PATH}/${KERNEL_MODULE_NAME}.ko ${TARGET_PLC_PATH} - -symlink: clean - rm -r -f ${SYMLINK_DIR_PATH} - mkdir -p ${SYMLINK_DIR_PATH}/src - mkdir -p ${SYMLINK_DIR_PATH}/bin - cp ${PWD}/${MODULE_MAKE_FILE} ${SYMLINK_DIR_PATH} - for f in ${C_SRC_FILES}; do\ - ln -s ${SRC_DIR_PATH}/$$f ${SYMLINK_DIR_PATH}/src ;\ - done - for f in ${H_SRC_FILES}; do\ - ln -s ${SRC_DIR_PATH}/$$f ${SYMLINK_DIR_PATH}/src ;\ - done - cd ${SYMLINK_DIR_PATH}; make all - mv ${SYMLINK_DIR_PATH}/${KERNEL_MODULE_NAME}.ko ${BIN_DIR_PATH} - rm -r -f ${SYMLINK_DIR_PATH} diff --git a/modules/neuron_spi/src/unipi_common.h b/modules/neuron_spi/src/unipi_common.h deleted file mode 100644 index f7646a3..0000000 --- a/modules/neuron_spi/src/unipi_common.h +++ /dev/null @@ -1,300 +0,0 @@ -/* - * UniPi Neuron tty serial driver - Copyright (C) 2018 UniPi Technologies - * Author: Tomas Knot - * - * Based on the SC16IS7xx driver by Jon Ringle , - * which was in turn based on max310x.c, by Alexander Shiyan - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - */ - -#ifndef MODULES_NEURON_SPI_SRC_UNIPI_COMMON_H_ -#define MODULES_NEURON_SPI_SRC_UNIPI_COMMON_H_ - -/************ - * Includes * - ************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/*************** - * Definitions * - ***************/ - -#define NEURONSPI_SCHED_REQUIRED 0 // Older kernels do not require sched/types to be specifically imported -#define NEURONSPI_MAJOR_VERSIONSTRING "Development Beta Version 0.02:12:02:2018" - -#define NEURONSPI_MAX_DEVS 3 -#define NEURONSPI_MAX_UART 128 -#define NEURONSPI_BUFFER_MAX 1152 -#define NEURONSPI_HEADER_LENGTH 10 -#define NEURONSPI_FIRST_MESSAGE_LENGTH 6 -#define NEURONSPI_EDGE_DELAY 10 -#define NEURONSPI_B_PER_WORD 8 -#define NEURONSPI_DEFAULT_FREQ 600000 -#define NEURONSPI_COMMON_FREQ 12000000 -#define NEURONSPI_SLOWER_FREQ 8000000 -#define NEURONSPI_MAX_TX 62 -#define NEURONSPI_MAX_BAUD 115200 -#define NEURONSPI_FIFO_SIZE 256 -#define NEURONSPI_DETAILED_DEBUG 0 -#define NEURONSPI_LAST_TRANSFER_DELAY 40 - -#define NEURON_DEVICE_NAME "neuronspi" -#define NEURON_DEVICE_CLASS "modbus_spi" -#define NEURON_DRIVER_NAME "NEURONSPI" -#define PORT_NEURONSPI 184 - -#define STRICT_RESERVING -#define NEURONSPI_ALWAYS_EXPORT - -#define NEURONSPI_GET_COIL_READ_PHASE2_BYTE_LENGTH(X) ((((X) + 15) >> 4) << 1) - -/******************** - * Module Constants * - ********************/ - -#define NEURONSPI_NO_INTERRUPT_MODELS_LEN 3 -static const u16 NEURONSPI_NO_INTERRUPT_MODELS[NEURONSPI_NO_INTERRUPT_MODELS_LEN] = { - 0xb10, 0xc10, 0xf10 -}; - -/******************* - * Data Structures * - *******************/ - -enum neuron_str_attribute_type { - NEURON_SATTR_MODEL, - NEURON_SATTR_EEPROM, - NEURON_SATTR_BOARD_NAME, - NEURON_SATTR_GPIO_GROUP_NAME -}; - -enum neuron_num_attribute_type { - NEURON_NATTR_BOARDCOUNT, - NEURON_NATTR_MODE, - NEURON_NATTR_CURRENT_VALUE -}; - -struct neuronspi_devtype -{ - u8 name[10]; - s32 nr_gpio; - s32 nr_uart; -}; - -struct neuronspi_port -{ - struct uart_port port; - u8 line; - struct kthread_work tx_work; - struct kthread_work rx_work; - struct kthread_work irq_work; - u32 flags; - u8 ier_clear; - u8 buf[NEURONSPI_FIFO_SIZE]; - struct neuronspi_uart_data *parent; - u8 dev_index; - u8 dev_port; - u8 parmrk_enabled; - u64 parmrk_frame_delay; - s32 baud; -}; - -struct neuronspi_uart_data -{ - const struct neuronspi_devtype *devtype; - struct kthread_worker kworker; - struct task_struct *kworker_task; - struct neuronspi_port *p; - u8 p_count; -}; - -// Instantiated once -struct neuronspi_char_driver -{ - s32 major_number; - u8 *message; - u16 message_size; - u32 open_counter; - struct class* driver_class; - struct device* dev; -}; - -// Instantiated once per SPI device -struct neuronspi_driver_data -{ - struct spi_driver *spi_driver; - struct neuronspi_char_driver *char_driver; - struct uart_driver *serial_driver; - struct neuronspi_uart_data *uart_data; - struct neuronspi_led_driver *led_driver; - struct neuronspi_di_driver **di_driver; - struct neuronspi_do_driver **do_driver; - struct neuronspi_ro_driver **ro_driver; - struct platform_device *board_device; - struct iio_dev *stm_ai_driver; - struct iio_dev *stm_ao_driver; - struct iio_dev **sec_ai_driver; - struct iio_dev **sec_ao_driver; - struct kthread_worker primary_worker; - struct task_struct *primary_worker_task; - struct regmap *reg_map; - struct task_struct *poll_thread; - struct mutex device_lock; - struct neuronspi_board_features *features; - struct neuronspi_board_regstart_table *regstart_table; - struct spinlock sysfs_regmap_lock; - char platform_name[sizeof("io_group0")]; - u8 *send_buf; - u8 *recv_buf; - u8 *first_probe_reply; - u8 *second_probe_reply; - u8 reserved_device; - u8 uart_count; - u8 uart_read; - u8 *uart_buf; - u8 slower_model; - u8 no_irq; - u8 lower_board_id; - u8 upper_board_id; - u8 combination_id; - s32 neuron_index; - u16 sysfs_regmap_target; - u16 sysfs_counter_target; - u32 ideal_frequency; -}; - -struct neuronspi_di_driver { - struct spi_device* spi; - struct gpio_chip gpio_c; - struct platform_device *plat_dev; - u8 di_index; - char name[sizeof("di_0_00")]; -}; - -struct neuronspi_do_driver -{ - struct spi_device* spi; - struct gpio_chip gpio_c; - struct platform_device *plat_dev; - u8 do_index; - char name[sizeof("do_0_00")]; -}; - -struct neuronspi_ro_driver -{ - struct spi_device* spi; - struct gpio_chip gpio_c; - struct platform_device *plat_dev; - u8 ro_index; - char name[sizeof("ro_0_00")]; -}; - -struct neuronspi_sec_ai_driver -{ - struct iio *devices; - u16 dev_count; -}; - -struct neuronspi_sec_ao_driver -{ - struct iio *devices; - u16 dev_count; -}; - -struct neuronspi_stm_ai_data -{ - u32 mode; - struct spi_device *parent; -}; - -struct neuronspi_stm_ao_data -{ - u32 mode; - struct spi_device *parent; -}; - -struct neuronspi_sec_ai_data -{ - u32 index; - u32 mode; - struct spi_device *parent; -}; - -struct neuronspi_sec_ao_data -{ - u32 index; - u32 mode; - struct spi_device *parent; -}; - -// Instantiated once per LED -struct neuronspi_led_driver -{ - struct led_classdev ldev; - struct spi_device *spi; - struct kthread_work led_work; - int id; - int brightness; - char name[sizeof("neuron:green:uled-x1")]; - spinlock_t lock; -}; - -struct neuronspi_file_data -{ - struct spi_device** spi_device; - struct mutex lock; - u8 *send_buf; - u8 *recv_buf; - u32 message_len; -}; - -struct neuronspi_direct_acc -{ - void __iomem *vaddr; - u32 size; -}; - -/********************* - * Data Declarations * - *********************/ - -extern struct mutex neuronspi_master_mutex; -extern struct neuronspi_char_driver neuronspi_cdrv; -extern struct spinlock* neuronspi_spi_w_spinlock; -extern struct spi_device* neuronspi_s_dev[NEURONSPI_MAX_DEVS]; -extern struct task_struct *neuronspi_invalidate_thread; - -extern u8 neuronspi_spi_w_flag; -extern u8 neuronspi_probe_count; -extern int neuronspi_model_id; -extern spinlock_t neuronspi_probe_spinlock; - -#endif /* MODULES_NEURON_SPI_SRC_UNIPI_COMMON_H_ */ diff --git a/modules/neuron_spi/src/unipi_gpio.c b/modules/neuron_spi/src/unipi_gpio.c deleted file mode 100644 index e7d9de6..0000000 --- a/modules/neuron_spi/src/unipi_gpio.c +++ /dev/null @@ -1,59 +0,0 @@ -/* - * UniPi Neuron tty serial driver - Copyright (C) 2018 UniPi Technologies - * Author: Tomas Knot - * - * Based on the SC16IS7xx driver by Jon Ringle , - * which was in turn based on max310x.c, by Alexander Shiyan - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - */ - -/************ - * Includes * - ************/ - -#include "unipi_gpio.h" -#include "unipi_spi.h" - -/************************ - * Non-static Functions * - ************************/ - -int neuronspi_gpio_di_direction_input(struct gpio_chip *chip, unsigned offset) { - return 0; -} - -int neuronspi_gpio_di_direction_output(struct gpio_chip *chip, unsigned offset, int value) { - return -EINVAL; -} - -int neuronspi_gpio_di_get(struct gpio_chip *chip, unsigned offset) { - struct neuronspi_di_driver *n_di = gpiochip_get_data(chip); - struct spi_device *spi = n_di->spi; - return neuronspi_spi_gpio_di_get(spi, n_di->di_index); -} - -int neuronspi_gpio_do_direction_output(struct gpio_chip *chip, unsigned offset, int value) { - return 0; -} - -void neuronspi_gpio_do_set(struct gpio_chip *chip, unsigned offset, int value) { - struct neuronspi_do_driver *n_do = gpiochip_get_data(chip); - struct spi_device *spi = n_do->spi; - neuronspi_spi_gpio_do_set(spi, n_do->do_index, value); -} - -int neuronspi_gpio_ro_direction_output(struct gpio_chip *chip, unsigned offset, int value) { - return 0; -} - -void neuronspi_gpio_ro_set(struct gpio_chip *chip, unsigned offset, int value) { - struct neuronspi_ro_driver *n_ro = gpiochip_get_data(chip); - struct spi_device *spi = n_ro->spi; - neuronspi_spi_gpio_ro_set(spi, n_ro->ro_index, value); -} - diff --git a/modules/neuron_spi/src/unipi_gpio.h b/modules/neuron_spi/src/unipi_gpio.h deleted file mode 100644 index 508fd78..0000000 --- a/modules/neuron_spi/src/unipi_gpio.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * UniPi Neuron tty serial driver - Copyright (C) 2018 UniPi Technologies - * Author: Tomas Knot - * - * Based on the SC16IS7xx driver by Jon Ringle , - * which was in turn based on max310x.c, by Alexander Shiyan - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - */ - -#ifndef MODULES_NEURON_SPI_SRC_UNIPI_GPIO_H_ -#define MODULES_NEURON_SPI_SRC_UNIPI_GPIO_H_ - -/************ - * Includes * - ************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "unipi_common.h" - -/************************* - * Function Declarations * - *************************/ - -int neuronspi_gpio_di_direction_input(struct gpio_chip *chip, unsigned offset); -int neuronspi_gpio_di_direction_output(struct gpio_chip *chip, unsigned offset, int value); -int neuronspi_gpio_di_get(struct gpio_chip *chip, unsigned offset); -int neuronspi_gpio_do_direction_input(struct gpio_chip *chip, unsigned offset); -int neuronspi_gpio_do_direction_output(struct gpio_chip *chip, unsigned offset, int value); -void neuronspi_gpio_do_set(struct gpio_chip *chip, unsigned offset, int value); -int neuronspi_gpio_ro_direction_input(struct gpio_chip *chip, unsigned offset); -int neuronspi_gpio_ro_direction_output(struct gpio_chip *chip, unsigned offset, int value); -void neuronspi_gpio_ro_set(struct gpio_chip *chip, unsigned offset, int value); - -#endif /* MODULES_NEURON_SPI_SRC_UNIPI_GPIO_H_ */ diff --git a/modules/neuron_spi/src/unipi_iio.c b/modules/neuron_spi/src/unipi_iio.c deleted file mode 100644 index eca3eae..0000000 --- a/modules/neuron_spi/src/unipi_iio.c +++ /dev/null @@ -1,183 +0,0 @@ -/* - * UniPi Neuron tty serial driver - Copyright (C) 2018 UniPi Technologies - * Author: Tomas Knot - * - * Based on the SC16IS7xx driver by Jon Ringle , - * which was in turn based on max310x.c, by Alexander Shiyan - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - */ - -/************ - * Includes * - ************/ - -#include "unipi_iio.h" -#include "unipi_spi.h" - -/************************ - * Non-static Functions * - ************************/ - -int neuronspi_iio_stm_ai_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *ch, int *val, int *val2, long mask) { - struct neuronspi_stm_ai_data *ai_data = iio_priv(indio_dev); - struct spi_device *spi = ai_data->parent; - struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi); - regmap_read(n_spi->reg_map, n_spi->regstart_table->stm_ai_mode_reg, &ai_data->mode); - switch(ai_data->mode) { - case 0: { - if (ch->type == IIO_VOLTAGE) { - neuronspi_spi_iio_stm_ai_read_voltage(indio_dev, ch, val, val2, mask); - return IIO_VAL_INT; - } else { - return -EINVAL; - } - break; - } - case 1: { - if (ch->type == IIO_CURRENT) { - neuronspi_spi_iio_stm_ai_read_current(indio_dev, ch, val, val2, mask); - return IIO_VAL_INT; - } else { - return -EINVAL; - } - break; - } - default: { - return -EINVAL; - break; - } - } -} - -int neuronspi_iio_stm_ao_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *ch, int *val, int *val2, long mask) -{ - struct neuronspi_stm_ao_data *ao_data = iio_priv(indio_dev); - struct spi_device *spi = ao_data->parent; - struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi); - regmap_read(n_spi->reg_map, n_spi->regstart_table->stm_ao_mode_reg, &ao_data->mode); - switch(ao_data->mode) { - case 3: { - if (ch->type == IIO_RESISTANCE) { - neuronspi_spi_iio_stm_ao_read_resistance(indio_dev, ch, val, val2, mask); - return IIO_VAL_INT; - } else { - return -EINVAL; - } - break; - } - default: { - return -EINVAL; - break; - } - } -} - -int neuronspi_iio_stm_ao_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *ch, int val, int val2, long mask) -{ - struct neuronspi_stm_ao_data *ao_data = iio_priv(indio_dev); - struct spi_device *spi = ao_data->parent; - struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi); - regmap_read(n_spi->reg_map, n_spi->regstart_table->stm_ao_mode_reg, &ao_data->mode); - switch(ao_data->mode) { - case 0: { - if (ch->type == IIO_VOLTAGE) { - neuronspi_spi_iio_stm_ao_set_voltage(indio_dev, ch, val, val2, mask); - return 0; - } else { - return -EINVAL; - } - break; - } - case 1: { - if (ch->type == IIO_CURRENT) { - neuronspi_spi_iio_stm_ao_set_current(indio_dev, ch, val, val2, mask); - return 0; - } else { - return -EINVAL; - } - break; - } - default: { - return -EINVAL; - break; - } - } -} - -int neuronspi_iio_sec_ai_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *ch, int *val, int *val2, long mask) -{ - struct neuronspi_sec_ai_data *ai_data = iio_priv(indio_dev); - struct spi_device *spi = ai_data->parent; - struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi); - regmap_read(n_spi->reg_map, n_spi->regstart_table->sec_ai_mode_reg, &ai_data->mode); - switch(ai_data->mode) { - case 0: { - return -EINVAL; - break; - } - case 1: { - if (ch->type == IIO_VOLTAGE) { - neuronspi_spi_iio_sec_ai_read_voltage(indio_dev, ch, val, val2, mask); - return IIO_VAL_FRACTIONAL; - } else { - return -EINVAL; - } - break; - } - case 2: { - if (ch->type == IIO_VOLTAGE) { - neuronspi_spi_iio_sec_ai_read_voltage(indio_dev, ch, val, val2, mask); - return IIO_VAL_FRACTIONAL; - } else { - return -EINVAL; - } - break; - } - case 3: { - if (ch->type == IIO_CURRENT) { - neuronspi_spi_iio_sec_ai_read_current(indio_dev, ch, val, val2, mask); - return IIO_VAL_FRACTIONAL; - } else { - return -EINVAL; - } - break; - } - case 4: { - if (ch->type == IIO_RESISTANCE) { - neuronspi_spi_iio_sec_ai_read_resistance(indio_dev, ch, val, val2, mask); - return IIO_VAL_FRACTIONAL; - } else { - return -EINVAL; - } - break; - } - case 5: { - if (ch->type == IIO_RESISTANCE) { - neuronspi_spi_iio_sec_ai_read_resistance(indio_dev, ch, val, val2, mask); - return IIO_VAL_FRACTIONAL; - } else { - return -EINVAL; - } - break; - } - default: { - return -EINVAL; - break; - } - } -} - -int neuronspi_iio_sec_ao_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *ch, int val, int val2, long mask) -{ - if (ch->type == IIO_VOLTAGE) { - neuronspi_spi_iio_stm_ao_set_voltage(indio_dev, ch, val, val2, mask); - return 0; - } else { - return -EINVAL; - } -} diff --git a/modules/neuron_spi/src/unipi_iio.h b/modules/neuron_spi/src/unipi_iio.h deleted file mode 100644 index c6e96c9..0000000 --- a/modules/neuron_spi/src/unipi_iio.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * UniPi Neuron tty serial driver - Copyright (C) 2018 UniPi Technologies - * Author: Tomas Knot - * - * Based on the SC16IS7xx driver by Jon Ringle , - * which was in turn based on max310x.c, by Alexander Shiyan - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - */ - -#ifndef MODULES_NEURON_SPI_SRC_UNIPI_IIO_H_ -#define MODULES_NEURON_SPI_SRC_UNIPI_IIO_H_ - -/************ - * Includes * - ************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "unipi_common.h" - -/************************* - * Function Declarations * - *************************/ - -int neuronspi_iio_stm_ai_read_raw(struct iio_dev *iio_dev, struct iio_chan_spec const *ch, int *val, int *val2, long mask); -int neuronspi_iio_stm_ao_read_raw(struct iio_dev *iio_dev, struct iio_chan_spec const *ch, int *val, int *val2, long mask); -int neuronspi_iio_stm_ao_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int val, int val2, long mask); -int neuronspi_iio_sec_ai_read_raw(struct iio_dev *iio_dev, struct iio_chan_spec const *ch, int *val, int *val2, long mask); -int neuronspi_iio_sec_ao_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int val, int val2, long mask); - -#endif /* MODULES_NEURON_SPI_SRC_UNIPI_IIO_H_ */ diff --git a/modules/neuron_spi/src/unipi_misc.c b/modules/neuron_spi/src/unipi_misc.c deleted file mode 100644 index 6efb89c..0000000 --- a/modules/neuron_spi/src/unipi_misc.c +++ /dev/null @@ -1,41 +0,0 @@ -/* - * UniPi Neuron tty serial driver - Copyright (C) 2018 UniPi Technologies - * Author: Tomas Knot - * - * Based on the SC16IS7xx driver by Jon Ringle , - * which was in turn based on max310x.c, by Alexander Shiyan - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - */ - -/************ - * Includes * - ************/ - -#include "unipi_misc.h" -#include "unipi_spi.h" - -/************************ - * Non-static Functions * - ************************/ - -void neuronspi_led_proc(struct kthread_work *ws) -{ - struct neuronspi_led_driver *led = to_led_driver(ws, led_work); - printk("NEURONSPI: BRIGHT id:%d\n", led->id); - neuronspi_spi_led_set_brightness(led->spi, led->brightness, led->id); -} - -void neuronspi_led_set_brightness(struct led_classdev *ldev, enum led_brightness brightness) -{ - struct neuronspi_led_driver *led = container_of(ldev, struct neuronspi_led_driver, ldev); - struct neuronspi_driver_data *n_spi = spi_get_drvdata(led->spi); - spin_lock(&led->lock); - led->brightness = brightness; - kthread_queue_work(&n_spi->primary_worker, &led->led_work); - spin_unlock(&led->lock); -} diff --git a/modules/neuron_spi/src/unipi_misc.h b/modules/neuron_spi/src/unipi_misc.h deleted file mode 100644 index ebeb7e2..0000000 --- a/modules/neuron_spi/src/unipi_misc.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * UniPi Neuron tty serial driver - Copyright (C) 2018 UniPi Technologies - * Author: Tomas Knot - * - * Based on the SC16IS7xx driver by Jon Ringle , - * which was in turn based on max310x.c, by Alexander Shiyan - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - */ - -#ifndef MODULES_NEURON_SPI_SRC_UNIPI_MISC_H_ -#define MODULES_NEURON_SPI_SRC_UNIPI_MISC_H_ - -/************ - * Includes * - ************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "unipi_common.h" - -/************************* - * Function Declarations * - *************************/ - -void neuronspi_led_proc(struct kthread_work *ws); -void neuronspi_led_set_brightness(struct led_classdev *ldev, enum led_brightness brightness); - -#endif /* MODULES_NEURON_SPI_SRC_UNIPI_MISC_H_ */ diff --git a/modules/neuron_spi/src/unipi_platform.c b/modules/neuron_spi/src/unipi_platform.c deleted file mode 100644 index 08a0ec8..0000000 --- a/modules/neuron_spi/src/unipi_platform.c +++ /dev/null @@ -1,1801 +0,0 @@ -/* - * UniPi Neuron tty serial driver - Copyright (C) 2018 UniPi Technologies - * Author: Tomas Knot - * - * Based on the SC16IS7xx driver by Jon Ringle , - * which was in turn based on max310x.c, by Alexander Shiyan - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - */ -/************ - * Includes * - ************/ - -#include "unipi_platform.h" -#include "unipi_spi.h" -#include "unipi_common.h" - -/*************************** - * Static Data Definitions * - ***************************/ - -// B_1000 (S103) -#define NEURONSPI_BOARD_B1000_HW_DEFINITION_BLOCK_SIZE 57 -static u32 NEURONSPI_BOARD_B1000_HW_DEFINITION_BLOCK[NEURONSPI_BOARD_B1000_HW_DEFINITION_BLOCK_SIZE] = { - 0, 21, // Register block beginning and size - NEURONSPI_REGFUN_DI_READ | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 0 - NEURONSPI_REGFUN_DO_RW | NEURONSPI_REGFLAG_ACC_10HZ, // 1 - NEURONSPI_REGFUN_AO_BRAIN | NEURONSPI_REGFLAG_ACC_AFAP, // 2 - NEURONSPI_REGFUN_AI_BRAIN | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 3 - NEURONSPI_REGFUN_AIO_BRAIN | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 4 - NEURONSPI_REGFUN_V_REF_INP | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 5 - NEURONSPI_REGFUN_MWD_STATUS | NEURONSPI_REGFLAG_ACC_6SEC | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 6 - NEURONSPI_REGFUN_TX_QUEUE_LEN | NEURONSPI_REGFLAG_ACC_10HZ, // 7 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 8 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 9 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 10 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 11 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 12 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 13 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 14 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 15 - NEURONSPI_REGFUN_PWM_DUTY | NEURONSPI_REGFLAG_ACC_6SEC, // 16 - NEURONSPI_REGFUN_PWM_DUTY | NEURONSPI_REGFLAG_ACC_6SEC, // 17 - NEURONSPI_REGFUN_PWM_DUTY | NEURONSPI_REGFLAG_ACC_6SEC, // 18 - NEURONSPI_REGFUN_PWM_DUTY | NEURONSPI_REGFLAG_ACC_6SEC, // 19 - NEURONSPI_REGFUN_LED_RW | NEURONSPI_REGFLAG_ACC_AFAP, // 20 - 1000, 32, // Register block beginning and size - NEURONSPI_REGFUN_SW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1000 - NEURONSPI_REGFUN_DIDO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1001 - NEURONSPI_REGFUN_UAIO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1002 - NEURONSPI_REGFUN_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1003 - NEURONSPI_REGFUN_FLASH_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1004 - NEURONSPI_REGFUN_SERIAL_NR_LOWER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1005 - NEURONSPI_REGFUN_SERIAL_NR_UPPER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1006 - NEURONSPI_REGFUN_INTERRUPTS | NEURONSPI_REGFLAG_ACC_AFAP, // 1007 - NEURONSPI_REGFUN_MWD_TO | NEURONSPI_REGFLAG_ACC_6SEC | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1008 - NEURONSPI_REGFUN_V_REF_INT | NEURONSPI_REGFLAG_ACC_ONCE, // 1009 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1010 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1011 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1012 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1013 - NEURONSPI_REGFUN_DS_ENABLE | NEURONSPI_REGFLAG_ACC_1HZ, // 1014 - NEURONSPI_REGFUN_DS_POLARITY | NEURONSPI_REGFLAG_ACC_1HZ, // 1015 - NEURONSPI_REGFUN_DS_TOGGLE | NEURONSPI_REGFLAG_ACC_1HZ, // 1016 - NEURONSPI_REGFUN_PWM_PRESCALE | NEURONSPI_REGFLAG_ACC_1HZ, // 1017 - NEURONSPI_REGFUN_PWM_CYCLE | NEURONSPI_REGFLAG_ACC_1HZ, // 1018 - NEURONSPI_REGFUN_AO_BRAIN_MODE | NEURONSPI_REGFLAG_ACC_1HZ, // 1019 - NEURONSPI_REGFUN_AO_BRAIN_V_ERR | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1020 - NEURONSPI_REGFUN_AO_BRAIN_V_OFF | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1021 - NEURONSPI_REGFUN_AO_BRAIN_I_ERR | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1022 - NEURONSPI_REGFUN_AO_BRAIN_I_OFF | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1023 - NEURONSPI_REGFUN_AI_BRAIN_MODE | NEURONSPI_REGFLAG_ACC_1HZ, // 1024 - NEURONSPI_REGFUN_AI_BRAIN_V_ERR | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1025 - NEURONSPI_REGFUN_AI_BRAIN_V_OFF | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1026 - NEURONSPI_REGFUN_AI_BRAIN_I_ERR | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1027 - NEURONSPI_REGFUN_AI_BRAIN_I_OFF | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1028 - NEURONSPI_REGFUN_AIO_BRAIN_OFF | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1029 - NEURONSPI_REGFUN_AIO_BRAIN_ERR | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1030 - NEURONSPI_REGFUN_RS485_CONFIG | NEURONSPI_REGFLAG_ACC_6SEC // 1031 -}; - -#define NEURONSPI_BOARD_B1000_HW_FEATURES { \ - .do_count = 4, \ - .ro_count = 0, \ - .ds_count = 4, \ - .di_count = 4, \ - .led_count = 4, \ - .stm_ai_count = 1, \ - .stm_ao_count = 1, \ - .sec_ai_count = 0, \ - .sec_ao_count = 0, \ - .uart_master_count = 1, \ - .uart_slave_count = 0, \ - .pwm_channel_count = 4, \ - .wd_count = 1, \ - .extension_sys_count = 0, \ - .light_count = 0, \ - .owire_count = 1, \ -} - -#define NEURONSPI_BOARD_B1000_HW_DEFINITION { \ - .combination_board_id = 0, \ - .lower_board_id = NEURONSPI_BOARD_LOWER_B1000_ID, \ - .upper_board_id = NEURONSPI_BOARD_UPPER_NONE_ID, \ - .block_count = NEURONSPI_BOARD_B1000_HW_DEFINITION_BLOCK_SIZE, \ - .name_length = 6, \ - .combination_name = "B_1000", \ - .features = NEURONSPI_BOARD_B1000_HW_FEATURES, \ - .blocks = NEURONSPI_BOARD_B1000_HW_DEFINITION_BLOCK \ -} -struct neuronspi_board_combination NEURONSPI_BOARD_B1000_HW_COMBINATION[] = {NEURONSPI_BOARD_B1000_HW_DEFINITION}; - -// E-8Di8Ro (M103) -#define NEURONSPI_BOARD_E8DI8RO_HW_DEFINITION_BLOCK_SIZE 44 -static u32 NEURONSPI_BOARD_E8DI8RO_HW_DEFINITION_BLOCK[NEURONSPI_BOARD_E8DI8RO_HW_DEFINITION_BLOCK_SIZE] = { - 0, 19, // Register block beginning and size - NEURONSPI_REGFUN_DI_READ | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 0 - NEURONSPI_REGFUN_DO_RW | NEURONSPI_REGFLAG_ACC_10HZ, // 1 - NEURONSPI_REGFUN_MWD_STATUS | NEURONSPI_REGFLAG_ACC_6SEC | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 2 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 3 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 4 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 5 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 6 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 7 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 8 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 9 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 10 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 11 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 12 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 13 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 14 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 15 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 16 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 17 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 18 - 1000, 17, // Register block beginning and size - NEURONSPI_REGFUN_SW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1000 - NEURONSPI_REGFUN_DIDO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1001 - NEURONSPI_REGFUN_UAIO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1002 - NEURONSPI_REGFUN_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1003 - NEURONSPI_REGFUN_FLASH_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1004 - NEURONSPI_REGFUN_SERIAL_NR_LOWER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1005 - NEURONSPI_REGFUN_SERIAL_NR_UPPER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1006 - NEURONSPI_REGFUN_INTERRUPTS | NEURONSPI_REGFLAG_ACC_AFAP, // 1007 - NEURONSPI_REGFUN_MWD_TO | NEURONSPI_REGFLAG_ACC_6SEC, // 1008 - NEURONSPI_REGFUN_V_REF_INT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1009 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1010 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1011 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1012 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1013 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1014 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1015 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1016 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1017 - NEURONSPI_REGFUN_DS_ENABLE | NEURONSPI_REGFLAG_ACC_1HZ, // 1018 - NEURONSPI_REGFUN_DS_POLARITY | NEURONSPI_REGFLAG_ACC_1HZ, // 1019 - NEURONSPI_REGFUN_DS_TOGGLE | NEURONSPI_REGFLAG_ACC_1HZ, // 1020 -}; - -#define NEURONSPI_BOARD_E8DI8RO_HW_FEATURES { \ - .do_count = 0, \ - .ro_count = 8, \ - .ds_count = 8, \ - .di_count = 8, \ - .led_count = 0, \ - .stm_ai_count = 0, \ - .stm_ao_count = 0, \ - .sec_ai_count = 0, \ - .sec_ao_count = 0, \ - .uart_master_count = 0, \ - .uart_slave_count = 0, \ - .pwm_channel_count = 0, \ - .wd_count = 1, \ - .extension_sys_count = 0, \ - .light_count = 0, \ - .owire_count = 0, \ -} - -#define NEURONSPI_BOARD_E8DI8RO_HW_DEFINITION { \ - .combination_board_id = 1, \ - .lower_board_id = NEURONSPI_BOARD_LOWER_E8DI8RO_ID, \ - .upper_board_id = NEURONSPI_BOARD_UPPER_NONE_ID, \ - .block_count = NEURONSPI_BOARD_E8DI8RO_HW_DEFINITION_BLOCK_SIZE, \ - .name_length = 8, \ - .combination_name = "E_8Di8Ro", \ - .blocks = NEURONSPI_BOARD_E8DI8RO_HW_DEFINITION_BLOCK, \ - .features = NEURONSPI_BOARD_E8DI8RO_HW_FEATURES \ -} -struct neuronspi_board_combination NEURONSPI_BOARD_E8DI8RO_HW_COMBINATION[] = {NEURONSPI_BOARD_E8DI8RO_HW_DEFINITION}; - -// E-14Ro -#define NEURONSPI_BOARD_E14RO_HW_DEFINITION_BLOCK_SIZE 15 -static u32 NEURONSPI_BOARD_E14RO_HW_DEFINITION_BLOCK[NEURONSPI_BOARD_E14RO_HW_DEFINITION_BLOCK_SIZE] = { - 0, 1, // Register block beginning and size - NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE, // 0 - 1000, 10, - NEURONSPI_REGFUN_SW_VER | NEURONSPI_REGFLAG_ACC_ONCE, // 1000 - NEURONSPI_REGFUN_DIDO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE, // 1001 - NEURONSPI_REGFUN_UAIO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE, // 1002 - NEURONSPI_REGFUN_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE, // 1003 - NEURONSPI_REGFUN_FLASH_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE, // 1004 - NEURONSPI_REGFUN_SERIAL_NR_LOWER | NEURONSPI_REGFLAG_ACC_ONCE, // 1005 - NEURONSPI_REGFUN_SERIAL_NR_UPPER | NEURONSPI_REGFLAG_ACC_ONCE, // 1006 - NEURONSPI_REGFUN_INTERRUPTS | NEURONSPI_REGFLAG_ACC_AFAP, // 1007 - NEURONSPI_REGFUN_MWD_TO | NEURONSPI_REGFLAG_ACC_6SEC, // 1008 - NEURONSPI_REGFUN_V_REF_INT | NEURONSPI_REGFLAG_ACC_ONCE, // 1009 -}; - -#define NEURONSPI_BOARD_E14RO_HW_FEATURES { \ - .do_count = 0, \ - .ro_count = 14, \ - .ds_count = 0, \ - .di_count = 0, \ - .led_count = 0, \ - .stm_ai_count = 0, \ - .stm_ao_count = 0, \ - .sec_ai_count = 0, \ - .sec_ao_count = 0, \ - .uart_master_count = 0, \ - .uart_slave_count = 0, \ - .pwm_channel_count = 0, \ - .wd_count = 1, \ - .extension_sys_count = 0, \ - .light_count = 0, \ - .owire_count = 0, \ -} - -#define NEURONSPI_BOARD_E14RO_HW_DEFINITION { \ - .combination_board_id = 2, \ - .lower_board_id = NEURONSPI_BOARD_LOWER_E14RO_ID, \ - .upper_board_id = NEURONSPI_BOARD_UPPER_NONE_ID, \ - .block_count = NEURONSPI_BOARD_E14RO_HW_DEFINITION_BLOCK_SIZE, \ - .name_length = 6, \ - .combination_name = "E_14Ro", \ - .blocks = NEURONSPI_BOARD_E14RO_HW_DEFINITION_BLOCK, \ - .features = NEURONSPI_BOARD_E14RO_HW_FEATURES \ -} -struct neuronspi_board_combination NEURONSPI_BOARD_E14RO_HW_COMBINATION[] = {NEURONSPI_BOARD_E14RO_HW_DEFINITION}; - -// E-16Di -#define NEURONSPI_BOARD_E16DI_HW_DEFINITION_BLOCK_SIZE 15 -static u32 NEURONSPI_BOARD_E16DI_HW_DEFINITION_BLOCK[NEURONSPI_BOARD_E16DI_HW_DEFINITION_BLOCK_SIZE] = { - 0, 1, // Register block beginning and size - NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE, // 0 - 1000, 10, - NEURONSPI_REGFUN_SW_VER | NEURONSPI_REGFLAG_ACC_ONCE, // 1000 - NEURONSPI_REGFUN_DIDO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE, // 1001 - NEURONSPI_REGFUN_UAIO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE, // 1002 - NEURONSPI_REGFUN_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE, // 1003 - NEURONSPI_REGFUN_FLASH_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE, // 1004 - NEURONSPI_REGFUN_SERIAL_NR_LOWER | NEURONSPI_REGFLAG_ACC_ONCE, // 1005 - NEURONSPI_REGFUN_SERIAL_NR_UPPER | NEURONSPI_REGFLAG_ACC_ONCE, // 1006 - NEURONSPI_REGFUN_INTERRUPTS | NEURONSPI_REGFLAG_ACC_AFAP, // 1007 - NEURONSPI_REGFUN_MWD_TO | NEURONSPI_REGFLAG_ACC_6SEC, // 1008 - NEURONSPI_REGFUN_V_REF_INT | NEURONSPI_REGFLAG_ACC_ONCE, // 1009 -}; - -#define NEURONSPI_BOARD_E16DI_HW_FEATURES { \ - .do_count = 0, \ - .ro_count = 0, \ - .ds_count = 0, \ - .di_count = 16, \ - .led_count = 0, \ - .stm_ai_count = 0, \ - .stm_ao_count = 0, \ - .sec_ai_count = 0, \ - .sec_ao_count = 0, \ - .uart_master_count = 0, \ - .uart_slave_count = 0, \ - .pwm_channel_count = 0, \ - .wd_count = 1, \ - .extension_sys_count = 0, \ - .light_count = 0, \ - .owire_count = 0, \ -} - -#define NEURONSPI_BOARD_E16DI_HW_DEFINITION { \ - .combination_board_id = 3, \ - .lower_board_id = NEURONSPI_BOARD_LOWER_E16DI_ID, \ - .upper_board_id = NEURONSPI_BOARD_UPPER_NONE_ID, \ - .block_count = NEURONSPI_BOARD_E16DI_HW_DEFINITION_BLOCK_SIZE, \ - .name_length = 6, \ - .combination_name = "E_16Di", \ - .blocks = NEURONSPI_BOARD_E16DI_HW_DEFINITION_BLOCK, \ - .features = NEURONSPI_BOARD_E16DI_HW_FEATURES \ -} -struct neuronspi_board_combination NEURONSPI_BOARD_E16DI_HW_COMBINATION[] = {NEURONSPI_BOARD_E16DI_HW_DEFINITION}; - -// E-8Di8Ro_P-11DiR485 (xS10) -#define NEURONSPI_BOARD_E8DI8ROP11DIR485_HW_DEFINITION_BLOCK_SIZE 47 -static u32 NEURONSPI_BOARD_E8DI8ROP11DIR485_HW_DEFINITION_BLOCK[NEURONSPI_BOARD_E8DI8ROP11DIR485_HW_DEFINITION_BLOCK_SIZE] = { - 0, 20, // Register block beginning and size - NEURONSPI_REGFUN_DI_READ | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 0 - NEURONSPI_REGFUN_DO_RW | NEURONSPI_REGFLAG_ACC_10HZ, // 1 - NEURONSPI_REGFUN_MWD_STATUS | NEURONSPI_REGFLAG_ACC_6SEC | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 2 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 3 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 4 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 5 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 6 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 7 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 8 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 9 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 10 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 11 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 12 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 13 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 14 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 15 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 16 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 17 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 18 - NEURONSPI_REGFUN_LED_RW | NEURONSPI_REGFLAG_ACC_1HZ, // 19 - 1000, 23, // Register block beginning and size - NEURONSPI_REGFUN_SW_VER | NEURONSPI_REGFLAG_ACC_ONCE, // 1000 - NEURONSPI_REGFUN_DIDO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE, // 1001 - NEURONSPI_REGFUN_UAIO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE, // 1002 - NEURONSPI_REGFUN_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE, // 1003 - NEURONSPI_REGFUN_FLASH_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE, // 1004 - NEURONSPI_REGFUN_SERIAL_NR_LOWER | NEURONSPI_REGFLAG_ACC_ONCE, // 1005 - NEURONSPI_REGFUN_SERIAL_NR_UPPER | NEURONSPI_REGFLAG_ACC_ONCE, // 1006 - NEURONSPI_REGFUN_INTERRUPTS | NEURONSPI_REGFLAG_ACC_AFAP, // 1007 - NEURONSPI_REGFUN_MWD_TO | NEURONSPI_REGFLAG_ACC_6SEC, // 1008 - NEURONSPI_REGFUN_V_REF_INT | NEURONSPI_REGFLAG_ACC_ONCE, // 1009 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1010 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1011 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1012 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1013 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1014 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1015 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1016 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1017 - NEURONSPI_REGFUN_DS_ENABLE | NEURONSPI_REGFLAG_ACC_1HZ, // 1018 - NEURONSPI_REGFUN_DS_POLARITY | NEURONSPI_REGFLAG_ACC_1HZ, // 1019 - NEURONSPI_REGFUN_DS_TOGGLE | NEURONSPI_REGFLAG_ACC_1HZ, // 1020 - NEURONSPI_REGFUN_RS485_CONFIG | NEURONSPI_REGFLAG_ACC_6SEC, // 1021 - NEURONSPI_REGFUN_RS485_ADDRESS | NEURONSPI_REGFLAG_ACC_6SEC // 1022 -}; - -#define NEURONSPI_BOARD_E8DI8ROP11DIR485_HW_FEATURES { \ - .do_count = 0, \ - .ro_count = 8, \ - .ds_count = 8, \ - .di_count = 8, \ - .led_count = 0, \ - .stm_ai_count = 0, \ - .stm_ao_count = 0, \ - .sec_ai_count = 0, \ - .sec_ao_count = 0, \ - .uart_master_count = 0, \ - .uart_slave_count = 1, \ - .pwm_channel_count = 0, \ - .wd_count = 1, \ - .extension_sys_count = 1, \ - .light_count = 0, \ - .owire_count = 0, \ -} - -#define NEURONSPI_BOARD_E8DI8ROP11DIR485_HW_DEFINITION { \ - .combination_board_id = 4, \ - .lower_board_id = NEURONSPI_BOARD_LOWER_E8DI8RO_ID, \ - .upper_board_id = NEURONSPI_BOARD_UPPER_P11DIR485_ID, \ - .block_count = NEURONSPI_BOARD_E8DI8ROP11DIR485_HW_DEFINITION_BLOCK_SIZE, \ - .name_length = 19, \ - .combination_name = "E_8Di8Ro_P_11DiR485", \ - .blocks = NEURONSPI_BOARD_E8DI8ROP11DIR485_HW_DEFINITION_BLOCK, \ - .features = NEURONSPI_BOARD_E8DI8ROP11DIR485_HW_FEATURES \ -} -struct neuronspi_board_combination NEURONSPI_BOARD_E8DI8ROP11DIR485_HW_COMBINATION[] = {NEURONSPI_BOARD_E8DI8ROP11DIR485_HW_DEFINITION}; - -// E-14Ro_P-11DiR485 (xS40) -#define NEURONSPI_BOARD_E14ROP11DIR485_HW_DEFINITION_BLOCK_SIZE 71 -static u32 NEURONSPI_BOARD_E14ROP11DIR485_HW_DEFINITION_BLOCK[NEURONSPI_BOARD_E14ROP11DIR485_HW_DEFINITION_BLOCK_SIZE] = { - 0, 36, // Register block beginning and size - NEURONSPI_REGFUN_DI_READ | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 0 - NEURONSPI_REGFUN_DO_RW | NEURONSPI_REGFLAG_ACC_10HZ, // 1 - NEURONSPI_REGFUN_MWD_STATUS | NEURONSPI_REGFLAG_ACC_6SEC | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 2 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 3 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 4 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 5 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 6 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 7 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 8 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 9 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 10 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 11 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 12 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 13 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 14 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 15 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 16 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 17 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 18 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 19 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 20 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 21 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 22 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 23 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 24 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 25 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 26 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 27 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 28 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 29 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 30 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 31 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 32 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 33 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 34 - NEURONSPI_REGFUN_LED_RW | NEURONSPI_REGFLAG_ACC_1HZ, // 35 - 1000, 31, // Register block beginning and size - NEURONSPI_REGFUN_SW_VER | NEURONSPI_REGFLAG_ACC_ONCE, // 1000 - NEURONSPI_REGFUN_DIDO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE, // 1001 - NEURONSPI_REGFUN_UAIO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE, // 1002 - NEURONSPI_REGFUN_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE, // 1003 - NEURONSPI_REGFUN_FLASH_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE, // 1004 - NEURONSPI_REGFUN_SERIAL_NR_LOWER | NEURONSPI_REGFLAG_ACC_ONCE, // 1005 - NEURONSPI_REGFUN_SERIAL_NR_UPPER | NEURONSPI_REGFLAG_ACC_ONCE, // 1006 - NEURONSPI_REGFUN_INTERRUPTS | NEURONSPI_REGFLAG_ACC_AFAP, // 1007 - NEURONSPI_REGFUN_MWD_TO | NEURONSPI_REGFLAG_ACC_6SEC, // 1008 - NEURONSPI_REGFUN_V_REF_INT | NEURONSPI_REGFLAG_ACC_ONCE, // 1009 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1010 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1011 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1012 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1013 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1014 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1015 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1016 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1017 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1018 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1019 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1020 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1021 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1022 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1023 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1024 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1025 - NEURONSPI_REGFUN_DS_ENABLE | NEURONSPI_REGFLAG_ACC_1HZ, // 1026 - NEURONSPI_REGFUN_DS_POLARITY | NEURONSPI_REGFLAG_ACC_1HZ, // 1027 - NEURONSPI_REGFUN_DS_TOGGLE | NEURONSPI_REGFLAG_ACC_1HZ, // 1028 - NEURONSPI_REGFUN_RS485_CONFIG | NEURONSPI_REGFLAG_ACC_6SEC, // 1029 - NEURONSPI_REGFUN_RS485_ADDRESS | NEURONSPI_REGFLAG_ACC_6SEC // 1030 -}; - -#define NEURONSPI_BOARD_E14ROP11DIR485_HW_FEATURES { \ - .do_count = 0, \ - .ro_count = 14, \ - .ds_count = 8, \ - .di_count = 8, \ - .led_count = 0, \ - .stm_ai_count = 0, \ - .stm_ao_count = 0, \ - .sec_ai_count = 0, \ - .sec_ao_count = 0, \ - .uart_master_count = 0, \ - .uart_slave_count = 1, \ - .pwm_channel_count = 0, \ - .wd_count = 1, \ - .extension_sys_count = 1, \ - .light_count = 0, \ - .owire_count = 0, \ -} - -#define NEURONSPI_BOARD_E14ROP11DIR485_HW_DEFINITION { \ - .combination_board_id = 5, \ - .lower_board_id = NEURONSPI_BOARD_LOWER_E14RO_ID, \ - .upper_board_id = NEURONSPI_BOARD_UPPER_P11DIR485_ID, \ - .name_length = 17, \ - .combination_name = "E_14Ro_P_11DiR485", \ - .block_count = NEURONSPI_BOARD_E14ROP11DIR485_HW_DEFINITION_BLOCK_SIZE, \ - .blocks = NEURONSPI_BOARD_E14ROP11DIR485_HW_DEFINITION_BLOCK, \ - .features = NEURONSPI_BOARD_E14ROP11DIR485_HW_FEATURES \ -} -struct neuronspi_board_combination NEURONSPI_BOARD_E14ROP11DIR485_HW_COMBINATION[] = {NEURONSPI_BOARD_E14ROP11DIR485_HW_DEFINITION}; - -// E-16Di_P-11DiR485 (xS30) -#define NEURONSPI_BOARD_E16DIP11DIR485_HW_DEFINITION_BLOCK_SIZE 92 -static u32 NEURONSPI_BOARD_E16DIP11DIR485_HW_DEFINITION_BLOCK[NEURONSPI_BOARD_E16DIP11DIR485_HW_DEFINITION_BLOCK_SIZE] = { - 0, 52, // Register block beginning and size - NEURONSPI_REGFUN_DI_READ | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 0 - NEURONSPI_REGFUN_DI_READ | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1 - NEURONSPI_REGFUN_MWD_STATUS | NEURONSPI_REGFLAG_ACC_6SEC, // 2 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 3 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 4 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 5 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 6 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 7 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 8 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 9 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 10 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 11 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 12 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 13 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 14 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 15 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 16 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 17 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 18 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 19 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 20 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 21 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 22 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 23 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 24 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 25 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 26 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 27 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 28 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 29 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 30 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 31 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 32 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 33 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 34 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 35 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 36 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 37 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 38 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 39 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 40 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 41 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 42 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 43 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 44 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 45 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 46 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 47 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 48 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 49 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 50 - NEURONSPI_REGFUN_LED_RW | NEURONSPI_REGFLAG_ACC_1HZ, // 51 - 1000, 36, // Register block beginning and size - NEURONSPI_REGFUN_SW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1000 - NEURONSPI_REGFUN_DIDO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1001 - NEURONSPI_REGFUN_UAIO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1002 - NEURONSPI_REGFUN_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1003 - NEURONSPI_REGFUN_FLASH_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1004 - NEURONSPI_REGFUN_SERIAL_NR_LOWER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1005 - NEURONSPI_REGFUN_SERIAL_NR_UPPER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1006 - NEURONSPI_REGFUN_INTERRUPTS | NEURONSPI_REGFLAG_ACC_AFAP, // 1007 - NEURONSPI_REGFUN_MWD_TO | NEURONSPI_REGFLAG_ACC_6SEC, // 1008 - NEURONSPI_REGFUN_V_REF_INT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1009 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1010 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1011 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1012 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1013 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1014 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1015 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1016 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1017 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1018 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1019 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1020 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1021 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1022 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1023 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1024 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1025 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1026 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1027 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1028 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1029 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1030 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1031 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1032 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1033 - NEURONSPI_REGFUN_RS485_CONFIG | NEURONSPI_REGFLAG_ACC_6SEC, // 1034 - NEURONSPI_REGFUN_RS485_ADDRESS | NEURONSPI_REGFLAG_ACC_6SEC // 1035 -}; - -#define NEURONSPI_BOARD_E16DIP11DIR485_HW_FEATURES { \ - .do_count = 0, \ - .ro_count = 0, \ - .ds_count = 0, \ - .di_count = 23, \ - .led_count = 0, \ - .stm_ai_count = 0, \ - .stm_ao_count = 0, \ - .sec_ai_count = 0, \ - .sec_ao_count = 0, \ - .uart_master_count = 0, \ - .uart_slave_count = 1, \ - .pwm_channel_count = 0, \ - .wd_count = 1, \ - .extension_sys_count = 1, \ - .light_count = 0, \ - .owire_count = 0, \ -} - -#define NEURONSPI_BOARD_E16DIP11DIR485_HW_DEFINITION { \ - .combination_board_id = 6, \ - .lower_board_id = NEURONSPI_BOARD_LOWER_E16DI_ID, \ - .upper_board_id = NEURONSPI_BOARD_UPPER_P11DIR485_ID, \ - .name_length = 17, \ - .combination_name = "E_16Di_P_11DiR485", \ - .block_count = NEURONSPI_BOARD_E16DIP11DIR485_HW_DEFINITION_BLOCK_SIZE, \ - .blocks = NEURONSPI_BOARD_E16DIP11DIR485_HW_DEFINITION_BLOCK, \ - .features = NEURONSPI_BOARD_E16DIP11DIR485_HW_FEATURES \ -} -struct neuronspi_board_combination NEURONSPI_BOARD_E16DIP11DIR485_HW_COMBINATION[] = {NEURONSPI_BOARD_E16DIP11DIR485_HW_DEFINITION}; - -// E-14Ro_U-14Ro (M403) -#define NEURONSPI_BOARD_E14ROU14RO_HW_DEFINITION_BLOCK_SIZE 17 -static u32 NEURONSPI_BOARD_E14ROU14RO_HW_DEFINITION_BLOCK[NEURONSPI_BOARD_E14ROU14RO_HW_DEFINITION_BLOCK_SIZE] = { - 0, 3, // Register block beginning and size - NEURONSPI_REGFUN_DO_RW | NEURONSPI_REGFLAG_ACC_10HZ, // 0 - NEURONSPI_REGFUN_DO_RW | NEURONSPI_REGFLAG_ACC_10HZ, // 1 - NEURONSPI_REGFUN_MWD_STATUS | NEURONSPI_REGFLAG_ACC_6SEC | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 2 - 1000, 10, // Register block beginning and size - NEURONSPI_REGFUN_SW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1000 - NEURONSPI_REGFUN_DIDO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1001 - NEURONSPI_REGFUN_UAIO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1002 - NEURONSPI_REGFUN_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1003 - NEURONSPI_REGFUN_FLASH_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1004 - NEURONSPI_REGFUN_SERIAL_NR_LOWER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1005 - NEURONSPI_REGFUN_SERIAL_NR_UPPER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1006 - NEURONSPI_REGFUN_INTERRUPTS | NEURONSPI_REGFLAG_ACC_AFAP, // 1007 - NEURONSPI_REGFUN_MWD_TO | NEURONSPI_REGFLAG_ACC_6SEC, // 1008 - NEURONSPI_REGFUN_V_REF_INT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1009 -}; - -#define NEURONSPI_BOARD_E14ROU14RO_HW_FEATURES { \ - .do_count = 0, \ - .ro_count = 28, \ - .ds_count = 0, \ - .di_count = 0, \ - .led_count = 0, \ - .stm_ai_count = 0, \ - .stm_ao_count = 0, \ - .sec_ai_count = 0, \ - .sec_ao_count = 0, \ - .uart_master_count = 0, \ - .uart_slave_count = 0, \ - .pwm_channel_count = 0, \ - .wd_count = 1, \ - .extension_sys_count = 1, \ - .light_count = 0, \ - .owire_count = 0, \ -} - -#define NEURONSPI_BOARD_E14ROU14RO_HW_DEFINITION { \ - .combination_board_id = 7, \ - .lower_board_id = NEURONSPI_BOARD_LOWER_E14RO_ID, \ - .upper_board_id = NEURONSPI_BOARD_UPPER_U14RO_ID, \ - .name_length = 13, \ - .combination_name = "E_14Ro_U_14Ro", \ - .block_count = NEURONSPI_BOARD_E14ROU14RO_HW_DEFINITION_BLOCK_SIZE, \ - .blocks = NEURONSPI_BOARD_E14ROU14RO_HW_DEFINITION_BLOCK, \ - .features = NEURONSPI_BOARD_E14ROU14RO_HW_FEATURES \ -} -struct neuronspi_board_combination NEURONSPI_BOARD_E14ROU14RO_HW_COMBINATION[] = {NEURONSPI_BOARD_E14ROU14RO_HW_DEFINITION}; - -// E-16Di_U-14Ro (M203) -#define NEURONSPI_BOARD_E16DIU14RO_HW_DEFINITION_BLOCK_SIZE 68 -static u32 NEURONSPI_BOARD_E16DIU14RO_HW_DEFINITION_BLOCK[NEURONSPI_BOARD_E16DIU14RO_HW_DEFINITION_BLOCK_SIZE] = { - 0, 35, // Register block beginning and size - NEURONSPI_REGFUN_DI_READ | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 0 - NEURONSPI_REGFUN_DO_RW | NEURONSPI_REGFLAG_ACC_10HZ, // 1 - NEURONSPI_REGFUN_MWD_STATUS | NEURONSPI_REGFLAG_ACC_6SEC | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 2 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 3 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 4 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 5 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 6 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 7 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 8 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 9 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 10 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 11 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 12 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 13 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 14 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 15 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 16 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 17 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 18 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 19 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 20 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 21 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 22 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 23 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 24 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 25 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 26 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 27 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 28 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 29 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 30 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 31 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 32 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 33 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 34 - 1000, 29, // Register block beginning and size - NEURONSPI_REGFUN_SW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1000 - NEURONSPI_REGFUN_DIDO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1001 - NEURONSPI_REGFUN_UAIO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1002 - NEURONSPI_REGFUN_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1003 - NEURONSPI_REGFUN_FLASH_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1004 - NEURONSPI_REGFUN_SERIAL_NR_LOWER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1005 - NEURONSPI_REGFUN_SERIAL_NR_UPPER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1006 - NEURONSPI_REGFUN_INTERRUPTS | NEURONSPI_REGFLAG_ACC_AFAP, // 1007 - NEURONSPI_REGFUN_MWD_TO | NEURONSPI_REGFLAG_ACC_6SEC, // 1008 - NEURONSPI_REGFUN_V_REF_INT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1009 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1010 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1011 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1012 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1013 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1014 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1015 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1016 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1017 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1018 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1019 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1020 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1021 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1022 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1023 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1024 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1025 - NEURONSPI_REGFUN_DS_ENABLE | NEURONSPI_REGFLAG_ACC_1HZ, // 1026 - NEURONSPI_REGFUN_DS_POLARITY | NEURONSPI_REGFLAG_ACC_1HZ, // 1027 - NEURONSPI_REGFUN_DS_TOGGLE | NEURONSPI_REGFLAG_ACC_1HZ, // 1028 -}; - -#define NEURONSPI_BOARD_E16DIU14RO_HW_FEATURES { \ - .do_count = 0, \ - .ro_count = 14, \ - .ds_count = 14, \ - .di_count = 16, \ - .led_count = 0, \ - .stm_ai_count = 0, \ - .stm_ao_count = 0, \ - .sec_ai_count = 0, \ - .sec_ao_count = 0, \ - .uart_master_count = 0, \ - .uart_slave_count = 0, \ - .pwm_channel_count = 0, \ - .wd_count = 1, \ - .extension_sys_count = 0, \ - .light_count = 0, \ - .owire_count = 0, \ -} - -#define NEURONSPI_BOARD_E16DIU14RO_HW_DEFINITION { \ - .combination_board_id = 8, \ - .lower_board_id = NEURONSPI_BOARD_LOWER_E16DI_ID, \ - .upper_board_id = NEURONSPI_BOARD_UPPER_U14RO_ID, \ - .name_length = 13, \ - .combination_name = "E_16Di_U_14Ro", \ - .block_count = NEURONSPI_BOARD_E16DIU14RO_HW_DEFINITION_BLOCK_SIZE, \ - .blocks = NEURONSPI_BOARD_E16DIU14RO_HW_DEFINITION_BLOCK, \ - .features = NEURONSPI_BOARD_E16DIU14RO_HW_FEATURES \ -} -struct neuronspi_board_combination NEURONSPI_BOARD_E16DIU14RO_HW_COMBINATION[] = {NEURONSPI_BOARD_E16DIU14RO_HW_DEFINITION}; - -// E-14Ro_U-14Di (L503) -#define NEURONSPI_BOARD_E14ROU14DI_HW_DEFINITION_BLOCK_SIZE 62 -static u32 NEURONSPI_BOARD_E14ROU14DI_HW_DEFINITION_BLOCK[NEURONSPI_BOARD_E14ROU14DI_HW_DEFINITION_BLOCK_SIZE] = { - 0, 31, // Register block beginning and size - NEURONSPI_REGFUN_DI_READ | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 0 - NEURONSPI_REGFUN_DO_RW | NEURONSPI_REGFLAG_ACC_10HZ, // 1 - NEURONSPI_REGFUN_MWD_STATUS | NEURONSPI_REGFLAG_ACC_6SEC | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 2 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 3 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 4 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 5 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 6 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 7 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 8 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 9 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 10 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 11 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 12 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 13 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 14 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 15 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 16 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 17 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 18 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 19 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 20 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 21 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 22 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 23 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 24 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 25 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 26 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 27 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 28 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 29 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 30 - 1000, 27, // Register block beginning and size - NEURONSPI_REGFUN_SW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1000 - NEURONSPI_REGFUN_DIDO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1001 - NEURONSPI_REGFUN_UAIO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1002 - NEURONSPI_REGFUN_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1003 - NEURONSPI_REGFUN_FLASH_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1004 - NEURONSPI_REGFUN_SERIAL_NR_LOWER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1005 - NEURONSPI_REGFUN_SERIAL_NR_UPPER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1006 - NEURONSPI_REGFUN_INTERRUPTS | NEURONSPI_REGFLAG_ACC_AFAP, // 1007 - NEURONSPI_REGFUN_MWD_TO | NEURONSPI_REGFLAG_ACC_6SEC, // 1008 - NEURONSPI_REGFUN_V_REF_INT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1009 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1010 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1011 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1012 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1013 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1014 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1015 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1016 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1017 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1018 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1019 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1020 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1021 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1022 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1023 - NEURONSPI_REGFUN_DS_ENABLE | NEURONSPI_REGFLAG_ACC_1HZ, // 1024 - NEURONSPI_REGFUN_DS_POLARITY | NEURONSPI_REGFLAG_ACC_1HZ, // 1025 - NEURONSPI_REGFUN_DS_TOGGLE | NEURONSPI_REGFLAG_ACC_1HZ // 1026 -}; - -#define NEURONSPI_BOARD_E14ROU14DI_HW_FEATURES { \ - .do_count = 0, \ - .ro_count = 14, \ - .ds_count = 14, \ - .di_count = 14, \ - .led_count = 0, \ - .stm_ai_count = 0, \ - .stm_ao_count = 0, \ - .sec_ai_count = 0, \ - .sec_ao_count = 0, \ - .uart_master_count = 0, \ - .uart_slave_count = 0, \ - .pwm_channel_count = 0, \ - .wd_count = 1, \ - .extension_sys_count = 0, \ - .light_count = 0, \ - .owire_count = 0, \ -} - -#define NEURONSPI_BOARD_E14ROU14DI_HW_DEFINITION { \ - .combination_board_id = 9, \ - .lower_board_id = NEURONSPI_BOARD_LOWER_E14RO_ID, \ - .upper_board_id = NEURONSPI_BOARD_UPPER_U14DI_ID, \ - .name_length = 13, \ - .combination_name = "E_14Ro_U_14Di", \ - .block_count = NEURONSPI_BOARD_E14ROU14DI_HW_DEFINITION_BLOCK_SIZE, \ - .blocks = NEURONSPI_BOARD_E14ROU14DI_HW_DEFINITION_BLOCK, \ - .features = NEURONSPI_BOARD_E14ROU14DI_HW_FEATURES \ -} -struct neuronspi_board_combination NEURONSPI_BOARD_E14ROU14DI_HW_COMBINATION[] = {NEURONSPI_BOARD_E14ROU14DI_HW_DEFINITION}; - - -// E-16Di_U-14Di (M303) -#define NEURONSPI_BOARD_E16DIU14DI_HW_DEFINITION_BLOCK_SIZE 107 -static u32 NEURONSPI_BOARD_E16DIU14DI_HW_DEFINITION_BLOCK[NEURONSPI_BOARD_E16DIU14DI_HW_DEFINITION_BLOCK_SIZE] = { - 0, 63, // Register block beginning and size - NEURONSPI_REGFUN_DI_READ | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 0 - NEURONSPI_REGFUN_DO_RW | NEURONSPI_REGFLAG_ACC_10HZ, // 1 - NEURONSPI_REGFUN_MWD_STATUS | NEURONSPI_REGFLAG_ACC_6SEC | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 2 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 3 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 4 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 5 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 6 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 7 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 8 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 9 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 10 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 11 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 12 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 13 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 14 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 15 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 16 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 17 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 18 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 19 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 20 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 21 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 22 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 23 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 24 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 25 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 26 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 27 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 28 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 29 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 30 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 31 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 32 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 33 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 34 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 35 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 36 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 37 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 38 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 39 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 40 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 41 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 42 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 43 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 44 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 45 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 46 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 47 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 48 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 49 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 50 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 51 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 52 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 53 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 54 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 55 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 56 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 57 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 58 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 59 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 60 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 61 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 62 - 1000, 40, // Register block beginning and size - NEURONSPI_REGFUN_SW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1000 - NEURONSPI_REGFUN_DIDO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1001 - NEURONSPI_REGFUN_UAIO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1002 - NEURONSPI_REGFUN_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1003 - NEURONSPI_REGFUN_FLASH_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1004 - NEURONSPI_REGFUN_SERIAL_NR_LOWER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1005 - NEURONSPI_REGFUN_SERIAL_NR_UPPER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1006 - NEURONSPI_REGFUN_INTERRUPTS | NEURONSPI_REGFLAG_ACC_AFAP, // 1007 - NEURONSPI_REGFUN_MWD_TO | NEURONSPI_REGFLAG_ACC_6SEC, // 1008 - NEURONSPI_REGFUN_V_REF_INT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1009 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1010 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1011 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1012 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1013 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1014 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1015 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1016 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1017 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1018 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1019 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1020 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1021 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1022 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1023 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1024 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1025 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1026 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1027 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1028 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1029 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1030 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1031 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1032 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1033 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1034 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1035 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1036 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1037 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1038 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1039 -}; - -#define NEURONSPI_BOARD_E16DIU14DI_HW_FEATURES { \ - .do_count = 0, \ - .ro_count = 0, \ - .ds_count = 0, \ - .di_count = 30, \ - .led_count = 0, \ - .stm_ai_count = 0, \ - .stm_ao_count = 0, \ - .sec_ai_count = 0, \ - .sec_ao_count = 0, \ - .uart_master_count = 0, \ - .uart_slave_count = 0, \ - .pwm_channel_count = 0, \ - .wd_count = 1, \ - .extension_sys_count = 0, \ - .light_count = 0, \ - .owire_count = 0, \ -} - -#define NEURONSPI_BOARD_E16DIU14DI_HW_DEFINITION { \ - .combination_board_id = 10, \ - .lower_board_id = NEURONSPI_BOARD_LOWER_E16DI_ID, \ - .upper_board_id = NEURONSPI_BOARD_UPPER_U14DI_ID, \ - .name_length = 13, \ - .combination_name = "E_16Di_U_14Di", \ - .block_count = NEURONSPI_BOARD_E16DIU14DI_HW_DEFINITION_BLOCK_SIZE, \ - .blocks = NEURONSPI_BOARD_E16DIU14DI_HW_DEFINITION_BLOCK, \ - .features = NEURONSPI_BOARD_E16DIU14DI_HW_FEATURES \ -} -struct neuronspi_board_combination NEURONSPI_BOARD_E16DIU14DI_HW_COMBINATION[] = {NEURONSPI_BOARD_E16DIU14DI_HW_DEFINITION}; - -// E-4Ai4Ao -#define NEURONSPI_BOARD_E4AI4AO_HW_DEFINITION_BLOCK_SIZE 15 -static u32 NEURONSPI_BOARD_E4AI4AO_HW_DEFINITION_BLOCK[NEURONSPI_BOARD_E4AI4AO_HW_DEFINITION_BLOCK_SIZE] = { - 0, 1, // Register block beginning and size - NEURONSPI_REGFUN_DO_RW | NEURONSPI_REGFLAG_ACC_10HZ | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 0 - 1000, 10, // Register block beginning and size - NEURONSPI_REGFUN_SW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1000 - NEURONSPI_REGFUN_DIDO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1001 - NEURONSPI_REGFUN_UAIO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1002 - NEURONSPI_REGFUN_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1003 - NEURONSPI_REGFUN_FLASH_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1004 - NEURONSPI_REGFUN_SERIAL_NR_LOWER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1005 - NEURONSPI_REGFUN_SERIAL_NR_UPPER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1006 - NEURONSPI_REGFUN_INTERRUPTS | NEURONSPI_REGFLAG_ACC_AFAP, // 1007 - NEURONSPI_REGFUN_MWD_TO | NEURONSPI_REGFLAG_ACC_6SEC, // 1008 - NEURONSPI_REGFUN_V_REF_INT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1009 -}; - -#define NEURONSPI_BOARD_E4AI4AO_HW_FEATURES { \ - .do_count = 0, \ - .ro_count = 0, \ - .ds_count = 0, \ - .di_count = 0, \ - .led_count = 0, \ - .stm_ai_count = 0, \ - .stm_ao_count = 0, \ - .sec_ai_count = 4, \ - .sec_ao_count = 4, \ - .uart_master_count = 0, \ - .uart_slave_count = 0, \ - .pwm_channel_count = 0, \ - .wd_count = 1, \ - .extension_sys_count = 0, \ - .light_count = 0, \ - .owire_count = 0, \ -} - - -#define NEURONSPI_BOARD_E4AI4AO_HW_DEFINITION { \ - .combination_board_id = 11, \ - .lower_board_id = NEURONSPI_BOARD_LOWER_E4AI4AO_ID, \ - .upper_board_id = NEURONSPI_BOARD_UPPER_NONE_ID, \ - .name_length = 8, \ - .combination_name = "E_4Ai4Ao", \ - .block_count = NEURONSPI_BOARD_E4AI4AO_HW_DEFINITION_BLOCK_SIZE, \ - .blocks = NEURONSPI_BOARD_E4AI4AO_HW_DEFINITION_BLOCK, \ - .features = NEURONSPI_BOARD_E4AI4AO_HW_FEATURES \ -} -struct neuronspi_board_combination NEURONSPI_BOARD_E4AI4AO_HW_COMBINATION[] = {NEURONSPI_BOARD_E4AI4AO_HW_DEFINITION}; - -// E-4Ai4Ao_P-6Di5Ro (xS50) -#define NEURONSPI_BOARD_E4AI4AOP6DI5RO_HW_DEFINITION_BLOCK_SIZE 56 -static u32 NEURONSPI_BOARD_E4AI4AOP6DI5RO_HW_DEFINITION_BLOCK[NEURONSPI_BOARD_E4AI4AOP6DI5RO_HW_DEFINITION_BLOCK_SIZE] = { - 0, 27, // Register block beginning and size - NEURONSPI_REGFUN_DI_READ | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 0 - NEURONSPI_REGFUN_DO_RW | NEURONSPI_REGFLAG_ACC_10HZ, // 1 - NEURONSPI_REGFUN_AO_VER2_RW | NEURONSPI_REGFLAG_ACC_10HZ, // 2 - NEURONSPI_REGFUN_AO_VER2_RW | NEURONSPI_REGFLAG_ACC_10HZ, // 3 - NEURONSPI_REGFUN_AO_VER2_RW | NEURONSPI_REGFLAG_ACC_10HZ, // 4 - NEURONSPI_REGFUN_AO_VER2_RW | NEURONSPI_REGFLAG_ACC_10HZ, // 5 - NEURONSPI_REGFUN_AI_VER2_READ_LOWER | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 6 - NEURONSPI_REGFUN_AI_VER2_READ_UPPER | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 7 - NEURONSPI_REGFUN_AI_VER2_READ_LOWER | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 8 - NEURONSPI_REGFUN_AI_VER2_READ_UPPER | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 9 - NEURONSPI_REGFUN_AI_VER2_READ_LOWER | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 10 - NEURONSPI_REGFUN_AI_VER2_READ_UPPER | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 11 - NEURONSPI_REGFUN_AI_VER2_READ_LOWER | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 12 - NEURONSPI_REGFUN_AI_VER2_READ_UPPER | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 13 - NEURONSPI_REGFUN_MWD_STATUS | NEURONSPI_REGFLAG_ACC_6SEC, // 14 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 15 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 16 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 17 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 18 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 19 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 20 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 21 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 22 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 23 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 24 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 25 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 26 - 1000, 25, // Register block beginning and size - NEURONSPI_REGFUN_SW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1000 - NEURONSPI_REGFUN_DIDO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1001 - NEURONSPI_REGFUN_UAIO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1002 - NEURONSPI_REGFUN_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1003 - NEURONSPI_REGFUN_FLASH_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1004 - NEURONSPI_REGFUN_SERIAL_NR_LOWER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1005 - NEURONSPI_REGFUN_SERIAL_NR_UPPER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1006 - NEURONSPI_REGFUN_INTERRUPTS | NEURONSPI_REGFLAG_ACC_AFAP, // 1007 - NEURONSPI_REGFUN_MWD_TO | NEURONSPI_REGFLAG_ACC_6SEC, // 1008 - NEURONSPI_REGFUN_V_REF_INT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1009 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1010 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1011 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1012 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1013 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1014 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1015 - NEURONSPI_REGFUN_DS_ENABLE | NEURONSPI_REGFLAG_ACC_1HZ, // 1016 - NEURONSPI_REGFUN_DS_POLARITY | NEURONSPI_REGFLAG_ACC_1HZ, // 1017 - NEURONSPI_REGFUN_DS_TOGGLE | NEURONSPI_REGFLAG_ACC_1HZ, // 1018 - NEURONSPI_REGFUN_AI_VER2_MODE | NEURONSPI_REGFLAG_ACC_1HZ, // 1019 - NEURONSPI_REGFUN_AI_VER2_MODE | NEURONSPI_REGFLAG_ACC_1HZ, // 1020 - NEURONSPI_REGFUN_AI_VER2_MODE | NEURONSPI_REGFLAG_ACC_1HZ, // 1021 - NEURONSPI_REGFUN_AI_VER2_MODE | NEURONSPI_REGFLAG_ACC_1HZ, // 1022 - NEURONSPI_REGFUN_RS485_CONFIG | NEURONSPI_REGFLAG_ACC_6SEC, // 1023 - NEURONSPI_REGFUN_RS485_ADDRESS | NEURONSPI_REGFLAG_ACC_6SEC // 1024 -}; - -#define NEURONSPI_BOARD_E4AI4AOP6DI5RO_HW_FEATURES { \ - .do_count = 0, \ - .ro_count = 6, \ - .ds_count = 5, \ - .di_count = 5, \ - .led_count = 0, \ - .stm_ai_count = 0, \ - .stm_ao_count = 0, \ - .sec_ai_count = 4, \ - .sec_ao_count = 4, \ - .uart_master_count = 0, \ - .uart_slave_count = 1, \ - .pwm_channel_count = 0, \ - .wd_count = 1, \ - .extension_sys_count = 1, \ - .light_count = 0, \ - .owire_count = 0, \ -} - -#define NEURONSPI_BOARD_E4AI4AOP6DI5RO_HW_DEFINITION { \ - .combination_board_id = 12, \ - .lower_board_id = NEURONSPI_BOARD_LOWER_E4AI4AO_ID, \ - .upper_board_id = NEURONSPI_BOARD_UPPER_P6DI5RO_ID, \ - .name_length = 17, \ - .combination_name = "E_4Ai4Ao_P_6Di5Ro", \ - .block_count = NEURONSPI_BOARD_E4AI4AOP6DI5RO_HW_DEFINITION_BLOCK_SIZE, \ - .blocks = NEURONSPI_BOARD_E4AI4AOP6DI5RO_HW_DEFINITION_BLOCK, \ - .features = NEURONSPI_BOARD_E4AI4AOP6DI5RO_HW_FEATURES \ -} -struct neuronspi_board_combination NEURONSPI_BOARD_E4AI4AOP6DI5RO_HW_COMBINATION[] = {NEURONSPI_BOARD_E4AI4AOP6DI5RO_HW_DEFINITION}; - -// B-485 -#define NEURONSPI_BOARD_B485_HW_DEFINITION_BLOCK_SIZE 15 -static u32 NEURONSPI_BOARD_B485_HW_DEFINITION_BLOCK[NEURONSPI_BOARD_B485_HW_DEFINITION_BLOCK_SIZE] = { - 0, 1, // Register block beginning and size - NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE, // 0 - 1000, 10, - NEURONSPI_REGFUN_SW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1000 - NEURONSPI_REGFUN_DIDO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1001 - NEURONSPI_REGFUN_UAIO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1002 - NEURONSPI_REGFUN_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1003 - NEURONSPI_REGFUN_FLASH_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1004 - NEURONSPI_REGFUN_SERIAL_NR_LOWER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1005 - NEURONSPI_REGFUN_SERIAL_NR_UPPER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1006 - NEURONSPI_REGFUN_INTERRUPTS | NEURONSPI_REGFLAG_ACC_AFAP, // 1007 - NEURONSPI_REGFUN_MWD_TO | NEURONSPI_REGFLAG_ACC_6SEC, // 1008 - NEURONSPI_REGFUN_V_REF_INT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1009 -}; - -#define NEURONSPI_BOARD_B485_HW_FEATURES { \ - .do_count = 0, \ - .ro_count = 0, \ - .ds_count = 0, \ - .di_count = 0, \ - .led_count = 0, \ - .stm_ai_count = 0, \ - .stm_ao_count = 0, \ - .sec_ai_count = 4, \ - .sec_ao_count = 4, \ - .uart_master_count = 1, \ - .uart_slave_count = 0, \ - .pwm_channel_count = 0, \ - .wd_count = 1, \ - .extension_sys_count = 0, \ - .light_count = 0, \ - .owire_count = 0, \ -} - -#define NEURONSPI_BOARD_B485_HW_DEFINITION { \ - .combination_board_id = 13, \ - .lower_board_id = NEURONSPI_BOARD_LOWER_B485_ID, \ - .upper_board_id = NEURONSPI_BOARD_UPPER_NONE_ID, \ - .name_length = 5, \ - .combination_name = "B_485", \ - .block_count = NEURONSPI_BOARD_B485_HW_DEFINITION_BLOCK_SIZE, \ - .blocks = NEURONSPI_BOARD_B485_HW_DEFINITION_BLOCK, \ - .features = NEURONSPI_BOARD_B485_HW_FEATURES \ -} -struct neuronspi_board_combination NEURONSPI_BOARD_B485_HW_COMBINATION[] = {NEURONSPI_BOARD_B485_HW_DEFINITION}; - -// E-4Light (M613) -#define NEURONSPI_BOARD_E4LIGHT_HW_DEFINITION_BLOCK_SIZE 35 -static u32 NEURONSPI_BOARD_E4LIGHT_HW_DEFINITION_BLOCK[NEURONSPI_BOARD_E4LIGHT_HW_DEFINITION_BLOCK_SIZE] = { - 0, 21, // Register block beginning and size - NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE, // 0 - NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE, // 1 - NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE, // 2 - NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE, // 3 - NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE, // 4 - NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE, // 5 - NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE, // 6 - NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE, // 7 - NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE, // 8 - NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE, // 9 - NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE, // 10 - NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE, // 11 - NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE, // 12 - NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE, // 13 - NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE, // 14 - NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE, // 15 - NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE, // 16 - NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE, // 17 - NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE, // 18 - NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE, // 19 - NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE, // 20 - 1000, 10, - NEURONSPI_REGFUN_SW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1000 - NEURONSPI_REGFUN_DIDO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1001 - NEURONSPI_REGFUN_UAIO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1002 - NEURONSPI_REGFUN_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1003 - NEURONSPI_REGFUN_FLASH_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1004 - NEURONSPI_REGFUN_SERIAL_NR_LOWER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1005 - NEURONSPI_REGFUN_SERIAL_NR_UPPER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1006 - NEURONSPI_REGFUN_INTERRUPTS | NEURONSPI_REGFLAG_ACC_AFAP, // 1007 - NEURONSPI_REGFUN_MWD_TO | NEURONSPI_REGFLAG_ACC_6SEC, // 1008 - NEURONSPI_REGFUN_V_REF_INT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1009 -}; - -#define NEURONSPI_BOARD_E4LIGHT_HW_FEATURES { \ - .do_count = 0, \ - .ro_count = 0, \ - .ds_count = 0, \ - .di_count = 0, \ - .led_count = 0, \ - .stm_ai_count = 0, \ - .stm_ao_count = 0, \ - .sec_ai_count = 0, \ - .sec_ao_count = 0, \ - .uart_master_count = 0, \ - .uart_slave_count = 0, \ - .pwm_channel_count = 0, \ - .wd_count = 1, \ - .extension_sys_count = 0, \ - .light_count = 4, \ - .owire_count = 0, \ -} - -#define NEURONSPI_BOARD_E4LIGHT_HW_DEFINITION { \ - .combination_board_id = 14, \ - .lower_board_id = NEURONSPI_BOARD_LOWER_E4LIGHT_ID, \ - .upper_board_id = NEURONSPI_BOARD_UPPER_NONE_ID, \ - .name_length = 8, \ - .combination_name = "E_4Light", \ - .block_count = NEURONSPI_BOARD_E4LIGHT_HW_DEFINITION_BLOCK_SIZE, \ - .blocks = NEURONSPI_BOARD_E4LIGHT_HW_DEFINITION_BLOCK, \ - .features = NEURONSPI_BOARD_E4LIGHT_HW_FEATURES \ -} -struct neuronspi_board_combination NEURONSPI_BOARD_E4LIGHT_HW_COMBINATION[] = {NEURONSPI_BOARD_E4LIGHT_HW_DEFINITION}; - -// E-4Ai4Ao_U-6Di5Ro (L503) -#define NEURONSPI_BOARD_E4AI4AOU6DI5RO_HW_DEFINITION_BLOCK_SIZE 56 -static u32 NEURONSPI_BOARD_E4AI4AOU6DI5RO_HW_DEFINITION_BLOCK[NEURONSPI_BOARD_E4AI4AOU6DI5RO_HW_DEFINITION_BLOCK_SIZE] = { - 0, 28, // Register block beginning and size - NEURONSPI_REGFUN_DI_READ | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 0 - NEURONSPI_REGFUN_DO_RW | NEURONSPI_REGFLAG_ACC_10HZ, // 1 - NEURONSPI_REGFUN_AO_VER2_RW | NEURONSPI_REGFLAG_ACC_AFAP, // 2 - NEURONSPI_REGFUN_AO_VER2_RW | NEURONSPI_REGFLAG_ACC_AFAP, // 3 - NEURONSPI_REGFUN_AO_VER2_RW | NEURONSPI_REGFLAG_ACC_AFAP, // 4 - NEURONSPI_REGFUN_AO_VER2_RW | NEURONSPI_REGFLAG_ACC_AFAP, // 5 - NEURONSPI_REGFUN_AI_VER2_READ_LOWER | NEURONSPI_REGFLAG_ACC_AFAP, // 6 - NEURONSPI_REGFUN_AI_VER2_READ_UPPER | NEURONSPI_REGFLAG_ACC_AFAP, // 7 - NEURONSPI_REGFUN_AI_VER2_READ_LOWER | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 8 - NEURONSPI_REGFUN_AI_VER2_READ_UPPER | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 9 - NEURONSPI_REGFUN_AI_VER2_READ_LOWER | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 10 - NEURONSPI_REGFUN_AI_VER2_READ_UPPER | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 11 - NEURONSPI_REGFUN_AI_VER2_READ_LOWER | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 12 - NEURONSPI_REGFUN_AI_VER2_READ_UPPER | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 13 - NEURONSPI_REGFUN_MWD_STATUS | NEURONSPI_REGFLAG_ACC_6SEC | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 14 - NEURONSPI_REGFUN_TX_QUEUE_LEN | NEURONSPI_REGFLAG_ACC_10HZ, // 15 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 16 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 17 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 18 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 19 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 20 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 21 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 22 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 23 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 24 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 25 - NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 26 - NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 27 - 1000, 24, // Register block beginning and size - NEURONSPI_REGFUN_SW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1000 - NEURONSPI_REGFUN_DIDO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1001 - NEURONSPI_REGFUN_UAIO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1002 - NEURONSPI_REGFUN_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1003 - NEURONSPI_REGFUN_FLASH_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1004 - NEURONSPI_REGFUN_SERIAL_NR_LOWER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1005 - NEURONSPI_REGFUN_SERIAL_NR_UPPER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1006 - NEURONSPI_REGFUN_INTERRUPTS | NEURONSPI_REGFLAG_ACC_AFAP, // 1007 - NEURONSPI_REGFUN_MWD_TO | NEURONSPI_REGFLAG_ACC_6SEC, // 1008 - NEURONSPI_REGFUN_V_REF_INT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1009 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1010 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1011 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1012 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1013 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1014 - NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1015 - NEURONSPI_REGFUN_DS_ENABLE | NEURONSPI_REGFLAG_ACC_1HZ, // 1016 - NEURONSPI_REGFUN_DS_POLARITY | NEURONSPI_REGFLAG_ACC_1HZ, // 1017 - NEURONSPI_REGFUN_DS_TOGGLE | NEURONSPI_REGFLAG_ACC_1HZ, // 1018 - NEURONSPI_REGFUN_AI_VER2_MODE | NEURONSPI_REGFLAG_ACC_1HZ, // 1019 - NEURONSPI_REGFUN_AI_VER2_MODE | NEURONSPI_REGFLAG_ACC_1HZ, // 1020 - NEURONSPI_REGFUN_AI_VER2_MODE | NEURONSPI_REGFLAG_ACC_1HZ, // 1021 - NEURONSPI_REGFUN_AI_VER2_MODE | NEURONSPI_REGFLAG_ACC_1HZ, // 1022 - NEURONSPI_REGFUN_RS485_CONFIG | NEURONSPI_REGFLAG_ACC_6SEC // 1023 -}; - -#define NEURONSPI_BOARD_E4AI4AOU6DI5RO_HW_FEATURES { \ - .do_count = 0, \ - .ro_count = 5, \ - .ds_count = 5, \ - .di_count = 6, \ - .led_count = 0, \ - .stm_ai_count = 0, \ - .stm_ao_count = 0, \ - .sec_ai_count = 4, \ - .sec_ao_count = 4, \ - .uart_master_count = 0, \ - .uart_slave_count = 0, \ - .pwm_channel_count = 0, \ - .wd_count = 1, \ - .extension_sys_count = 0, \ - .light_count = 4, \ - .owire_count = 0, \ -} - -#define NEURONSPI_BOARD_E4AI4AOU6DI5RO_HW_DEFINITION { \ - .combination_board_id = 15, \ - .lower_board_id = NEURONSPI_BOARD_LOWER_E4AI4AO_ID, \ - .upper_board_id = NEURONSPI_BOARD_UPPER_U6DI5RO_ID, \ - .name_length = 17, \ - .combination_name = "E_4Ai4Ao_U_6Di5Ro", \ - .block_count = NEURONSPI_BOARD_E4AI4AOU6DI5RO_HW_DEFINITION_BLOCK_SIZE, \ - .blocks = NEURONSPI_BOARD_E4AI4AOU6DI5RO_HW_DEFINITION_BLOCK, \ - .features = NEURONSPI_BOARD_E4AI4AOU6DI5RO_HW_FEATURES \ -} -struct neuronspi_board_combination NEURONSPI_BOARD_E4AI4AOU6DI5RO_HW_COMBINATION[] = {NEURONSPI_BOARD_E4AI4AOU6DI5RO_HW_DEFINITION}; - -/******************** - * Data Definitions * - ********************/ - -struct platform_device *neuron_plc_dev; - -struct neuronspi_board_combination NEURONSPI_MODEL_S103_HW_DEFINITION_BOARD[NEURONSPI_MODEL_S103_HW_DEFINITION_BOARD_SIZE] = { - NEURONSPI_BOARD_B1000_HW_DEFINITION -}; - -struct neuronspi_board_combination NEURONSPI_MODEL_S103G_HW_DEFINITION_BOARD[NEURONSPI_MODEL_S103G_HW_DEFINITION_BOARD_SIZE] = { - NEURONSPI_BOARD_B1000_HW_DEFINITION -}; - -struct neuronspi_board_combination NEURONSPI_MODEL_S103IQ_HW_DEFINITION_BOARD[NEURONSPI_MODEL_S103IQ_HW_DEFINITION_BOARD_SIZE] = { - NEURONSPI_BOARD_B1000_HW_DEFINITION -}; - -struct neuronspi_board_combination NEURONSPI_MODEL_S103EO_HW_DEFINITION_BOARD[NEURONSPI_MODEL_S103EO_HW_DEFINITION_BOARD_SIZE] = { - NEURONSPI_BOARD_B1000_HW_DEFINITION -}; - -struct neuronspi_board_combination NEURONSPI_MODEL_M103_HW_DEFINITION_BOARD[NEURONSPI_MODEL_M103_HW_DEFINITION_BOARD_SIZE] = { - NEURONSPI_BOARD_B1000_HW_DEFINITION, NEURONSPI_BOARD_E8DI8RO_HW_DEFINITION -}; - -struct neuronspi_board_combination NEURONSPI_MODEL_M203_HW_DEFINITION_BOARD[NEURONSPI_MODEL_M203_HW_DEFINITION_BOARD_SIZE] = { - NEURONSPI_BOARD_B1000_HW_DEFINITION, NEURONSPI_BOARD_E16DIU14RO_HW_DEFINITION -}; - -struct neuronspi_board_combination NEURONSPI_MODEL_M303_HW_DEFINITION_BOARD[NEURONSPI_MODEL_M303_HW_DEFINITION_BOARD_SIZE] = { - NEURONSPI_BOARD_B1000_HW_DEFINITION, NEURONSPI_BOARD_E16DIU14DI_HW_DEFINITION -}; - -struct neuronspi_board_combination NEURONSPI_MODEL_M403_HW_DEFINITION_BOARD[NEURONSPI_MODEL_M403_HW_DEFINITION_BOARD_SIZE] = { - NEURONSPI_BOARD_B1000_HW_DEFINITION, NEURONSPI_BOARD_E14ROU14RO_HW_DEFINITION -}; - -struct neuronspi_board_combination NEURONSPI_MODEL_M503_HW_DEFINITION_BOARD[NEURONSPI_MODEL_M503_HW_DEFINITION_BOARD_SIZE] = { - NEURONSPI_BOARD_B1000_HW_DEFINITION, NEURONSPI_BOARD_E4AI4AOU6DI5RO_HW_DEFINITION -}; - -struct neuronspi_board_combination NEURONSPI_MODEL_M603_HW_DEFINITION_BOARD[NEURONSPI_MODEL_M603_HW_DEFINITION_BOARD_SIZE] = { - NEURONSPI_BOARD_B1000_HW_DEFINITION, NEURONSPI_BOARD_E4LIGHT_HW_DEFINITION -}; - -struct neuronspi_board_combination NEURONSPI_MODEL_L203_HW_DEFINITION_BOARD[NEURONSPI_MODEL_L203_HW_DEFINITION_BOARD_SIZE] = { - NEURONSPI_BOARD_B1000_HW_DEFINITION, NEURONSPI_BOARD_E16DIU14RO_HW_DEFINITION, NEURONSPI_BOARD_E16DIU14RO_HW_DEFINITION -}; - -struct neuronspi_board_combination NEURONSPI_MODEL_L303_HW_DEFINITION_BOARD[NEURONSPI_MODEL_L303_HW_DEFINITION_BOARD_SIZE] = { - NEURONSPI_BOARD_B1000_HW_DEFINITION, NEURONSPI_BOARD_E16DIU14DI_HW_DEFINITION, NEURONSPI_BOARD_E16DIU14DI_HW_DEFINITION -}; - -struct neuronspi_board_combination NEURONSPI_MODEL_L403_HW_DEFINITION_BOARD[NEURONSPI_MODEL_L403_HW_DEFINITION_BOARD_SIZE] = { - NEURONSPI_BOARD_B1000_HW_DEFINITION, NEURONSPI_BOARD_E14ROU14RO_HW_DEFINITION, NEURONSPI_BOARD_E14ROU14RO_HW_DEFINITION -}; - -struct neuronspi_board_combination NEURONSPI_MODEL_L503_HW_DEFINITION_BOARD[NEURONSPI_MODEL_L503_HW_DEFINITION_BOARD_SIZE] = { - NEURONSPI_BOARD_B1000_HW_DEFINITION, NEURONSPI_BOARD_E4AI4AOU6DI5RO_HW_DEFINITION, NEURONSPI_BOARD_E14ROU14DI_HW_DEFINITION -}; - -struct neuronspi_board_combination NEURONSPI_MODEL_L513_HW_DEFINITION_BOARD[NEURONSPI_MODEL_L513_HW_DEFINITION_BOARD_SIZE] = { - NEURONSPI_BOARD_B1000_HW_DEFINITION, NEURONSPI_BOARD_E4AI4AOU6DI5RO_HW_DEFINITION, NEURONSPI_BOARD_E4AI4AOU6DI5RO_HW_DEFINITION -}; - -// Board table -// Column 4 is the number of 0-indexed registers and column 5 is the number of 1000-indexed ones -struct neuronspi_board_entry NEURONSPI_BOARDTABLE[NEURONSPI_BOARDTABLE_LEN] = { - {.index = 0, .lower_board_id = NEURONSPI_BOARD_LOWER_B1000_ID, .upper_board_id = NEURONSPI_BOARD_UPPER_NONE_ID, - .data_register_count = 21, .config_register_count = 32, .definition = NEURONSPI_BOARD_B1000_HW_COMBINATION}, // B_1000 (S103) - {.index = 1, .lower_board_id = NEURONSPI_BOARD_LOWER_E8DI8RO_ID, .upper_board_id = NEURONSPI_BOARD_UPPER_NONE_ID, - .data_register_count = 19, .config_register_count = 21, .definition = NEURONSPI_BOARD_E8DI8RO_HW_COMBINATION}, // E-8Di8Ro (M103) - {.index = 2, .lower_board_id = NEURONSPI_BOARD_LOWER_E14RO_ID, .upper_board_id = NEURONSPI_BOARD_UPPER_NONE_ID, - .data_register_count = 1, .config_register_count = 0, .definition = NEURONSPI_BOARD_E14RO_HW_COMBINATION}, // E-14Ro - {.index = 3, .lower_board_id = NEURONSPI_BOARD_LOWER_E16DI_ID, .upper_board_id = NEURONSPI_BOARD_UPPER_NONE_ID, - .data_register_count = 1, .config_register_count = 0, .definition = NEURONSPI_BOARD_E16DI_HW_COMBINATION}, // E-16Di - {.index = 4, .lower_board_id = NEURONSPI_BOARD_LOWER_E8DI8RO_ID, .upper_board_id = NEURONSPI_BOARD_UPPER_P11DIR485_ID, - .data_register_count = 36, .config_register_count = 31, .definition = NEURONSPI_BOARD_E8DI8ROP11DIR485_HW_COMBINATION}, // E-8Di8Ro_P-11DiR485 (xS10) - {.index = 5, .lower_board_id = NEURONSPI_BOARD_LOWER_E14RO_ID, .upper_board_id = NEURONSPI_BOARD_UPPER_P11DIR485_ID, - .data_register_count = 20, .config_register_count = 23, .definition = NEURONSPI_BOARD_E14ROP11DIR485_HW_COMBINATION}, // E-14Ro_P-11DiR485 (xS40) - {.index = 6, .lower_board_id = NEURONSPI_BOARD_LOWER_E16DI_ID, .upper_board_id = NEURONSPI_BOARD_UPPER_P11DIR485_ID, - .data_register_count = 52, .config_register_count = 36, .definition = NEURONSPI_BOARD_E16DIP11DIR485_HW_COMBINATION}, // E-16Di_P-11DiR485 (xS30) - {.index = 7, .lower_board_id = NEURONSPI_BOARD_LOWER_E14RO_ID, .upper_board_id = NEURONSPI_BOARD_UPPER_U14RO_ID, - .data_register_count = 3, .config_register_count = 10, .definition = NEURONSPI_BOARD_E14ROU14RO_HW_COMBINATION}, // E-14Ro_U-14Ro (M403) - {.index = 8, .lower_board_id = NEURONSPI_BOARD_LOWER_E16DI_ID, .upper_board_id = NEURONSPI_BOARD_UPPER_U14RO_ID, - .data_register_count = 35, .config_register_count = 29, .definition = NEURONSPI_BOARD_E16DIU14RO_HW_COMBINATION}, // E-16Di_U-14Ro (M203) - {.index = 9, .lower_board_id = NEURONSPI_BOARD_LOWER_E14RO_ID, .upper_board_id = NEURONSPI_BOARD_UPPER_U14DI_ID, - .data_register_count = 31, .config_register_count = 27, .definition = NEURONSPI_BOARD_E14ROU14DI_HW_COMBINATION}, // E-14Ro_U-14Di (L503) - {.index = 10, .lower_board_id = NEURONSPI_BOARD_LOWER_E16DI_ID, .upper_board_id = NEURONSPI_BOARD_UPPER_U14DI_ID, - .data_register_count = 63, .config_register_count = 40, .definition = NEURONSPI_BOARD_E16DIU14DI_HW_COMBINATION}, // E-16Di_U-14Di (M303) - {.index = 11, .lower_board_id = NEURONSPI_BOARD_LOWER_E4AI4AO_ID, .upper_board_id = NEURONSPI_BOARD_UPPER_NONE_ID, - .data_register_count = 1, .config_register_count = 0, .definition = NEURONSPI_BOARD_E4AI4AO_HW_COMBINATION}, // E-4Ai4Ao - {.index = 12, .lower_board_id = NEURONSPI_BOARD_LOWER_E4AI4AO_ID, .upper_board_id = NEURONSPI_BOARD_UPPER_P6DI5RO_ID, - .data_register_count = 27, .config_register_count = 25, .definition = NEURONSPI_BOARD_E4AI4AOP6DI5RO_HW_COMBINATION}, // E-4Ai4Ao_P-6Di5Ro (xS50) - {.index = 13, .lower_board_id = NEURONSPI_BOARD_LOWER_B485_ID, .upper_board_id = NEURONSPI_BOARD_UPPER_NONE_ID, - .data_register_count = 1, .config_register_count = 0, .definition = NEURONSPI_BOARD_B485_HW_COMBINATION}, // B-485 - {.index = 14, .lower_board_id = NEURONSPI_BOARD_LOWER_E4LIGHT_ID, .upper_board_id = NEURONSPI_BOARD_UPPER_NONE_ID, - .data_register_count = 21, .config_register_count = 8, .definition = NEURONSPI_BOARD_E4LIGHT_HW_COMBINATION}, // E-4Light (M603) - {.index = 15, .lower_board_id = NEURONSPI_BOARD_LOWER_E4AI4AO_ID, .upper_board_id = NEURONSPI_BOARD_UPPER_U6DI5RO_ID, - .data_register_count = 28, .config_register_count = 24, .definition = NEURONSPI_BOARD_E4AI4AOU6DI5RO_HW_COMBINATION} // E-4Ai4Ao_U-6Di5Ro (M503) -}; - -// Module table -struct neuronspi_model_definition NEURONSPI_MODELTABLE[NEURONSPI_MODELTABLE_LEN] = { - {.eeprom_length = 4, .eeprom_name = "S103", .name_length = 4, .model_name = "S103", - .combination_count = 1, .combinations = NEURONSPI_MODEL_S103_HW_DEFINITION_BOARD}, - {.eeprom_length = 4, .eeprom_name = "S103", .name_length = 6, .model_name = "S103-G", - .combination_count = 1, .combinations = NEURONSPI_MODEL_S103G_HW_DEFINITION_BOARD}, - {.eeprom_length = 6, .eeprom_name = "S103IQ", .name_length = 7, .model_name = "S103-IQ", - .combination_count = 1, .combinations = NEURONSPI_MODEL_S103IQ_HW_DEFINITION_BOARD}, - {.eeprom_length = 6, .eeprom_name = "S103EO", .name_length = 7, .model_name = "S103-EO", - .combination_count = 1, .combinations = NEURONSPI_MODEL_S103EO_HW_DEFINITION_BOARD}, - {.eeprom_length = 4, .eeprom_name = "M103", .name_length = 4, .model_name = "M103", - .combination_count = 2, .combinations = NEURONSPI_MODEL_M103_HW_DEFINITION_BOARD}, - {.eeprom_length = 4, .eeprom_name = "M203", .name_length = 4, .model_name = "M203", - .combination_count = 2, .combinations = NEURONSPI_MODEL_M203_HW_DEFINITION_BOARD}, - {.eeprom_length = 4, .eeprom_name = "M303", .name_length = 4, .model_name = "M303", - .combination_count = 2, .combinations = NEURONSPI_MODEL_M303_HW_DEFINITION_BOARD}, - {.eeprom_length = 4, .eeprom_name = "M403", .name_length = 4, .model_name = "M403", - .combination_count = 2, .combinations = NEURONSPI_MODEL_M403_HW_DEFINITION_BOARD}, - {.eeprom_length = 4, .eeprom_name = "M503", .name_length = 4, .model_name = "M503", - .combination_count = 2, .combinations = NEURONSPI_MODEL_M503_HW_DEFINITION_BOARD}, - {.eeprom_length = 4, .eeprom_name = "M603", .name_length = 4, .model_name = "M603", - .combination_count = 2, .combinations = NEURONSPI_MODEL_M603_HW_DEFINITION_BOARD}, - {.eeprom_length = 4, .eeprom_name = "L203", .name_length = 4, .model_name = "L203", - .combination_count = 3, .combinations = NEURONSPI_MODEL_L203_HW_DEFINITION_BOARD}, - {.eeprom_length = 4, .eeprom_name = "L303", .name_length = 4, .model_name = "L303", - .combination_count = 3, .combinations = NEURONSPI_MODEL_L303_HW_DEFINITION_BOARD}, - {.eeprom_length = 4, .eeprom_name = "L403", .name_length = 4, .model_name = "L403", - .combination_count = 3, .combinations = NEURONSPI_MODEL_L403_HW_DEFINITION_BOARD}, - {.eeprom_length = 4, .eeprom_name = "L503", .name_length = 4, .model_name = "L503", - .combination_count = 3, .combinations = NEURONSPI_MODEL_L503_HW_DEFINITION_BOARD}, - {.eeprom_length = 4, .eeprom_name = "L513", .name_length = 4, .model_name = "L513", - .combination_count = 3, .combinations = NEURONSPI_MODEL_L513_HW_DEFINITION_BOARD} -}; - -/************************ - * Non-static Functions * - ************************/ - -s32 neuronspi_regmap_invalidate(void *data) -{ - int i; - int freq_cnt = 0; - while (!kthread_should_stop()) { - usleep_range(15000,25000); - if (freq_cnt == 450001) freq_cnt = 0; - for (i = 0; i < NEURONSPI_MAX_DEVS; i++) { - if (neuronspi_s_dev[i] != NULL) { - struct neuronspi_driver_data *d_data = spi_get_drvdata(neuronspi_s_dev[i]); - if (d_data->combination_id == 0xFF) { - continue; - } - neuronspi_regmap_invalidate_device(d_data->reg_map, NEURONSPI_BOARDTABLE[d_data->combination_id].definition, freq_cnt); - } - } - freq_cnt++; - } - return 0; -} - -void neuronspi_regmap_invalidate_device(struct regmap *reg_map, struct neuronspi_board_combination *device_def, u32 period_counter) -{ - int block_start, block_len, block_counter, current_period, period_len; - int i; - block_start = -1; - block_len = -1; - block_counter = 0; - period_len = 1; - - for (i = 0; i < device_def->block_count; i++) { - if (block_start == -1) { - block_start = device_def->blocks[i]; - block_counter = 0; - } else if (block_len == -1) { - block_len = device_def->blocks[i]; - } else if ((block_counter != block_len)) { - current_period = device_def->blocks[i] & 0x00FF0000; - if ((block_counter + 1 != block_len) && ((device_def->blocks[i + 1] & 0x00FF0000) == current_period)) { - period_len++; - } else { - switch (current_period) { - case NEURONSPI_REGFLAG_ACC_AFAP: { - regcache_drop_region(reg_map, block_start + block_counter - period_len + 1, block_start + block_counter); - break; - } - case NEURONSPI_REGFLAG_ACC_10HZ: { - if ((period_counter) % 5) { - regcache_drop_region(reg_map, block_start + block_counter - period_len + 1, block_start + block_counter); - } - break; - } - case NEURONSPI_REGFLAG_ACC_1HZ: { - if ((period_counter % 50) == 0) { - regcache_drop_region(reg_map, block_start + block_counter - period_len + 1, block_start + block_counter); - } - break; - } - case NEURONSPI_REGFLAG_ACC_6SEC: { - if ((period_counter % 300) == 0) { - regcache_drop_region(reg_map, block_start + block_counter - period_len + 1, block_start + block_counter); - } - break; - } - case NEURONSPI_REGFLAG_ACC_1MIN: { - if ((period_counter % 3000) == 0) { - regcache_drop_region(reg_map, block_start + block_counter - period_len + 1, block_start + block_counter); - } - break; - } - case NEURONSPI_REGFLAG_ACC_15MIN: { - if ((period_counter % 45000) == 0) { - regcache_drop_region(reg_map, block_start + block_counter - period_len + 1, block_start + block_counter); - } - break; - } - default: - break; - } - period_len = 1; - } - block_counter++; - } - if (block_counter == block_len) { - block_counter = 0; - block_start = -1; - block_len = -1; - } - } -} - -int neuronspi_regmap_hw_reg_read(void *context, unsigned int reg, unsigned int *val) -{ - struct spi_device *spi = context; - struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi); - u8 *inp_buf; - u8 *outp_buf; - int write_length; - printk(KERN_INFO "NEURONSPI: RM_REG_READ\n"); - write_length = neuronspi_spi_compose_single_register_read(reg, &inp_buf, &outp_buf); - neuronspi_spi_send_message(spi, inp_buf, outp_buf, write_length, n_spi->ideal_frequency, 25, 1); - memcpy(val, &outp_buf[NEURONSPI_HEADER_LENGTH], sizeof(u16)); - kfree(inp_buf); - kfree(outp_buf); - return 0; -} - -int neuronspi_regmap_hw_write(void *context, const void *data, size_t count) -{ - BUG_ON(count < 1); - return neuronspi_regmap_hw_gather_write(context, data, 1, data + 1, count - 1); -} - -int neuronspi_regmap_hw_reg_write(void *context, unsigned int reg, unsigned int val) -{ - struct spi_device *spi = context; - struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi); - u8 *inp_buf; - u8 *outp_buf; - int write_length; - write_length = neuronspi_spi_compose_single_register_write(reg, &inp_buf, &outp_buf, (val >> 8)); - printk(KERN_INFO "HW_REG_WRITE l:%d, r:%d, v:%d\n", write_length, reg, (val >> 8)); - neuronspi_spi_send_message(spi, inp_buf, outp_buf, write_length, n_spi->ideal_frequency, 25, 1); - memcpy(&val, &outp_buf[NEURONSPI_HEADER_LENGTH], sizeof(u16)); - kfree(inp_buf); - kfree(outp_buf); - return 0; -} - -int neuronspi_regmap_hw_gather_write(void *context, const void *reg, size_t reg_size, const void *val, size_t val_size) -{ - u16 *mb_reg_buf = (u16*)reg; - u32 *mb_val_buf = (u32*)val; - struct spi_device *spi = context; - struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi); - u8 *inp_buf; - u8 *outp_buf; - int i, write_length; - int block_counter = 0; - printk(KERN_INFO "HW_REG_GATHER_WRITE:%d, %d, %x, %x\n", val_size, reg_size, mb_reg_buf[0], mb_val_buf[0]); - if (reg_size == 1) { - neuronspi_regmap_hw_reg_write(context,mb_reg_buf[0],mb_val_buf[0]); - } else { - for (i = 0; i < reg_size; i++) { - // Swap endianness - cpu_to_be16s((u16*)&(mb_val_buf[i])); - // Check for continuity and read the largest possible continuous block - if (block_counter == (reg_size - 1) || ((mb_reg_buf[i] + 1) != mb_reg_buf[i + 1])) { - write_length = neuronspi_spi_compose_multiple_register_write(block_counter, mb_reg_buf[i - block_counter], &inp_buf, &outp_buf, - (u8*)(&mb_val_buf[i - block_counter])); - neuronspi_spi_send_message(spi, inp_buf, outp_buf, write_length, n_spi->ideal_frequency, 125, 1); - block_counter = 0; - kfree(inp_buf); - kfree(outp_buf); - } else { - block_counter++; - } - } - } - return 0; -} - -int neuronspi_create_reg_starts(struct neuronspi_board_regstart_table *out_table, struct neuronspi_board_combination *board) { - if (board->features.di_count > 0) { - out_table->di_val_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_DI_READ); - out_table->di_counter_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_DI_COUNTER_UPPER); - out_table->di_deboun_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_DI_DEBOUNCE); - out_table->di_direct_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_DS_ENABLE); - out_table->di_polar_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_DS_POLARITY); - out_table->di_toggle_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_DS_TOGGLE); - } - if (board->features.do_count > 0) { - out_table->do_val_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_DO_RW); - out_table->do_pwm_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_PWM_DUTY); - out_table->do_pwm_c_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_PWM_CYCLE); - out_table->do_pwm_ps_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_PWM_PRESCALE); - } - if (board->features.led_count > 0) { - out_table->led_val_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_LED_RW); - } - if (board->features.light_count > 0) { - // TODO: Fill in light bus registers - } - if (board->features.ro_count > 0) { - out_table->ro_val_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_DO_RW); - } - if (board->features.sec_ai_count > 0) { - out_table->sec_ai_val_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_AI_VER2_READ_LOWER); - out_table->sec_ai_mode_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_AI_VER2_MODE); - } - if (board->features.sec_ao_count > 0) { - out_table->sec_ao_val_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_AO_VER2_RW); - } - if (board->features.stm_ao_count > 0) { - out_table->stm_ao_val_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_AO_BRAIN); - out_table->stm_ao_mode_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_AO_BRAIN_MODE); - out_table->stm_ao_vol_err = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_AO_BRAIN_V_ERR); - out_table->stm_ao_vol_off = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_AO_BRAIN_V_OFF); - out_table->stm_ao_curr_err = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_AO_BRAIN_I_ERR); - out_table->stm_ao_curr_off = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_AO_BRAIN_I_OFF); - } - if (board->features.stm_ai_count > 0) { - out_table->stm_ai_val_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_AI_BRAIN); - out_table->stm_ai_mode_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_AI_BRAIN_MODE); - out_table->stm_ai_vol_err = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_AI_BRAIN_V_ERR); - out_table->stm_ai_vol_off = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_AI_BRAIN_V_OFF); - out_table->stm_ai_curr_err = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_AI_BRAIN_I_ERR); - out_table->stm_ai_curr_off = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_AI_BRAIN_I_OFF); - out_table->stm_aio_val_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_AIO_BRAIN); - out_table->stm_aio_vol_err = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_AIO_BRAIN_ERR); - out_table->stm_aio_vol_off = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_AIO_BRAIN_OFF); - out_table->vref_inp = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_V_REF_INP); - } - out_table->uart_queue_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_TX_QUEUE_LEN); - out_table->uart_conf_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_RS485_CONFIG); - out_table->vref_int = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_V_REF_INT); - out_table->wd_timeout_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_MWD_TO); - out_table->sys_serial_num = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_SERIAL_NR_LOWER); - out_table->sys_sw_ver = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_SW_VER); - out_table->sys_hw_ver = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_HW_VER); - out_table->sys_hw_flash_ver = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_FLASH_HW_VER); - return 0; -} - -s32 neuronspi_find_reg_start(struct neuronspi_board_combination *board, u16 regfun) { - int i; - int block_start = -1; - int block_len = -1; - int block_counter = 0; - for (i = 0; i < board->block_count; i++) { - if (block_start == -1) { - block_start = board->blocks[i]; - } else if (block_len == -1) { - block_len = board->blocks[i]; - } else if ((board->blocks[i] & 0xFFFF) == regfun) { - //printk(KERN_INFO "NEURONSPI: Reg Start Fun: %x RegS: %d", regfun, block_start + block_counter); - return block_start + block_counter; - } else { - block_counter++; - } - if (block_counter == block_len) { - block_counter = 0; - block_start = -1; - block_len = -1; - } - } - return -1; -} - -int neuronspi_regmap_hw_read(void *context, const void *reg_buf, size_t reg_size, void *val_buf, size_t val_size) { - const u16 *mb_reg_buf = reg_buf; - u16 *mb_val_buf = val_buf; - struct spi_device *spi; - struct neuronspi_driver_data *n_spi; - u8 *inp_buf; - u8 *outp_buf; - int i, write_length; - int block_counter = 0; - if (context == NULL) { - return 0; - } - spi = context; - n_spi = spi_get_drvdata(spi); - if (n_spi == NULL) { - return 0; - } - for (i = 0; i < (reg_size / 2); i++) { - // Check for continuity and read the largest possible continuous block - if (block_counter == ((reg_size / 2) - 1) || ((mb_reg_buf[i] + 1) != mb_reg_buf[i + 1])) { - write_length = neuronspi_spi_compose_multiple_register_read(block_counter + 1, mb_reg_buf[i - block_counter], &inp_buf, &outp_buf); - neuronspi_spi_send_message(spi, inp_buf, outp_buf, write_length, n_spi->ideal_frequency, 125, 1); - memcpy(&mb_val_buf[i - block_counter], &outp_buf[NEURONSPI_HEADER_LENGTH], (block_counter + 1) * 2); - kfree(inp_buf); - kfree(outp_buf); - block_counter = 0; - } else { - block_counter++; - } - } - printk(KERN_INFO "NEURONSPI: RM_READ %d %x %d %x\n", reg_size, mb_reg_buf[0], val_size, mb_val_buf[0]); - return 0; -} - -s32 neuronspi_find_model_id(u32 probe_count) -{ - struct neuronspi_driver_data *n_spi; - int i,j, ret = -1; - u8 *inv = kzalloc(sizeof(*inv) * NEURONSPI_MODELTABLE_LEN, GFP_KERNEL); - for (i = 0; i < probe_count; i++) { - if (neuronspi_s_dev[i]) { - n_spi = spi_get_drvdata(neuronspi_s_dev[i]); - for (j = 0; j < NEURONSPI_MODELTABLE_LEN; j++) { - if (i + 1 > NEURONSPI_MODELTABLE[j].combination_count) { - inv[j] = 1; - } else if (NEURONSPI_MODELTABLE[j].combinations[i].combination_board_id != n_spi->combination_id) { - inv[j] = 1; - } - } - } else { - for (j = 0; j < NEURONSPI_MODELTABLE_LEN; j++) { - if (i + 1 < NEURONSPI_MODELTABLE[j].combination_count) { - inv[j] = 1; - } - } - } - } - for (i = 0; i < NEURONSPI_MODELTABLE_LEN; i++) { - if (inv[i] != 1) { - ret = i; - break; - } - } - kfree(inv); - return ret; -} - - diff --git a/modules/neuron_spi/src/unipi_platform.h b/modules/neuron_spi/src/unipi_platform.h deleted file mode 100644 index 8178ebb..0000000 --- a/modules/neuron_spi/src/unipi_platform.h +++ /dev/null @@ -1,358 +0,0 @@ -/* - * UniPi Neuron tty serial driver - Copyright (C) 2018 UniPi Technologies - * Author: Tomas Knot - * - * Based on the SC16IS7xx driver by Jon Ringle , - * which was in turn based on max310x.c, by Alexander Shiyan - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - */ - -#ifndef MODULES_NEURON_SPI_SRC_UNIPI_PLATFORM_H_ -#define MODULES_NEURON_SPI_SRC_UNIPI_PLATFORM_H_ - -/************ - * Includes * - ************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "unipi_common.h" - -/******************* - * Data Structures * - *******************/ - -struct neuronspi_board_entry { - u16 index; - u16 lower_board_id; - u16 upper_board_id; - u16 data_register_count; - u16 config_register_count; - struct neuronspi_board_combination *definition; -}; - -struct neuronspi_register_block -{ - u32 starting_register; - u32 register_count; - u32 *register_flags; -}; - -struct neuronspi_board_features -{ - u32 do_count; - u32 ro_count; - u32 ds_count; - u32 di_count; - u32 led_count; - u32 stm_ai_count; - u32 stm_ao_count; - u32 sec_ai_count; - u32 sec_ao_count; - u32 uart_master_count; - u32 uart_slave_count; - u32 pwm_channel_count; - u32 wd_count; - u32 extension_sys_count; - u32 light_count; - u32 owire_count; -}; - -struct neuronspi_board_regstart_table -{ - u32 do_val_reg; - u32 do_val_coil; - u32 do_pwm_reg; - u32 do_pwm_ps_reg; - u32 do_pwm_c_reg; - u32 di_val_reg; - u32 di_counter_reg; - u32 di_direct_reg; - u32 di_deboun_reg; - u32 di_polar_reg; - u32 di_toggle_reg; - u32 uart_queue_reg; - u32 uart_conf_reg; - u32 uart_address_reg; - u32 led_val_coil; - u32 led_val_reg; - u32 wd_val_reg; - u32 wd_timeout_reg; - u32 wd_nv_sav_coil; - u32 wd_reset_coil; - u32 reg_start_reg; - u32 ro_val_reg; - u32 ro_val_coil; - u32 vref_inp; - u32 vref_int; - u32 stm_ao_val_reg; - u32 stm_ao_mode_reg; - u32 stm_ao_vol_err; - u32 stm_ao_vol_off; - u32 stm_ao_curr_err; - u32 stm_ao_curr_off; - u32 stm_ai_val_reg; - u32 stm_ai_mode_reg; - u32 stm_ai_curr_err; - u32 stm_ai_curr_off; - u32 stm_ai_vol_err; - u32 stm_ai_vol_off; - u32 stm_aio_val_reg; - u32 stm_aio_vol_err; - u32 stm_aio_vol_off; - u32 sec_ao_val_reg; - u32 sec_ao_mode_reg; - u32 sec_ai_val_reg; - u32 sec_ai_mode_reg; - u32 sys_serial_num; - u32 sys_hw_ver; - u32 sys_hw_flash_ver; - u32 sys_sw_ver; -}; - -struct neuronspi_board_combination -{ - u32 combination_board_id; - u16 lower_board_id; - u16 upper_board_id; - u32 block_count; - size_t name_length; - const char* combination_name; - struct neuronspi_board_features features; - u32 *blocks; -}; - -struct neuronspi_model_definition -{ - size_t eeprom_length; - const char* eeprom_name; - size_t name_length; - const char* model_name; - u32 combination_count; - struct neuronspi_board_combination *combinations; -}; - -/*************** - * Definitions * - ***************/ - -// Lower Boards -#define NEURONSPI_BOARD_LOWER_B1000_ID 0 -#define NEURONSPI_BOARD_LOWER_E8DI8RO_ID 1 -#define NEURONSPI_BOARD_LOWER_E14RO_ID 2 -#define NEURONSPI_BOARD_LOWER_E16DI_ID 3 -#define NEURONSPI_BOARD_LOWER_E4AI4AO_ID 11 -#define NEURONSPI_BOARD_LOWER_B485_ID 13 -#define NEURONSPI_BOARD_LOWER_E4LIGHT_ID 14 - -// Upper Boards -#define NEURONSPI_BOARD_UPPER_NONE_ID 0 -#define NEURONSPI_BOARD_UPPER_P11DIR485_ID 1 -#define NEURONSPI_BOARD_UPPER_U14RO_ID 2 -#define NEURONSPI_BOARD_UPPER_U14DI_ID 3 -#define NEURONSPI_BOARD_UPPER_P6DI5RO_ID 4 -#define NEURONSPI_BOARD_UPPER_U6DI5RO_ID 5 - -// Register function codes -// Digital Input Functions -#define NEURONSPI_FUNGROUP_DI 0 -#define NEURONSPI_REGFUN_DI_READ 0 | NEURONSPI_FUNGROUP_DI << 8 -#define NEURONSPI_REGFUN_DI_COUNTER_LOWER 1 | NEURONSPI_FUNGROUP_DI << 8 -#define NEURONSPI_REGFUN_DI_COUNTER_UPPER 2 | NEURONSPI_FUNGROUP_DI << 8 -#define NEURONSPI_REGFUN_DI_DEBOUNCE 3 | NEURONSPI_FUNGROUP_DI << 8 -#define NEURONSPI_REGFUN_DS_ENABLE 4 | NEURONSPI_FUNGROUP_DI << 8 -#define NEURONSPI_REGFUN_DS_POLARITY 5 | NEURONSPI_FUNGROUP_DI << 8 -#define NEURONSPI_REGFUN_DS_TOGGLE 6 | NEURONSPI_FUNGROUP_DI << 8 - -// Digital Output Functions -#define NEURONSPI_FUNGROUP_DO 1 -#define NEURONSPI_REGFUN_DO_RW 0 | NEURONSPI_FUNGROUP_DO << 8 - -// B1000 Analog Output Functions -#define NEURONSPI_FUNGROUP_AO_BRAIN 2 -#define NEURONSPI_REGFUN_AO_BRAIN 0 | NEURONSPI_FUNGROUP_AO_BRAIN << 8 -#define NEURONSPI_REGFUN_AO_BRAIN_MODE 1 | NEURONSPI_FUNGROUP_AO_BRAIN << 8 -#define NEURONSPI_REGFUN_AO_BRAIN_V_ERR 2 | NEURONSPI_FUNGROUP_AO_BRAIN << 8 -#define NEURONSPI_REGFUN_AO_BRAIN_V_OFF 3 | NEURONSPI_FUNGROUP_AO_BRAIN << 8 -#define NEURONSPI_REGFUN_AO_BRAIN_I_ERR 4 | NEURONSPI_FUNGROUP_AO_BRAIN << 8 -#define NEURONSPI_REGFUN_AO_BRAIN_I_OFF 5 | NEURONSPI_FUNGROUP_AO_BRAIN << 8 - -// B1000 Analog Input Functions -#define NEURONSPI_FUNGROUP_AI_BRAIN 3 -#define NEURONSPI_REGFUN_AI_BRAIN 0 | NEURONSPI_FUNGROUP_AI_BRAIN << 8 -#define NEURONSPI_REGFUN_AIO_BRAIN 1 | NEURONSPI_FUNGROUP_AI_BRAIN << 8 -#define NEURONSPI_REGFUN_AI_BRAIN_MODE 2 | NEURONSPI_FUNGROUP_AI_BRAIN << 8 -#define NEURONSPI_REGFUN_AI_BRAIN_V_ERR 3 | NEURONSPI_FUNGROUP_AI_BRAIN << 8 -#define NEURONSPI_REGFUN_AI_BRAIN_V_OFF 4 | NEURONSPI_FUNGROUP_AI_BRAIN << 8 -#define NEURONSPI_REGFUN_AI_BRAIN_I_ERR 5 | NEURONSPI_FUNGROUP_AI_BRAIN << 8 -#define NEURONSPI_REGFUN_AI_BRAIN_I_OFF 6 | NEURONSPI_FUNGROUP_AI_BRAIN << 8 -#define NEURONSPI_REGFUN_AIO_BRAIN_ERR 7 | NEURONSPI_FUNGROUP_AI_BRAIN << 8 -#define NEURONSPI_REGFUN_AIO_BRAIN_OFF 8 | NEURONSPI_FUNGROUP_AI_BRAIN << 8 - -// System Functions -#define NEURONSPI_FUNGROUP_SYSTEM 4 -#define NEURONSPI_REGFUN_V_REF_INT 0 | NEURONSPI_FUNGROUP_SYSTEM << 8 -#define NEURONSPI_REGFUN_V_REF_INP 1 | NEURONSPI_FUNGROUP_SYSTEM << 8 -#define NEURONSPI_REGFUN_LED_RW 2 | NEURONSPI_FUNGROUP_SYSTEM << 8 -#define NEURONSPI_REGFUN_SW_VER 3 | NEURONSPI_FUNGROUP_SYSTEM << 8 -#define NEURONSPI_REGFUN_DIDO_COUNT 4 | NEURONSPI_FUNGROUP_SYSTEM << 8 -#define NEURONSPI_REGFUN_UAIO_COUNT 5 | NEURONSPI_FUNGROUP_SYSTEM << 8 -#define NEURONSPI_REGFUN_HW_VER 6 | NEURONSPI_FUNGROUP_SYSTEM << 8 -#define NEURONSPI_REGFUN_FLASH_HW_VER 7 | NEURONSPI_FUNGROUP_SYSTEM << 8 -#define NEURONSPI_REGFUN_SERIAL_NR_LOWER 8 | NEURONSPI_FUNGROUP_SYSTEM << 8 -#define NEURONSPI_REGFUN_SERIAL_NR_UPPER 9 | NEURONSPI_FUNGROUP_SYSTEM << 8 -#define NEURONSPI_REGFUN_INTERRUPTS 10 | NEURONSPI_FUNGROUP_SYSTEM << 8 -#define NEURONSPI_REGFUN_NONE_TEST 11 | NEURONSPI_FUNGROUP_SYSTEM << 8 - -// Watchdog Functions -#define NEURONSPI_FUNGROUP_MWD 5 -#define NEURONSPI_REGFUN_MWD_TO 0 | NEURONSPI_FUNGROUP_MWD << 8 -#define NEURONSPI_REGFUN_MWD_STATUS 1 | NEURONSPI_FUNGROUP_MWD << 8 - -// PWM Functions -#define NEURONSPI_FUNGROUP_PWM 6 -#define NEURONSPI_REGFUN_PWM_DUTY 0 | NEURONSPI_FUNGROUP_PWM << 8 -#define NEURONSPI_REGFUN_PWM_PRESCALE 1 | NEURONSPI_FUNGROUP_PWM << 8 -#define NEURONSPI_REGFUN_PWM_CYCLE 2 | NEURONSPI_FUNGROUP_PWM << 8 - -// UART Functions -#define NEURONSPI_FUNGROUP_RS485 7 -#define NEURONSPI_REGFUN_TX_QUEUE_LEN 0 | NEURONSPI_FUNGROUP_RS485 << 8 -#define NEURONSPI_REGFUN_RS485_CONFIG 1 | NEURONSPI_FUNGROUP_RS485 << 8 -#define NEURONSPI_REGFUN_RS485_ADDRESS 2 | NEURONSPI_FUNGROUP_RS485 << 8 - -// Secondary Analog Output Functions -#define NEURONSPI_FUNGROUP_AO_VER2 8 -#define NEURONSPI_REGFUN_AO_VER2_RW 0 | NEURONSPI_FUNGROUP_AO_VER2 << 8 - -// Secondary Analog Input Functions -#define NEURONSPI_FUNGROUP_AI_VER2 9 -#define NEURONSPI_REGFUN_AI_VER2_READ_LOWER 0 | NEURONSPI_FUNGROUP_AI_VER2 << 8 -#define NEURONSPI_REGFUN_AI_VER2_READ_UPPER 0 | NEURONSPI_FUNGROUP_AI_VER2 << 8 -#define NEURONSPI_REGFUN_AI_VER2_MODE 1 | NEURONSPI_FUNGROUP_AI_VER2 << 8 - -// Register access flags -#define NEURONSPI_REGFLAG_ACC_NEVER 0 -#define NEURONSPI_REGFLAG_ACC_AFAP 0x1 << 16 -#define NEURONSPI_REGFLAG_ACC_10HZ 0x2 << 16 -#define NEURONSPI_REGFLAG_ACC_1HZ 0x3 << 16 -#define NEURONSPI_REGFLAG_ACC_6SEC 0x4 << 16 -#define NEURONSPI_REGFLAG_ACC_1MIN 0x5 << 16 -#define NEURONSPI_REGFLAG_ACC_15MIN 0x6 << 16 -#define NEURONSPI_REGFLAG_ACC_ONCE 0x7 << 16 - -// Register system flags -#define NEURONSPI_REGFLAG_SYS_READ_ONLY 0x10 << 24 - -// IIO Modes -#define NEURONSPI_IIO_AI_STM_MODE_VOLTAGE 0x0 -#define NEURONSPI_IIO_AI_STM_MODE_CURRENT 0x1 -#define NEURONSPI_IIO_AI_STM_MODE_RESISTANCE 0x3 - -/********************* - * Data Declarations * - *********************/ - -extern struct platform_device *neuron_plc_dev; - -// Board Definitions -extern struct neuronspi_board_combination NEURONSPI_BOARD_B1000_HW_COMBINATION[]; // B_1000 (S103) -extern struct neuronspi_board_combination NEURONSPI_BOARD_E8DI8RO_HW_COMBINATION[]; // E-8Di8Ro (M103) -extern struct neuronspi_board_combination NEURONSPI_BOARD_E14RO_HW_COMBINATION[]; // E-14Ro -extern struct neuronspi_board_combination NEURONSPI_BOARD_E16DI_HW_COMBINATION[]; // E-16Di -extern struct neuronspi_board_combination NEURONSPI_BOARD_E8DI8ROP11DIR485_HW_COMBINATION[]; // E-8Di8Ro_P-11DiR485 (xS10) -extern struct neuronspi_board_combination NEURONSPI_BOARD_E14ROP11DIR485_HW_COMBINATION[]; // E-14Ro_P-11DiR485 (xS40) -extern struct neuronspi_board_combination NEURONSPI_BOARD_E16DIP11DIR485_HW_COMBINATION[]; // E-16Di_P-11DiR485 (xS30) -extern struct neuronspi_board_combination NEURONSPI_BOARD_E14ROU14RO_HW_COMBINATION[]; // E-14Ro_U-14Ro (M403) -extern struct neuronspi_board_combination NEURONSPI_BOARD_E16DIU14RO_HW_COMBINATION[]; // E-16Di_U-14Ro (M203) -extern struct neuronspi_board_combination NEURONSPI_BOARD_E14ROU14DI_HW_COMBINATION[]; // E-14Ro_U-14Di (L503) -extern struct neuronspi_board_combination NEURONSPI_BOARD_E16DIU14DI_HW_COMBINATION[]; // E-16Di_U-14Di (M303) -extern struct neuronspi_board_combination NEURONSPI_BOARD_E4AI4AO_HW_COMBINATION[]; // E-4Ai4Ao -extern struct neuronspi_board_combination NEURONSPI_BOARD_E4AI4AOP6DI5RO_HW_COMBINATION[]; // E-4Ai4Ao_P-6Di5Ro (xS50) -extern struct neuronspi_board_combination NEURONSPI_BOARD_B485_HW_COMBINATION[]; // B-485 -extern struct neuronspi_board_combination NEURONSPI_BOARD_E4LIGHT_HW_COMBINATION[]; // E-4Light (M613) -extern struct neuronspi_board_combination NEURONSPI_BOARD_E4AI4AOU6DI5RO_HW_COMBINATION[]; // E-4Ai4Ao_U-6Di5Ro (L503) - -// Model Definitions -#define NEURONSPI_MODEL_S103_HW_DEFINITION_BOARD_SIZE 1 -extern struct neuronspi_board_combination NEURONSPI_MODEL_S103_HW_DEFINITION_BOARD[NEURONSPI_MODEL_S103_HW_DEFINITION_BOARD_SIZE]; -#define NEURONSPI_MODEL_S103G_HW_DEFINITION_BOARD_SIZE 1 -extern struct neuronspi_board_combination NEURONSPI_MODEL_S103G_HW_DEFINITION_BOARD[NEURONSPI_MODEL_S103G_HW_DEFINITION_BOARD_SIZE]; -#define NEURONSPI_MODEL_S103IQ_HW_DEFINITION_BOARD_SIZE 1 -extern struct neuronspi_board_combination NEURONSPI_MODEL_S103IQ_HW_DEFINITION_BOARD[NEURONSPI_MODEL_S103IQ_HW_DEFINITION_BOARD_SIZE]; -#define NEURONSPI_MODEL_S103EO_HW_DEFINITION_BOARD_SIZE 1 -extern struct neuronspi_board_combination NEURONSPI_MODEL_S103EO_HW_DEFINITION_BOARD[NEURONSPI_MODEL_S103EO_HW_DEFINITION_BOARD_SIZE]; -#define NEURONSPI_MODEL_M103_HW_DEFINITION_BOARD_SIZE 2 -extern struct neuronspi_board_combination NEURONSPI_MODEL_M103_HW_DEFINITION_BOARD[NEURONSPI_MODEL_M103_HW_DEFINITION_BOARD_SIZE]; -#define NEURONSPI_MODEL_M203_HW_DEFINITION_BOARD_SIZE 2 -extern struct neuronspi_board_combination NEURONSPI_MODEL_M203_HW_DEFINITION_BOARD[NEURONSPI_MODEL_M203_HW_DEFINITION_BOARD_SIZE]; -#define NEURONSPI_MODEL_M303_HW_DEFINITION_BOARD_SIZE 2 -extern struct neuronspi_board_combination NEURONSPI_MODEL_M303_HW_DEFINITION_BOARD[NEURONSPI_MODEL_M303_HW_DEFINITION_BOARD_SIZE]; -#define NEURONSPI_MODEL_M403_HW_DEFINITION_BOARD_SIZE 2 -extern struct neuronspi_board_combination NEURONSPI_MODEL_M403_HW_DEFINITION_BOARD[NEURONSPI_MODEL_M403_HW_DEFINITION_BOARD_SIZE]; -#define NEURONSPI_MODEL_M503_HW_DEFINITION_BOARD_SIZE 2 -extern struct neuronspi_board_combination NEURONSPI_MODEL_M503_HW_DEFINITION_BOARD[NEURONSPI_MODEL_M503_HW_DEFINITION_BOARD_SIZE]; -#define NEURONSPI_MODEL_M603_HW_DEFINITION_BOARD_SIZE 2 -extern struct neuronspi_board_combination NEURONSPI_MODEL_M603_HW_DEFINITION_BOARD[NEURONSPI_MODEL_M603_HW_DEFINITION_BOARD_SIZE]; -#define NEURONSPI_MODEL_L203_HW_DEFINITION_BOARD_SIZE 3 -extern struct neuronspi_board_combination NEURONSPI_MODEL_L203_HW_DEFINITION_BOARD[NEURONSPI_MODEL_L203_HW_DEFINITION_BOARD_SIZE]; -#define NEURONSPI_MODEL_L303_HW_DEFINITION_BOARD_SIZE 3 -extern struct neuronspi_board_combination NEURONSPI_MODEL_L303_HW_DEFINITION_BOARD[NEURONSPI_MODEL_L303_HW_DEFINITION_BOARD_SIZE]; -#define NEURONSPI_MODEL_L403_HW_DEFINITION_BOARD_SIZE 3 -extern struct neuronspi_board_combination NEURONSPI_MODEL_L403_HW_DEFINITION_BOARD[NEURONSPI_MODEL_L403_HW_DEFINITION_BOARD_SIZE]; -#define NEURONSPI_MODEL_L503_HW_DEFINITION_BOARD_SIZE 3 -extern struct neuronspi_board_combination NEURONSPI_MODEL_L503_HW_DEFINITION_BOARD[NEURONSPI_MODEL_L503_HW_DEFINITION_BOARD_SIZE]; -#define NEURONSPI_MODEL_L513_HW_DEFINITION_BOARD_SIZE 3 -extern struct neuronspi_board_combination NEURONSPI_MODEL_L513_HW_DEFINITION_BOARD[]; - -// Board table -#define NEURONSPI_BOARDTABLE_LEN 16 -extern struct neuronspi_board_entry NEURONSPI_BOARDTABLE[]; - -// Module table -#define NEURONSPI_MODELTABLE_LEN 15 -extern struct neuronspi_model_definition NEURONSPI_MODELTABLE[]; - -/************************* - * Function Declarations * - *************************/ - -int neuronspi_regmap_hw_gather_write(void *context, const void *reg, size_t reg_size, const void *val, size_t val_size); -int neuronspi_regmap_hw_read(void *context, const void *reg_buf, size_t reg_size, void *val_buf, size_t val_size); -int neuronspi_regmap_hw_reg_read(void *context, unsigned int reg, unsigned int *val); -int neuronspi_regmap_hw_reg_write(void *context, unsigned int reg, unsigned int val); -int neuronspi_regmap_hw_write(void *context, const void *data, size_t count); -void neuronspi_regmap_invalidate_device(struct regmap *reg_map, struct neuronspi_board_combination *device_def, u32 period_counter); -s32 neuronspi_regmap_invalidate(void *data); -int neuronspi_create_reg_starts(struct neuronspi_board_regstart_table *out_table, struct neuronspi_board_combination *board); -s32 neuronspi_find_reg_start(struct neuronspi_board_combination *board, u16 regfun); -s32 neuronspi_find_model_id(u32 probe_count); - -#endif /* MODULES_NEURON_SPI_SRC_UNIPI_PLATFORM_H_ */ diff --git a/modules/neuron_spi/src/unipi_spi.c b/modules/neuron_spi/src/unipi_spi.c deleted file mode 100644 index d58c5c4..0000000 --- a/modules/neuron_spi/src/unipi_spi.c +++ /dev/null @@ -1,1587 +0,0 @@ -/* - * UniPi Neuron tty serial driver - Copyright (C) 2017 UniPi Tech -nologies - * Author: Tomas Knot - * - * Based on the SC16IS7xx driver by Jon Ringle , - * which was in turn based on max310x.c, by Alexander Shiyan - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -/************ - * Includes * - ************/ - -#include "unipi_common.h" -#include "unipi_sysfs.h" -#include "unipi_uart.h" -#include "unipi_platform.h" -#include "unipi_gpio.h" -#include "unipi_iio.h" -#include "unipi_misc.h" -#include "unipi_spi.h" - -/******************** - * Data Definitions * - ********************/ - -MODULE_DEVICE_TABLE(of, neuronspi_id_match); - -struct spi_driver neuronspi_spi_driver = -{ - .driver = - { - .name = NEURON_DRIVER_NAME, - .of_match_table = of_match_ptr(neuronspi_id_match) - }, - .probe = neuronspi_spi_probe, - .remove = neuronspi_spi_remove, -}; - -struct file_operations file_ops = -{ - .open = neuronspi_open, - .read = neuronspi_read, - .write = neuronspi_write, - .release = neuronspi_release, - .owner = THIS_MODULE -}; - -struct neuronspi_char_driver neuronspi_cdrv = -{ - .dev = NULL -}; - -struct mutex neuronspi_master_mutex; -struct spinlock* neuronspi_spi_w_spinlock; -u8 neuronspi_spi_w_flag = 1; -u8 neuronspi_probe_count = 0; -int neuronspi_model_id = -1; -spinlock_t neuronspi_probe_spinlock; -struct spi_device* neuronspi_s_dev[NEURONSPI_MAX_DEVS]; -struct task_struct *neuronspi_invalidate_thread; - -/************************ - * Non-static Functions * - ************************/ - -int neuronspi_open (struct inode *inode_p, struct file *file_p) -{ - struct neuronspi_file_data *f_internal_data; - if (neuronspi_s_dev == NULL || file_p == NULL || inode_p == NULL) { - return -1; - } - neuronspi_cdrv.open_counter += 1; - f_internal_data = kzalloc(sizeof(*f_internal_data), GFP_KERNEL); - f_internal_data->recv_buf = kzalloc(NEURONSPI_BUFFER_MAX, GFP_KERNEL); - f_internal_data->send_buf = kzalloc(NEURONSPI_BUFFER_MAX, GFP_KERNEL); - f_internal_data->spi_device = neuronspi_s_dev; - mutex_init(&f_internal_data->lock); - file_p->private_data = f_internal_data; - return 0; -} - -int neuronspi_release (struct inode *inode_p, struct file *file_p) -{ - struct neuronspi_file_data *f_internal_data; - if (file_p == NULL) { - return -1; - } - 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); - file_p->private_data = NULL; - neuronspi_cdrv.open_counter -= 1; - return 0; -} - -ssize_t neuronspi_read (struct file *file_p, char *buffer, size_t len, loff_t *offset) -{ - - s32 result = 0; - u8 device_index = 0; - u32 frequency = NEURONSPI_COMMON_FREQ; - struct neuronspi_file_data* private_data; - struct spi_device* spi_driver_data; - struct neuronspi_driver_data* driver_data; - // Sanity checking - if (neuronspi_cdrv.open_counter == 0) { - neuronspi_cdrv.open_counter = 1; - } - if (buffer == NULL) return -7; // Invalid read buffer - if (len == 0) return result; // Empty read - if (len > 4095) return -EMSGSIZE; - if (file_p == NULL) { - printk(KERN_DEBUG "NEURONSPI: File Pointer is NULL\n"); - return -8; - } - if (file_p->private_data == NULL) { - printk(KERN_DEBUG "NEURONSPI: 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 - 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) return -3; // No device present - if (driver_data->slower_model) { - frequency = NEURONSPI_SLOWER_FREQ; - } - mutex_lock(&(private_data->lock)); - if (private_data->recv_buf == NULL) { - mutex_unlock(&(private_data->lock)); - return -10; - } -#if NEURONSPI_DETAILED_DEBUG > 0 - printk(KERN_INFO "NEURONSPI: 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; - } 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; - s32 delay = 25; - struct neuronspi_file_data* private_data; - struct spi_device* spi_driver_data; - struct neuronspi_driver_data* driver_data; - // Sanity checking - if (neuronspi_cdrv.open_counter == 0) { - neuronspi_cdrv.open_counter = 1; - } -#if NEURONSPI_DETAILED_DEBUG > 0 - printk(KERN_INFO "NEURONSPI: LENGTH:%d\n", len); -#endif - if (buffer == NULL) { - return 0; // Void write - } - if (len == 0) { - return result; // Empty write - } - if (len > 4095) return -EMSGSIZE; - if (file_p == NULL) { - return -12; - } - if (file_p->private_data == NULL) { - printk(KERN_DEBUG "NEURONSPI: No Private Data\n"); - return -1; // No private data - } - // Read packet header and initialise private data (dependent on each other) - device_index = buffer[0]; - 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) 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; - } -#else - } else if (device_index == (driver_data->reserved_device - 1)) { - return -5; // Device reserved - } - if (driver_data->slower_model) { - frequency = NEURONSPI_SLOWER_FREQ; - } -#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(neuronspi_spi_w_spinlock); - neuronspi_spi_w_flag = 1; - spin_unlock(neuronspi_spi_w_spinlock); - neuronspi_spi_send_message(spi_driver_data, &private_data->send_buf[NEURONSPI_HEADER_LENGTH], private_data->recv_buf, - transmit_len, frequency, delay, send_header); - mutex_unlock(&private_data->lock); - return len; -} - -s32 neuronspi_spi_uart_write(struct spi_device *spi, u8 *send_buf, u8 length, u8 uart_index) -{ - u8 *message_buf; - u8 *recv_buf; - s32 transmit_len, i; - 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 "NEURONSPI: UART SPI Write, dev:%d, len:%d\n", uart_index, length); -#endif - if (length == 0) { - return -1; - } - if (length == 1) { - transmit_len = 6; - message_buf = kzalloc(transmit_len, GFP_KERNEL); - 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); - } else { - transmit_len = 6 + length + 2; - message_buf = kzalloc(transmit_len, GFP_KERNEL); - 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); - } - recv_buf = kzalloc(transmit_len, GFP_KERNEL); - 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); - } - 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) -{ - s32 transmit_len; - 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; - } -#if NEURONSPI_DETAILED_DEBUG > 0 - printk(KERN_INFO "NEURONSPI: 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; - } 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 "NEURONSPI: UART Device Read len:%d %100ph\n", transmit_len, send_buf); -#endif - } - if (!d_data->reserved_device) { - neuronspi_spi_send_message(spi, send_buf, recv_buf, transmit_len, frequency, 65, 1); - } -} - -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 "NEURONSPI: 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_KERNEL); - recv_buf = kzalloc(NEURONSPI_SPI_IRQ_SET_MESSAGE_LEN, GFP_KERNEL); - 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); - } - kfree(message_buf); - kfree(recv_buf); -} - -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; - } -#if NEURONSPI_DETAILED_DEBUG > 0 - printk(KERN_INFO "NEURONSPI: 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_KERNEL); - recv_buf = kzalloc(NEURONSPI_SPI_UART_SET_CFLAG_MESSAGE_LEN, GFP_KERNEL); - 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); - 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); - } - kfree(message_buf); - kfree(recv_buf); -} - -void neuronspi_spi_uart_set_ldisc(struct spi_device* spi_dev, u8 port, u8 to) -{ - u8 *message_buf; - u8 *recv_buf; - 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 "NEURONSPI: 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); - } - kfree(message_buf); - kfree(recv_buf); -} - -u8 neuronspi_spi_uart_get_ldisc(struct spi_device* spi_dev, u8 port) -{ - u8 *message_buf; - u8 *recv_buf; - u8 outp; - 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); - } - outp = recv_buf[MODBUS_FIRST_DATA_BYTE + 1]; -#if NEURONSPI_DETAILED_DEBUG > 1 - printk(KERN_INFO "NEURONSPI: SPI TERMIOS GET, Dev-CS:%d, to:%x\n", spi_dev->chip_select, outp); -#endif - kfree(message_buf); - kfree(recv_buf); - return outp; -} - - -/* - * 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_sec_ai_data *ai_data = iio_priv(indio_dev); - struct spi_device *spi = ai_data->parent; - struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi); - 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 + (2 * ai_data->index), &sec_ai_val_h); - regmap_read(n_spi->reg_map, n_spi->regstart_table->sec_ai_val_reg + 1 + (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_sec_ai_data *ai_data = iio_priv(indio_dev); - struct spi_device *spi = ai_data->parent; - struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi); - 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 + (2 * ai_data->index), &sec_ai_val_h); - regmap_read(n_spi->reg_map, n_spi->regstart_table->sec_ai_val_reg + 1 + (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_sec_ai_data *ai_data = iio_priv(indio_dev); - struct spi_device *spi = ai_data->parent; - struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi); - 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 + (2 * ai_data->index), &sec_ai_val_h); - regmap_read(n_spi->reg_map, n_spi->regstart_table->sec_ai_val_reg + 1 + (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_sec_ao_data *ao_data = iio_priv(indio_dev); - struct spi_device *spi = ao_data->parent; - struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi); - u32 sec_true_val = (val * 2) / 5; - if (val > 10000) val = 10000; - regmap_write(n_spi->reg_map, n_spi->regstart_table->stm_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_stm_ai_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_stm_ai_data *ai_data = iio_priv(indio_dev); - struct spi_device *spi = ai_data->parent; - struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi); - 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; -} - -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_stm_ao_data *ao_data = iio_priv(indio_dev); - struct spi_device *spi = ao_data->parent; - struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi); - 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; -} - - -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_stm_ao_data *ao_data = iio_priv(indio_dev); - struct spi_device *spi = ao_data->parent; - struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi); - 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_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_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_stm_ao_data *ao_data = iio_priv(indio_dev); - struct spi_device *spi = ao_data->parent; - struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi); - 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->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); - stm_v_inp_ref = stm_v_inp_ref * 10000; - stm_true_val = (stm_true_val * 10000) - stm_i_off; - do_div(stm_true_ref, stm_v_inp_ref); - do_div(stm_true_ref, 4095); - stm_v_inp_ref = stm_true_ref; - do_div(stm_true_val, stm_v_inp_ref); - 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); -} - -/* -static s32 neuronspi_spi_watchdog(void *data) -{ - s32 *cycle = (s32 *) data; - while (!kthread_should_stop()) { - msleep(*cycle); - spin_lock(neuronspi_spi_w_spinlock); - if (neuronspi_spi_w_flag == 0) { - panic_timeout = -1; - panic("SPI Watchdog Failure\n"); - } else { - neuronspi_spi_w_flag = 0; - } - spin_unlock(neuronspi_spi_w_spinlock); - } - return 0; -} -*/ - - - -void neuronspi_spi_send_message(struct spi_device* spi_dev, u8 *send_buf, u8 *recv_buf, s32 len, s32 freq, s32 delay, s32 send_header) -{ - s32 i = 0; - 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; - struct neuronspi_driver_data *d_data; - struct spi_transfer* s_trans; - mutex_lock(&neuronspi_master_mutex); - s_trans = kzalloc(sizeof(struct spi_transfer) * trans_count, GFP_KERNEL); -#if NEURONSPI_DETAILED_DEBUG > 1 - printk(KERN_INFO "NEURONSPI: SPI Master Write, len:%d,\n %100ph\n", len, send_buf); -#endif - if (!send_header) { - trans_count -= 1; // one less transmission as the header is omitted - } - 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; - s_trans[i].bits_per_word = 8; - s_trans[i].speed_hz = freq; - if (i == 0) { - s_trans[i].delay_usecs = NEURONSPI_EDGE_DELAY; - } else if (i == 1) { - s_trans[i].tx_buf = send_buf; - s_trans[i].rx_buf = recv_buf; - if (send_header) { - s_trans[i].delay_usecs = delay; - s_trans[i].len = NEURONSPI_FIRST_MESSAGE_LENGTH; - } else { - // If len is more than NEURONSPI_MAX_TX * i, then chunk len is NEURONSPI_MAX_TX, otherwise it's the remainder - s_trans[i].len = (len - (NEURONSPI_MAX_TX * i)) > 0 ? NEURONSPI_MAX_TX : len; - } - } else if (i == trans_count - 1) { - 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))); - } 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)]); - s_trans[i].len = ((NEURONSPI_MAX_TX * i) - len) < 0 ? NEURONSPI_MAX_TX : (len - (NEURONSPI_MAX_TX * (i - 1))); - } - s_trans[i].delay_usecs = NEURONSPI_LAST_TRANSFER_DELAY; - // 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 - } else { - 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))); - } 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)]); - s_trans[i].len = ((NEURONSPI_MAX_TX * i) - len) < 0 ? NEURONSPI_MAX_TX : (len - (NEURONSPI_MAX_TX * (i - 1))); - } - // 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])); - } -#if NEURONSPI_DETAILED_DEBUG > 1 - printk(KERN_INFO "NEURONSPI: 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 - d_data = spi_get_drvdata(spi_dev); - 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 "NEURONSPI: SPI CRC1: %x\t COMPUTED CRC1:%x\n", packet_crc, recv_crc1); -#endif - if (recv_crc1 == packet_crc) { - // Signal the UART to issue character reads -#if NEURONSPI_DETAILED_DEBUG > 1 - printk(KERN_INFO "NEURONSPI: SPI CRC1 Correct"); -#endif - if (d_data && recv_buf[0] == 0x41) { - d_data->uart_buf[0] = recv_buf[3]; -#if NEURONSPI_DETAILED_DEBUG > 0 - printk(KERN_INFO "NEURONSPI: 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); - } - } - 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 "NEURONSPI: 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); - } - } - } - } - } -#if NEURONSPI_DETAILED_DEBUG > 0 - else { - printk(KERN_INFO "NEURONSPI: 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 "NEURONSPI: SPI CRC2: %x\t COMPUTED CRC2:%x\n", packet_crc, recv_crc2); -#endif - if (recv_crc2 != packet_crc) { -#if NEURONSPI_DETAILED_DEBUG > 0 - printk(KERN_INFO "NEURONSPI: SPI CRC2 Not Correct"); -#endif - recv_buf[0] = 0; - } - } - - mutex_unlock(&neuronspi_master_mutex); - kfree(s_trans); -} - - - -irqreturn_t neuronspi_spi_irq(s32 irq, void *dev_id) -{ - s32 i; - struct spi_device *spi; - struct neuronspi_driver_data *d_data; - 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 "NEURONSPI: SPI IRQ\n"); -#endif - if (d_data->uart_count) { - u_data = d_data->uart_data; - for (i = 0; i < u_data->p_count; i++) { - if (u_data->p[i].dev_index == d_data->neuron_index) { - kthread_queue_work(&u_data->kworker, &u_data->p[i].irq_work); - } - - } - } - return 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 "NEURONSPI: SPI LED Set, Dev-CS:%d, led id:%d\n", spi_dev->chip_select, id); -#endif - message_buf = kzalloc(NEURONSPI_SPI_LED_SET_MESSAGE_LEN, GFP_KERNEL); - recv_buf = kzalloc(NEURONSPI_SPI_LED_SET_MESSAGE_LEN, GFP_KERNEL); - memcpy(message_buf, NEURONSPI_SPI_LED_SET_MESSAGE, NEURONSPI_SPI_LED_SET_MESSAGE_LEN); - message_buf[2] += id; - if (brightness > 0) { - message_buf[1] = 0x01; - } else { - message_buf[1] = 0x00; - } - crc1 = neuronspi_spi_crc(message_buf, 4, 0); - memcpy(&message_buf[4], &crc1, 2); - if (!d_data->reserved_device) { - neuronspi_spi_send_message(spi_dev, message_buf, recv_buf, NEURONSPI_SPI_LED_SET_MESSAGE_LEN, frequency, 25, 0); - } - printk(KERN_INFO "NEURONSPI: Brightness set to %d on led %d\n", brightness, id); - kfree(message_buf); - kfree(recv_buf); -} - -int neuronspi_spi_gpio_di_get(struct spi_device* spi_dev, u32 id) -{ - u8 *recv_buf; - bool ret = 0; - u32 offset = id / 16; - struct neuronspi_driver_data *d_data = spi_get_drvdata(spi_dev); - recv_buf = kzalloc(4, GFP_KERNEL); - printk(KERN_INFO "NEURONSPI: REGMAP TEST: %d\n", regmap_read(d_data->reg_map, d_data->regstart_table->di_val_reg + offset, (void*)recv_buf)); - if (*recv_buf & (0x1 << offset)) { - ret = 1; - } - kfree(recv_buf); - printk(KERN_INFO "NEURONSPI: GPIO DI %d get %d\n", id, ret); - return ret; -} - -int neuronspi_spi_gpio_do_set(struct spi_device* spi_dev, u32 id, int value) -{ - u32 current_value = 0; - bool ret = 0; - u32 offset = id / 16; - u16 off_val = value << (id % 16); - u16 mask = ~(1 << (id % 16)); - struct neuronspi_driver_data *d_data = spi_get_drvdata(spi_dev); - regmap_read(d_data->reg_map, d_data->regstart_table->do_val_reg + offset, ¤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); - printk(KERN_INFO "NEURONSPI: GPIO DO %d set %d\n", id, value); - return ret; -} - -int neuronspi_spi_gpio_ro_set(struct spi_device* spi_dev, u32 id, int value) -{ - u32 current_value = 0; - bool ret = 0; - u32 offset = id / 16; - u16 off_val = value << (id % 16); - u16 mask = ~(1 << (id % 16)); - struct neuronspi_driver_data *d_data = spi_get_drvdata(spi_dev); - regmap_read(d_data->reg_map, d_data->regstart_table->ro_val_reg + offset, ¤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); - printk(KERN_INFO "NEURONSPI: GPIO RO %d set %d\n", id, value); - return ret; -} - - - -s32 neuronspi_spi_probe(struct spi_device *spi) -{ - const struct neuronspi_devtype *devtype; - struct sched_param sched_param = { .sched_priority = MAX_RT_PRIO / 2 }; - - struct neuronspi_driver_data *n_spi; - - s32 ret, i, no_irq = 0; - u8 uart_count = 0; - n_spi = kzalloc(sizeof *n_spi, GFP_KERNEL); - spin_lock(&neuronspi_probe_spinlock); - neuronspi_probe_count++; - spin_unlock(&neuronspi_probe_spinlock); - if (!n_spi) - return -ENOMEM; - printk(KERN_INFO "NEURONSPI: Neuronspi Probe Started\n"); - if (n_spi == NULL || spi == NULL) { - return -8; - } -#if NEURONSPI_DETAILED_DEBUG > 0 - printk(KERN_DEBUG "NEURONSPI: Chip Max Hz-%d\n",spi->master->max_speed_hz); -#endif - /* Setup SPI bus */ - spi->bits_per_word = 8; - spi->mode = spi->mode ? spi->mode : SPI_MODE_0; - spi->max_speed_hz = spi->max_speed_hz ? spi->max_speed_hz : 12000000; - ret = spi_setup(spi); - n_spi->neuron_index = spi->chip_select - 1; - n_spi->reserved_device = 0; - - if (neuron_plc_dev == NULL) { - neuron_plc_dev = platform_device_alloc("unipi_plc", -1); - neuron_plc_dev->dev.groups = neuron_plc_attr_groups; - platform_device_add(neuron_plc_dev); - } - - if (ret) - return ret; -#if NEURONSPI_DETAILED_DEBUG > 0 - printk(KERN_DEBUG "NEURONSPI: Chip Max Hz-%d %d\n", spi->master->max_speed_hz, spi->max_speed_hz); -#endif - if (spi->dev.of_node) { - const struct of_device_id *of_id = - of_match_device(neuronspi_id_match, &spi->dev); - if (!of_id) { - printk(KERN_DEBUG "NEURONSPI: Probe %s does not match a device!\n", *(&spi->dev.of_node->full_name)); - return -ENODEV; - } - of_property_read_u32_array(spi->dev.of_node, "neuron-board-index", &(n_spi->neuron_index), 1); - //print_device_tree_node(spi->dev.of_node->parent, 0); - devtype = (struct neuronspi_devtype *)of_id->data; -#if NEURONSPI_DETAILED_DEBUG > 0 - printk(KERN_INFO "DEVICE TREE NODE FOUND %d\n", n_spi->neuron_index); -#endif - } else { - const struct spi_device_id *id_entry = spi_get_device_id(spi); - devtype = (struct neuronspi_devtype *)id_entry->driver_data; - } - - - kthread_init_worker(&n_spi->primary_worker); - - n_spi->primary_worker_task = kthread_run(kthread_worker_fn, &n_spi->primary_worker, "neuronspi"); - if (IS_ERR(n_spi->primary_worker_task )) { - ret = PTR_ERR(n_spi->primary_worker_task); - return ret; - } - sched_setscheduler(n_spi->primary_worker_task, SCHED_FIFO, &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_KERNEL); - n_spi->send_buf = kzalloc(NEURONSPI_BUFFER_MAX, GFP_KERNEL); - n_spi->first_probe_reply = kzalloc(NEURONSPI_PROBE_MESSAGE_LEN, GFP_KERNEL); // allocate space for initial probe - n_spi->second_probe_reply = kzalloc(NEURONSPI_PROBE_MESSAGE_LEN, GFP_KERNEL); // allocate space for uart probe - n_spi->lower_board_id = 0xFF; - n_spi->upper_board_id = 0xFF; - 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); - - // Throw away the first message - the associated SPI Master is sometimes not properly initialised at this point - 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); - i++; - if (i > 1000) { // Sanity check to prevent looping if we get constant UART/0x41 messages - ret = -4; - kfree(n_spi); - printk(KERN_INFO "NEURONSPI: Probe did not detect a valid Neuron device on CS %d\n", spi->chip_select); - return ret; - } - } while (n_spi->first_probe_reply[0] == 0x41); // UART messages should be ignored - - 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; - for (i = 0; i < NEURONSPI_BOARDTABLE_LEN; i++) { - if (n_spi->first_probe_reply[19] == 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]; - } - if (n_spi->first_probe_reply[17] == NEURONSPI_BOARDTABLE[i].index) { - n_spi->combination_id = n_spi->first_probe_reply[17]; - n_spi->upper_board_id = NEURONSPI_BOARDTABLE[i].upper_board_id; - } - } - } - } else { - ret = -5; - kfree(n_spi); - printk(KERN_INFO "NEURONSPI: Probe did not detect a valid Neuron device on CS %d\n", spi->chip_select); - return ret; - } - - if (n_spi->lower_board_id != 0xFF && n_spi->combination_id != 0xFF) { - n_spi->features = kzalloc(sizeof(struct neuronspi_board_features), GFP_KERNEL); - n_spi->features = &(NEURONSPI_BOARDTABLE[n_spi->combination_id].definition->features); - } else { - n_spi->features = NULL; - } - - 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])) { - n_spi->slower_model = 1; - n_spi->ideal_frequency = NEURONSPI_SLOWER_FREQ; - } - } - if (n_spi->lower_board_id != 0xFF && n_spi->combination_id != 0xFF) { - printk(KERN_INFO "NEURONSPI: Probe detected Neuron Board %s (L:%x U:%x C:%x) Index: %d Fw: v%d.%d on CS %d, \ -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]); - } else if (n_spi->lower_board_id != 0xFF) { - printk(KERN_INFO "NEURONSPI: Probe detected Neuron 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]); - } else { - printk(KERN_INFO "NEURONSPI: Probe detected Neuron 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]); - } - printk(KERN_INFO "NEURONSPI: Neuron device %s on CS %d uses SPI communication freq. %d Hz\n", - NEURONSPI_BOARDTABLE[n_spi->combination_id].definition->combination_name, - spi->chip_select, n_spi->ideal_frequency); - - n_spi->reg_map = regmap_init(&(spi->dev), &neuronspi_regmap_bus, spi, &neuronspi_regmap_config_default); - spin_lock_init(&n_spi->sysfs_regmap_lock); - if (n_spi->features) { - n_spi->regstart_table = kzalloc(sizeof(struct neuronspi_board_regstart_table), 1); - neuronspi_create_reg_starts(n_spi->regstart_table, NEURONSPI_BOARDTABLE[n_spi->combination_id].definition); - } else { - n_spi->regstart_table = NULL; - } - - - // Check for user-configurable LED devices - if (n_spi->features && n_spi->features->led_count > 0) { - printk(KERN_INFO "NEURONSPI: LED model %s with %d LEDs detected at CS: %d\n", - NEURONSPI_BOARDTABLE[n_spi->combination_id].definition->combination_name, - n_spi->features->led_count, spi->chip_select); - n_spi->led_driver = kzalloc(sizeof(struct neuronspi_led_driver) * n_spi->features->led_count, GFP_KERNEL); - for (i = 0; i < n_spi->features->led_count; i++) { - kthread_init_work(&(n_spi->led_driver[i].led_work), neuronspi_led_proc); - } - } - - - if (uart_count && neuronspi_uart == NULL) { // Register UART if not registered - neuronspi_uart = kzalloc(sizeof(struct uart_driver), GFP_KERNEL); - neuronspi_uart->owner = THIS_MODULE; - neuronspi_uart->dev_name = "ttyNS"; - neuronspi_uart->driver_name = "ttyNS"; - neuronspi_uart->nr = NEURONSPI_MAX_UART; - ret = uart_register_driver(neuronspi_uart); - if (ret) { - printk(KERN_ERR "NEURONSPI:Failed to register the neuronspi uart driver, ERR:%d\n", ret); - } else { -#if NEURONSPI_DETAILED_DEBUG > 0 - printk(KERN_DEBUG "NEURONSPI: UART driver registered successfully!\n"); -#endif - } - if (neuronspi_uart_glob_data != NULL) { - printk(KERN_ERR "NEURONSPI:Uart data already allocated!\n"); - } else { - neuronspi_uart_glob_data = kzalloc(sizeof(struct neuronspi_uart_data), GFP_KERNEL); -#if NEURONSPI_DETAILED_DEBUG > 0 - printk(KERN_DEBUG "NEURONSPI: UART driver data allocated successfully!\n"); -#endif - } - - } - if (neuronspi_uart_glob_data != NULL) { - n_spi->uart_data = neuronspi_uart_glob_data; - } - n_spi->char_driver = &neuronspi_cdrv; - if (uart_count) { - n_spi->serial_driver = neuronspi_uart; - } else { - n_spi->serial_driver = NULL; - } - n_spi->uart_count = uart_count; - -#if NEURONSPI_DETAILED_DEBUG > 0 - printk(KERN_DEBUG "NEURONSPI: CHIP SELECT %d\n", spi->chip_select); -#endif - spin_lock(&neuronspi_probe_spinlock); - neuronspi_s_dev[n_spi->neuron_index] = spi; - spi_set_drvdata(neuronspi_s_dev[n_spi->neuron_index], n_spi); - if (neuronspi_probe_count == NEURONSPI_MAX_DEVS) { - printk(KERN_INFO "NEURONSPI: MAXPROBECOUNT\n"); - neuronspi_model_id = neuronspi_find_model_id(neuronspi_probe_count); - } - spin_unlock(&neuronspi_probe_spinlock); - if (neuronspi_model_id != -1) { - printk(KERN_INFO "NEURONSPI: Detected Neuron board combination corresponding to %s\n", NEURONSPI_MODELTABLE[neuronspi_model_id].model_name); - } -#if NEURONSPI_DETAILED_DEBUG > 0 - printk(KERN_DEBUG "NEURONSPI: SPI IRQ: %d", spi->irq); -#endif - 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); - n_spi->board_device->dev.parent = &(neuron_plc_dev->dev); - n_spi->board_device->dev.groups = neuron_board_attr_groups; - n_spi->board_device->dev.driver = &neuronspi_spi_driver.driver; - platform_device_add(n_spi->board_device); - platform_set_drvdata(n_spi->board_device, n_spi); - - if (!(neuronspi_cdrv.major_number)) { // Register character device if it doesn't exist - ret = char_register_driver(); - if (ret) { - printk(KERN_ERR "NEURONSPI: Failed to register the neuronspi character driver, ERR:%d\n", ret); - } - } - - if (n_spi->features) { - if (n_spi->features->led_count) { - for (i = 0; i < n_spi->features->led_count; i++) { - strcpy(n_spi->led_driver[i].name, "neuron:green:uled-x1"); - n_spi->led_driver[i].name[19] = i + '1'; - // Initialise the rest of the structure - n_spi->led_driver[i].id = i; - n_spi->led_driver[i].brightness = LED_OFF; - n_spi->led_driver[i].spi = spi; - spin_lock_init(&n_spi->led_driver[i].lock); - n_spi->led_driver[i].ldev.name = n_spi->led_driver[i].name; - n_spi->led_driver[i].ldev.brightness = n_spi->led_driver[i].brightness; - n_spi->led_driver[i].ldev.brightness_set = neuronspi_led_set_brightness; - led_classdev_register(&(n_spi->board_device->dev), &(n_spi->led_driver[i].ldev)); - } - } -#ifdef CONFIG_GPIOLIB - - if (n_spi->features->di_count) { - n_spi->di_driver = kzalloc(sizeof(struct neuronspi_di_driver*) * n_spi->features->di_count, GFP_KERNEL); - for (i = 0; i < n_spi->features->di_count; i++) { - n_spi->di_driver[i] = kzalloc(sizeof(struct neuronspi_di_driver), GFP_KERNEL); - strcpy(n_spi->di_driver[i]->name, "di_0_00"); - n_spi->di_driver[i]->name[3] = n_spi->neuron_index + '1'; - n_spi->di_driver[i]->name[5] = ((i + 1) / 10) + '0'; - n_spi->di_driver[i]->name[6] = ((i + 1) % 10) + '0'; - n_spi->di_driver[i]->di_index = i; - n_spi->di_driver[i]->spi = spi; - n_spi->di_driver[i]->plat_dev = platform_device_alloc(n_spi->di_driver[i]->name, -1); - n_spi->di_driver[i]->plat_dev->dev.parent = &(n_spi->board_device->dev); - n_spi->di_driver[i]->plat_dev->dev.groups = neuron_gpio_di_attr_groups; - n_spi->di_driver[i]->plat_dev->dev.driver = &neuronspi_spi_driver.driver; - platform_device_add(n_spi->di_driver[i]->plat_dev); - platform_set_drvdata(n_spi->di_driver[i]->plat_dev, n_spi->di_driver[i]); - n_spi->di_driver[i]->gpio_c.owner = THIS_MODULE; - n_spi->di_driver[i]->gpio_c.parent = &(n_spi->di_driver[i]->plat_dev->dev); - n_spi->di_driver[i]->gpio_c.label = "neuron_di"; - n_spi->di_driver[i]->gpio_c.can_sleep = 1; - n_spi->di_driver[i]->gpio_c.ngpio = 1; - n_spi->di_driver[i]->gpio_c.base = -1; - n_spi->di_driver[i]->gpio_c.direction_input = neuronspi_gpio_di_direction_input; - n_spi->di_driver[i]->gpio_c.get = neuronspi_gpio_di_get; - gpiochip_add_data(&n_spi->di_driver[i]->gpio_c, n_spi->di_driver[i]); - } - } - - if (n_spi->features->do_count) { - n_spi->do_driver = kzalloc(sizeof(struct neuronspi_do_driver*) * n_spi->features->do_count, GFP_KERNEL); - for (i = 0; i < n_spi->features->do_count; i++) { - n_spi->do_driver[i] = kzalloc(sizeof(struct neuronspi_do_driver), GFP_KERNEL); - strcpy(n_spi->do_driver[i]->name, "do_0_00"); - n_spi->do_driver[i]->name[3] = n_spi->neuron_index + '1'; - n_spi->do_driver[i]->name[5] = ((i + 1) / 10) + '0'; - n_spi->do_driver[i]->name[6] = ((i + 1) % 10) + '0'; - n_spi->do_driver[i]->do_index = i; - n_spi->do_driver[i]->spi = spi; - n_spi->do_driver[i]->plat_dev = platform_device_alloc(n_spi->do_driver[i]->name, -1); - n_spi->do_driver[i]->plat_dev->dev.parent = &(n_spi->board_device->dev); - n_spi->do_driver[i]->plat_dev->dev.groups = neuron_gpio_do_attr_groups; - n_spi->do_driver[i]->plat_dev->dev.driver = &neuronspi_spi_driver.driver; - platform_device_add(n_spi->do_driver[i]->plat_dev); - platform_set_drvdata(n_spi->do_driver[i]->plat_dev, n_spi->do_driver[i]); - n_spi->do_driver[i]->gpio_c.owner = THIS_MODULE; - n_spi->do_driver[i]->gpio_c.parent = &(n_spi->do_driver[i]->plat_dev->dev); - n_spi->do_driver[i]->gpio_c.label = "neuron_do"; - n_spi->do_driver[i]->gpio_c.can_sleep = 1; - n_spi->do_driver[i]->gpio_c.ngpio = n_spi->features->do_count; - n_spi->do_driver[i]->gpio_c.base = -1; - n_spi->do_driver[i]->gpio_c.direction_output = neuronspi_gpio_do_direction_output; - n_spi->do_driver[i]->gpio_c.set = neuronspi_gpio_do_set; - gpiochip_add_data(&n_spi->do_driver[i]->gpio_c, n_spi->do_driver[i]); - } - } - - if (n_spi->features->ro_count) { - n_spi->ro_driver = kzalloc(sizeof(struct neuronspi_ro_driver*) * n_spi->features->ro_count, GFP_KERNEL); - for (i = 0; i < n_spi->features->ro_count; i++) { - n_spi->ro_driver[i] = kzalloc(sizeof(struct neuronspi_ro_driver), GFP_KERNEL); - strcpy(n_spi->ro_driver[i]->name, "ro_0_00"); - n_spi->ro_driver[i]->name[3] = n_spi->neuron_index + '1'; - n_spi->ro_driver[i]->name[5] = ((i + 1) / 10) + '0'; - n_spi->ro_driver[i]->name[6] = ((i + 1) % 10) + '0'; - n_spi->ro_driver[i]->ro_index = i; - n_spi->ro_driver[i]->spi = spi; - n_spi->ro_driver[i]->plat_dev = platform_device_alloc(n_spi->ro_driver[i]->name, -1); - n_spi->ro_driver[i]->plat_dev->dev.parent = &(n_spi->board_device->dev); - n_spi->ro_driver[i]->plat_dev->dev.groups = neuron_gpio_ro_attr_groups; - n_spi->ro_driver[i]->plat_dev->dev.driver = &neuronspi_spi_driver.driver; - platform_device_add(n_spi->ro_driver[i]->plat_dev); - platform_set_drvdata(n_spi->ro_driver[i]->plat_dev, n_spi->ro_driver[i]); - n_spi->ro_driver[i]->gpio_c.owner = THIS_MODULE; - n_spi->ro_driver[i]->gpio_c.parent = &(n_spi->ro_driver[i]->plat_dev->dev); - n_spi->ro_driver[i]->gpio_c.label = "neuron_ro"; - n_spi->ro_driver[i]->gpio_c.can_sleep = 1; - n_spi->ro_driver[i]->gpio_c.ngpio = n_spi->features->ro_count; - n_spi->ro_driver[i]->gpio_c.base = -1; - n_spi->ro_driver[i]->gpio_c.direction_output = neuronspi_gpio_ro_direction_output; - n_spi->ro_driver[i]->gpio_c.set = neuronspi_gpio_ro_set; - gpiochip_add_data(&n_spi->ro_driver[i]->gpio_c, n_spi->ro_driver[i]); - } - } - -#endif - if (n_spi->features->stm_ai_count) { - n_spi->stm_ai_driver = devm_iio_device_alloc(&(spi->dev), sizeof(struct neuronspi_stm_ai_data)); - ((struct neuronspi_stm_ai_data*)iio_priv(n_spi->stm_ai_driver))->parent = spi; - n_spi->stm_ai_driver->modes = INDIO_DIRECT_MODE; - n_spi->stm_ai_driver->currentmode = INDIO_DIRECT_MODE; - n_spi->stm_ai_driver->name = "ai_type_a"; - n_spi->stm_ai_driver->dev.parent = &(n_spi->board_device->dev); - dev_set_name(&n_spi->stm_ai_driver->dev, "ai_%d_1", (int)n_spi->neuron_index + 1); - n_spi->stm_ai_driver->num_channels = 2; - n_spi->stm_ai_driver->channels = neuronspi_stm_ai_chan_spec; - n_spi->stm_ai_driver->info = &neuronspi_stm_ai_info; - iio_device_register(n_spi->stm_ai_driver); - } - if (n_spi->features->stm_ao_count) { - n_spi->stm_ao_driver = devm_iio_device_alloc(&(spi->dev), sizeof(struct neuronspi_stm_ai_data)); - ((struct neuronspi_stm_ao_data*)iio_priv(n_spi->stm_ao_driver))->parent = spi; - n_spi->stm_ao_driver->modes = INDIO_DIRECT_MODE; - n_spi->stm_ao_driver->currentmode = INDIO_DIRECT_MODE; - n_spi->stm_ao_driver->name = "ao_type_a"; - n_spi->stm_ao_driver->dev.parent = &(n_spi->board_device->dev); - dev_set_name(&n_spi->stm_ao_driver->dev, "ao_%d_1", (int)n_spi->neuron_index + 1); - n_spi->stm_ao_driver->num_channels = 3; - n_spi->stm_ao_driver->channels = neuronspi_stm_ao_chan_spec; - n_spi->stm_ao_driver->info = &neuronspi_stm_ao_info; - iio_device_register(n_spi->stm_ao_driver); - } - if (n_spi->features->sec_ai_count) { - n_spi->sec_ai_driver = kzalloc(sizeof(struct neuronspi_sec_ai_data*) * n_spi->features->sec_ai_count, GFP_KERNEL); - for (i = 0; i < n_spi->features->sec_ai_count; i++) { - n_spi->sec_ai_driver[i] = devm_iio_device_alloc(&(spi->dev), sizeof(struct neuronspi_sec_ai_data)); - ((struct neuronspi_sec_ai_data*)iio_priv(n_spi->sec_ai_driver[i]))->parent = spi; - n_spi->sec_ai_driver[i]->modes = INDIO_DIRECT_MODE; - n_spi->sec_ai_driver[i]->currentmode = INDIO_DIRECT_MODE; - n_spi->sec_ai_driver[i]->name = "ai_type_b"; - n_spi->sec_ai_driver[i]->dev.parent = &(n_spi->board_device->dev); - dev_set_name(&n_spi->sec_ai_driver[i]->dev, "ai_%d_%d", (int)n_spi->neuron_index + 1, (int)i + 1); - n_spi->sec_ai_driver[i]->num_channels = 3; - n_spi->sec_ai_driver[i]->channels = neuronspi_sec_ai_chan_spec; - n_spi->sec_ai_driver[i]->info = &neuronspi_sec_ai_info; - iio_device_register(n_spi->sec_ai_driver[i]); - } - } - if (n_spi->features->sec_ao_count) { - n_spi->sec_ao_driver = kzalloc(sizeof(struct neuronspi_sec_ao_data*) * n_spi->features->sec_ao_count, GFP_KERNEL); - for (i = 0; i < n_spi->features->sec_ao_count; i++) { - n_spi->sec_ao_driver[i] = devm_iio_device_alloc(&(spi->dev), sizeof(struct neuronspi_sec_ao_data)); - ((struct neuronspi_sec_ao_data*)iio_priv(n_spi->sec_ao_driver[i]))->parent = spi; - n_spi->sec_ao_driver[i]->modes = INDIO_DIRECT_MODE; - n_spi->sec_ao_driver[i]->currentmode = INDIO_DIRECT_MODE; - n_spi->sec_ao_driver[i]->name = "ao_type_b"; - n_spi->sec_ao_driver[i]->dev.parent = &(n_spi->board_device->dev); - dev_set_name(&n_spi->sec_ao_driver[i]->dev, "ao_%d_%d", (int)n_spi->neuron_index + 1, (int)i + 1); - n_spi->sec_ao_driver[i]->num_channels = 1; - n_spi->sec_ao_driver[i]->channels = neuronspi_sec_ao_chan_spec; - n_spi->sec_ao_driver[i]->info = &neuronspi_sec_ao_info; - iio_device_register(n_spi->sec_ao_driver[i]); - } - } - } - - if (uart_count) { -#if NEURONSPI_DETAILED_DEBUG > 0 - printk(KERN_DEBUG "NEURONSPI: UART registration 1\n"); -#endif - n_spi->uart_buf = kzalloc(NEURONSPI_FIFO_SIZE, GFP_KERNEL); - neuronspi_uart_probe(spi, n_spi->neuron_index); -#if NEURONSPI_DETAILED_DEBUG > 0 - printk(KERN_DEBUG "NEURONSPI: UART PROBE MCTRL:%d\n", neuronspi_spi_uart_get_cflag(spi, 0)); -#endif - } -#if NEURONSPI_DETAILED_DEBUG > 0 - printk(KERN_DEBUG "NEURONSPI: UART registration\n"); -#endif - 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])) { - no_irq = 1; - } - } - - n_spi->poll_thread = NULL; - 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 "NEURONSPI: IRQ registration, ret:%d\n", ret); -#endif - } else { - n_spi->no_irq = 1; -#if NEURONSPI_DETAILED_DEBUG > 0 - printk(KERN_DEBUG "NEURONSPI: NO IRQ ON THIS MODEL !!\n"); -#endif - } - - 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_KERNEL); - recv_buf = kzalloc(NEURONSPI_SPI_UART_GET_CFLAG_MESSAGE_LEN, GFP_KERNEL); - memcpy(message_buf, NEURONSPI_SPI_UART_GET_CFLAG_MESSAGE, NEURONSPI_SPI_UART_GET_CFLAG_MESSAGE_LEN); - crc1 = neuronspi_spi_crc(message_buf, 4, 0); - memcpy(&message_buf[4], &crc1, 2); - crc2 = neuronspi_spi_crc(&message_buf[6], NEURONSPI_SPI_UART_GET_CFLAG_MESSAGE_LEN - 8, crc1); - memcpy(&message_buf[NEURONSPI_SPI_UART_GET_CFLAG_MESSAGE_LEN - 2], &crc2, 2); - if (!d_data->reserved_device) { - neuronspi_spi_send_message(spi_dev, message_buf, recv_buf, NEURONSPI_SPI_UART_GET_CFLAG_MESSAGE_LEN, frequency, 65, 1); - } - ret = ((u32*)recv_buf)[5]; -#if NEURONSPI_DETAILED_DEBUG > 0 - printk(KERN_INFO "NEURONSPI: SPI TERMIOS Get, Dev-CS:%d, val:%x\n", spi_dev->chip_select, ret); -#endif - kfree(message_buf); - kfree(recv_buf); - return ret; -} - -s32 neuronspi_spi_remove(struct spi_device *spi) -{ - int i; - struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi); - if (n_spi) { - if (n_spi->led_driver) { - for (i = 0; i < n_spi->features->led_count; i++) { - led_classdev_unregister(&(n_spi->led_driver[i].ldev)); - } - kthread_flush_worker(&n_spi->primary_worker); - kfree(n_spi->led_driver); - n_spi->led_driver = NULL; - } - printk(KERN_INFO "NEURONSPI: LED DRIVER UNREGISTERED\n"); - if (n_spi->di_driver) { - for (i = 0; i < n_spi->features->di_count; i++) { - gpiochip_remove(&n_spi->di_driver[i]->gpio_c); - platform_set_drvdata(n_spi->di_driver[i]->plat_dev, 0); - platform_device_unregister(n_spi->di_driver[i]->plat_dev); - kfree(n_spi->di_driver[i]); - } - kfree(n_spi->di_driver); - } - if (n_spi->do_driver) { - for (i = 0; i < n_spi->features->do_count; i++) { - gpiochip_remove(&n_spi->do_driver[i]->gpio_c); - platform_set_drvdata(n_spi->do_driver[i]->plat_dev, 0); - platform_device_unregister(n_spi->do_driver[i]->plat_dev); - kfree(n_spi->do_driver[i]); - } - kfree(n_spi->do_driver); - } - if (n_spi->ro_driver) { - for (i = 0; i < n_spi->features->ro_count; i++) { - gpiochip_remove(&n_spi->ro_driver[i]->gpio_c); - platform_set_drvdata(n_spi->ro_driver[i]->plat_dev, 0); - platform_device_unregister(n_spi->ro_driver[i]->plat_dev); - kfree(n_spi->ro_driver[i]); - } - kfree(n_spi->ro_driver); - } - printk(KERN_INFO "NEURONSPI: GPIO DRIVER UNREGISTERED\n"); - if (n_spi->stm_ai_driver) { - iio_device_unregister(n_spi->stm_ai_driver); - } - if (n_spi->stm_ao_driver) { - iio_device_unregister(n_spi->stm_ao_driver); - } - if (n_spi->sec_ai_driver) { - for (i = 0; i < n_spi->features->sec_ai_count; i++) { - iio_device_unregister(n_spi->sec_ai_driver[i]); - } - kfree(n_spi->sec_ai_driver); - n_spi->sec_ai_driver = NULL; - } - if (n_spi->sec_ao_driver) { - for (i = 0; i < n_spi->features->sec_ao_count; i++) { - iio_device_unregister(n_spi->sec_ao_driver[i]); - } - kfree(n_spi->sec_ao_driver); - n_spi->sec_ao_driver = NULL; - } - printk(KERN_INFO "NEURONSPI: 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; - } - printk(KERN_INFO "NEURONSPI: SPI/UART DRIVER UNREGISTERED\n"); - if (n_spi->board_device) { - platform_set_drvdata(n_spi->board_device, 0); - platform_device_unregister(n_spi->board_device); - } - kfree(n_spi); - } - return 0; -} - -s32 char_register_driver(void) -{ - s32 ret = 0; - - // Character device registration -#if NEURONSPI_DETAILED_DEBUG > 0 - printk(KERN_DEBUG "NEURONSPI: Initialising Character Device\n"); -#endif - 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 "NEURONSPI: registered correctly with major number %d\n", neuronspi_cdrv.major_number); -#endif - - // Character class registration - neuronspi_cdrv.driver_class = class_create(THIS_MODULE, NEURON_DEVICE_CLASS); - if (IS_ERR(neuronspi_cdrv.driver_class)) { - unregister_chrdev(neuronspi_cdrv.major_number, NEURON_DEVICE_NAME); - 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 "NEURONSPI: device class registered correctly\n"); -#endif - - // 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); - if (IS_ERR(neuronspi_cdrv.dev)) { - class_destroy(neuronspi_cdrv.driver_class); - unregister_chrdev(neuronspi_cdrv.major_number, NEURON_DEVICE_NAME); - printk(KERN_ALERT "NEURONSPI: Failed to create the device\n"); - return PTR_ERR(neuronspi_cdrv.dev); - } -#if NEURONSPI_DETAILED_DEBUG > 0 - printk(KERN_DEBUG "NEURONSPI: device class created correctly\n"); -#endif - return ret; -} - -s32 char_unregister_driver(void) -{ - device_destroy(neuronspi_cdrv.driver_class, MKDEV(neuronspi_cdrv.major_number, 0)); // Destroy the device - class_unregister(neuronspi_cdrv.driver_class); // Unregister the class - class_destroy(neuronspi_cdrv.driver_class); // Destroy the class - unregister_chrdev(neuronspi_cdrv.major_number, NEURON_DEVICE_NAME); // Unregister the major number - printk(KERN_INFO "NEURONSPI: Device unloaded successfully\n"); - return 0; -} - -/********************* - * Final definitions * - *********************/ - -MODULE_ALIAS("spi:neuronspi"); - -static s32 __init neuronspi_init(void) -{ - s32 ret = 0; - neuronspi_spi_w_spinlock = kzalloc(sizeof(struct spinlock), GFP_KERNEL); - spin_lock_init(neuronspi_spi_w_spinlock); - mutex_init(&neuronspi_master_mutex); - memset(&neuronspi_s_dev, 0, sizeof(neuronspi_s_dev)); - ret = spi_register_driver(&neuronspi_spi_driver); - if (ret < 0) { - printk(KERN_ERR "NEURONSPI: Failed to init neuronspi spi --> %d\n", ret); - return ret; - } else { -#ifdef NEURONSPI_MAJOR_VERSIONSTRING - printk(KERN_INFO "NEURONSPI: SPI Driver Registered, Major Version: %s\n", NEURONSPI_MAJOR_VERSIONSTRING); -#else - printk(KERN_INFO "NEURONSPI: SPI Driver Registered\n"); -#endif - } - neuronspi_invalidate_thread = kthread_create(neuronspi_regmap_invalidate, NULL, "neuronspi_inv"); - if (neuronspi_invalidate_thread != NULL) { - wake_up_process(neuronspi_invalidate_thread); - } - return ret; -} -__attribute__((unused)) module_init(neuronspi_init); - -static void __exit neuronspi_exit(void) -{ -#if NEURONSPI_DETAILED_DEBUG > 0 - printk(KERN_INFO "NEURONSPI: Open Counter is %d\n", neuronspi_cdrv.open_counter); -#endif - if (neuronspi_invalidate_thread) { - kthread_stop(neuronspi_invalidate_thread); - } - char_unregister_driver(); - if (neuronspi_uart) { - neuronspi_uart_remove(neuronspi_uart_glob_data); - uart_unregister_driver(neuronspi_uart); - kfree(neuronspi_uart); - kfree(neuronspi_uart_glob_data); - } - spi_unregister_driver(&neuronspi_spi_driver); - if (neuron_plc_dev) { - platform_device_unregister(neuron_plc_dev); - } - kfree(neuronspi_spi_w_spinlock); - printk(KERN_INFO "NEURONSPI: SPI Driver Unregistered\n"); -} -__attribute__((unused)) module_exit(neuronspi_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Tomas Knot "); -MODULE_DESCRIPTION("UniPi Neuron driver"); diff --git a/modules/neuron_spi/src/unipi_spi.h b/modules/neuron_spi/src/unipi_spi.h deleted file mode 100644 index 75e795f..0000000 --- a/modules/neuron_spi/src/unipi_spi.h +++ /dev/null @@ -1,512 +0,0 @@ -/* - * UniPi Neuron tty serial driver - Copyright (C) 2017 UniPi Technologies - * Author: Tomas Knot - * - * Based on the SC16IS7xx driver by Jon Ringle , - * which was in turn based on max310x.c, by Alexander Shiyan - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - */ - -#ifndef MODULES_NEURON_SPI_SRC_UNIPI_SPI_H_ -#define MODULES_NEURON_SPI_SRC_UNIPI_SPI_H_ - -/************ - * Includes * - ************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "unipi_common.h" -#include "unipi_platform.h" -#include "unipi_sysfs.h" -#include "unipi_iio.h" - -/******************** - * Module Constants * - ********************/ - -#define NEURONSPI_SLOWER_MODELS_LEN 3 -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, - 0x04, 0x00, 0xe8, 0x03, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x12, 0x16 -}; - -#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 -}; - -#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 -}; - -#define NEURONSPI_SPI_UART_LONG_MESSAGE_LEN 8 -static const u8 NEURONSPI_SPI_UART_LONG_MESSAGE[NEURONSPI_SPI_UART_LONG_MESSAGE_LEN] = { - 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00 -}; - -#define NEURONSPI_SPI_UART_READ_MESSAGE_LEN 14 -static const u8 NEURONSPI_SPI_UART_READ_MESSAGE[NEURONSPI_SPI_UART_READ_MESSAGE_LEN] = { - 0x65, 0x06, 0x00, 0x00, 0x44, 0x69, - 0x65, 0x03, 0x00, 0x00, 0x00, 0x05, - 0x6a, 0x0c -}; - -#define NEURONSPI_SPI_IRQ_SET_MESSAGE_LEN 14 -static const u8 NEURONSPI_SPI_IRQ_SET_MESSAGE[NEURONSPI_SPI_UART_READ_MESSAGE_LEN] = { - 0x06, 0x06, 0xef, 0x03, 0x00, 0x00, - 0x06, 0x01, 0xef, 0x03, 0x05, 0x00, - 0x00, 0x00 -}; - -#define NEURONSPI_SPI_UART_GET_CFLAG_MESSAGE_LEN 16 -static const u8 NEURONSPI_SPI_UART_GET_CFLAG_MESSAGE[NEURONSPI_SPI_UART_GET_CFLAG_MESSAGE_LEN] = { - 0x04, 0x08, 0xf4, 0x01, 0x00, 0x00, - 0x04, 0x02, 0xf4, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00 -}; - -#define NEURONSPI_SPI_UART_GET_LDISC_MESSAGE_LEN 16 -static const u8 NEURONSPI_SPI_UART_GET_LDISC_MESSAGE[NEURONSPI_SPI_UART_GET_LDISC_MESSAGE_LEN] = { - 0x04, 0x08, 0xf6, 0x01, 0x00, 0x00, - 0x04, 0x02, 0xf6, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00 -}; - -#define NEURONSPI_SPI_UART_SET_CFLAG_MESSAGE_LEN 16 -static const u8 NEURONSPI_SPI_UART_SET_CFLAG_MESSAGE[NEURONSPI_SPI_UART_SET_CFLAG_MESSAGE_LEN] = { - 0x06, 0x08, 0xf4, 0x01, 0x00, 0x00, - 0x06, 0x02, 0xf4, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00 -}; - -#define NEURONSPI_SPI_LED_SET_MESSAGE_LEN 6 -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] = { - 0, 1408, 3968, 2560, 7040, 7680, 5120, 4480, 13184, 13824, 15360, -14720, 10240, 11648, 10112, 8704, 25472, 26112, 27648, 27008, 30720, 32128, -30592, 29184, 20480, 21888, 24448, 23040, 19328, 19968, 17408, 16768, 50048, -50688, 52224, 51584, 55296, 56704, 55168, 53760, 61440, 62848, 65408, 64000, -60288, 60928, 58368, 57728, 40960, 42368, 44928, 43520, 48000, 48640, 46080, -45440, 37760, 38400, 39936, 39296, 34816, 36224, 34688, 33280, 33665, 34305, -35841, 35201, 38913, 40321, 38785, 37377, 45057, 46465, 49025, 47617, 43905, -44545, 41985, 41345, 57345, 58753, 61313, 59905, 64385, 65025, 62465, 61825, -54145, 54785, 56321, 55681, 51201, 52609, 51073, 49665, 16385, 17793, 20353, -18945, 23425, 24065, 21505, 20865, 29569, 30209, 31745, 31105, 26625, 28033, -26497, 25089, 9089, 9729, 11265, 10625, 14337, 15745, 14209, 12801, 4097, - 5505, 8065, 6657, 2945, 3585, 1025, 385, 899, 1539, 3075, 2435, - 6147, 7555, 6019, 4611, 12291, 13699, 16259, 14851, 11139, 11779, 9219, - 8579, 24579, 25987, 28547, 27139, 31619, 32259, 29699, 29059, 21379, 22019, -23555, 22915, 18435, 19843, 18307, 16899, 49155, 50563, 53123, 51715, 56195, -56835, 54275, 53635, 62339, 62979, 64515, 63875, 59395, 60803, 59267, 57859, -41859, 42499, 44035, 43395, 47107, 48515, 46979, 45571, 36867, 38275, 40835, -39427, 35715, 36355, 33795, 33155, 32770, 34178, 36738, 35330, 39810, 40450, -37890, 37250, 45954, 46594, 48130, 47490, 43010, 44418, 42882, 41474, 58242, -58882, 60418, 59778, 63490, 64898, 63362, 61954, 53250, 54658, 57218, 55810, -52098, 52738, 50178, 49538, 17282, 17922, 19458, 18818, 22530, 23938, 22402, -20994, 28674, 30082, 32642, 31234, 27522, 28162, 25602, 24962, 8194, 9602, -12162, 10754, 15234, 15874, 13314, 12674, 4994, 5634, 7170, 6530, 2050, - 3458, 1922, 514 -}; - -static const struct of_device_id neuronspi_id_match[] = { - {.compatible = "unipi,neuron"}, - {.compatible = NEURON_DEVICE_NAME}, - {} -}; - -/*************** - * Definitions * - ***************/ - -#define NEURON_INT_RX_NOT_EMPTY 0x1 -#define NEURON_INT_TX_FINISHED 0x2 -#define NEURON_INT_RX_MODBUS 0x4 -#define NEURON_INT_DI_CHANGED 0x8 -#define NEURON_INT_ID_MASK 0x0f -#define NEURON_INT_NO_INT_BIT 0x0f - -#define NEURONSPI_RECONF_MD (1 << 0) -#define NEURONSPI_RECONF_IER (1 << 1) -#define NEURONSPI_RECONF_RS485 (1 << 2) - -#define MODBUS_FIRST_DATA_BYTE 10 - -#define MODBUS_MAX_READ_BITS 2000 -#define MODBUS_MAX_WRITE_BITS 1968 -#define MODBUS_MAX_READ_REGISTERS 125 -#define MODBUS_MAX_WRITE_REGISTERS 123 -#define MODBUS_MAX_WR_WRITE_REGISTERS 121 -#define MODBUS_MAX_WR_READ_REGISTERS 125 - -/************************* - * Function Declarations * - *************************/ - -int neuronspi_open (struct inode *, struct file *); -int neuronspi_release (struct inode *, struct file *); -ssize_t neuronspi_read (struct file *, char *, size_t, loff_t *); -ssize_t neuronspi_write (struct file *, const char *, size_t, loff_t *); -s32 char_register_driver(void); -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); -void neuronspi_spi_send_message(struct spi_device *spi_dev, u8 *send_buf, u8 *recv_buf, s32 len, s32 freq, s32 delay, s32 send_header); -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); -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); -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); -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_iio_stm_ao_set_current(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int val, int val2, long mask); -void neuronspi_spi_iio_sec_ai_read_voltage(struct iio_dev *iio_dev, struct iio_chan_spec const *ch, int *val, int *val2, long mask); -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); -int neuronspi_spi_gpio_di_get(struct spi_device* spi_dev, u32 id); - -/*********************** - * Function structures * - ***********************/ - -// Host driver struct -extern struct spi_driver neuronspi_spi_driver; -extern struct file_operations file_ops; - -static const struct regmap_bus neuronspi_regmap_bus = -{ - .fast_io = 1, - .write = neuronspi_regmap_hw_write, - .gather_write = neuronspi_regmap_hw_gather_write, - .reg_write = neuronspi_regmap_hw_reg_write, - .read = neuronspi_regmap_hw_read, - .reg_read = neuronspi_regmap_hw_reg_read, - .reg_format_endian_default = REGMAP_ENDIAN_NATIVE, - .val_format_endian_default = REGMAP_ENDIAN_NATIVE, - .max_raw_read = 200, // CRC and other overhead not included - .max_raw_write = 200, // CRC and other overhead not included -}; - -static const struct regmap_config neuronspi_regmap_config_default = -{ - .name = "Neuronspi Regmap", - .reg_bits = 16, - .reg_stride = 0, - .pad_bits = 0, - .val_bits = 16, - .max_register = 65535, - .cache_type = REGCACHE_RBTREE, - .use_single_rw = 0, - .can_multi_write = 1, -}; - -static const struct iio_chan_spec neuronspi_stm_ai_chan_spec[] = { - { - .type = IIO_VOLTAGE, - .indexed = 1, - .channel = 0, - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), - .output = 0 - }, - { - .type = IIO_CURRENT, - .indexed = 1, - .channel = 1, - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), - .output = 0 - } -}; - -static const struct iio_chan_spec neuronspi_stm_ao_chan_spec[] = { - { - .type = IIO_VOLTAGE, - .indexed = 1, - .channel = 0, - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), - .output = 1 - }, - { - .type = IIO_CURRENT, - .indexed = 1, - .channel = 1, - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), - .output = 1 - }, - { - .type = IIO_RESISTANCE, - .indexed = 1, - .channel = 2, - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), - .output = 0 - } -}; - -static const struct iio_chan_spec neuronspi_sec_ai_chan_spec[] = { - { - .type = IIO_VOLTAGE, - .indexed = 1, - .channel = 0, - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), - .output = 0 - }, - { - .type = IIO_CURRENT, - .indexed = 1, - .channel = 1, - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), - .output = 0 - }, - { - .type = IIO_RESISTANCE, - .indexed = 1, - .channel = 2, - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), - .output = 0 - } -}; - -static const struct iio_chan_spec neuronspi_sec_ao_chan_spec[] = { - { - .type = IIO_VOLTAGE, - .indexed = 1, - .channel = 0, - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), - .output = 1 - } -}; - -static const struct iio_info neuronspi_stm_ai_info = { - .read_raw = neuronspi_iio_stm_ai_read_raw, - .driver_module = THIS_MODULE, - .attrs = &neuron_stm_ai_group, -}; - -static const struct iio_info neuronspi_stm_ao_info = { - .read_raw = neuronspi_iio_stm_ao_read_raw, - .write_raw = neuronspi_iio_stm_ao_write_raw, - .driver_module = THIS_MODULE, - .attrs = &neuron_stm_ao_group, -}; - -static const struct iio_info neuronspi_sec_ai_info = { - .read_raw = neuronspi_iio_sec_ai_read_raw, - .driver_module = THIS_MODULE, - .attrs = &neuron_sec_ai_group, -}; - -static const struct iio_info neuronspi_sec_ao_info = { - .write_raw = neuronspi_iio_sec_ao_write_raw, - .driver_module = THIS_MODULE, - .attrs = &neuron_sec_ao_group, -}; - -// These defines need to be at the end -#define to_neuronspi_uart_data(p,e) ((container_of((p), struct neuronspi_uart_data, e))) -#define to_neuronspi_port(p,e) ((container_of((p), struct neuronspi_port, e))) -#define to_led_driver(p,e) ((container_of((p), struct neuronspi_led_driver, e))) -#define to_uart_port(p,e) ((container_of((p), struct uart_port, e))) - - -/********************* - * In-line Functions * - *********************/ - -static __always_inline u16 neuronspi_spi_crc(u8* inputstring, s32 length, u16 initval) -{ - s32 i; - u16 result = initval; - for (i=0; i> 8) ^ NEURONSPI_CRC16TABLE[(result ^ inputstring[i]) & 0xff]; - } - 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; - *buf_outp = kzalloc(6, GFP_KERNEL); - *buf_inp = kzalloc(6, GFP_KERNEL); - (*buf_inp)[0] = 0x05; - (*buf_inp)[1] = data; - (*buf_inp)[2] = start & 0xFF; - (*buf_inp)[3] = start >> 8; - crc1 = neuronspi_spi_crc(*buf_inp, 4, 0); - memcpy(&(*buf_inp)[4], &crc1, 2); - return 6; -} - -static __always_inline size_t neuronspi_spi_compose_single_coil_read(u16 start, u8 **buf_inp, u8 **buf_outp) -{ - u16 crc1, crc2; - *buf_outp = kzalloc(14, GFP_KERNEL); - *buf_inp = kzalloc(14, GFP_KERNEL); - (*buf_inp)[0] = 0x01; - (*buf_inp)[1] = 0x06; - (*buf_inp)[2] = start & 0xFF; - (*buf_inp)[3] = start >> 8; - crc1 = neuronspi_spi_crc(*buf_inp, 4, 0); - memcpy(&(*buf_inp)[4], &crc1, 2); - memcpy(&(*buf_inp)[6], *buf_inp, 4); - crc2 = neuronspi_spi_crc(&(*buf_inp)[6], 6, crc1); - memcpy(&(*buf_inp)[12], &crc2, 2); - return 14; -} - -static __always_inline size_t neuronspi_spi_compose_multiple_coil_write(u8 number, u16 start, u8 **buf_inp, u8 **buf_outp, u8 *data) -{ - u16 crc1, crc2; - *buf_outp = kzalloc(12 + NEURONSPI_GET_COIL_READ_PHASE2_BYTE_LENGTH(number), GFP_KERNEL); - *buf_inp = kzalloc(12 + NEURONSPI_GET_COIL_READ_PHASE2_BYTE_LENGTH(number), GFP_KERNEL); - (*buf_inp)[0] = 0x0F; - (*buf_inp)[1] = 4 + NEURONSPI_GET_COIL_READ_PHASE2_BYTE_LENGTH(number); - (*buf_inp)[2] = start & 0xFF; - (*buf_inp)[3] = start >> 8; - crc1 = neuronspi_spi_crc(*buf_inp, 4, 0); - memcpy(&(*buf_inp)[4], &crc1, 2); - memcpy(&(*buf_inp)[6], *buf_inp, 4); - (*buf_inp)[7] = number; - memcpy(&(*buf_inp)[10], data, NEURONSPI_GET_COIL_READ_PHASE2_BYTE_LENGTH(number)); - crc2 = neuronspi_spi_crc(&(*buf_inp)[6], 4 + NEURONSPI_GET_COIL_READ_PHASE2_BYTE_LENGTH(number), crc1); - memcpy(&(*buf_inp)[10 + NEURONSPI_GET_COIL_READ_PHASE2_BYTE_LENGTH(number)], &crc2, 2); - return 12 + NEURONSPI_GET_COIL_READ_PHASE2_BYTE_LENGTH(number); -} - -static __always_inline size_t neuronspi_spi_compose_multiple_coil_read(u8 number, u16 start, u8 **buf_inp, u8 **buf_outp) -{ - u16 crc1, crc2; - *buf_outp = kzalloc(12 + NEURONSPI_GET_COIL_READ_PHASE2_BYTE_LENGTH(number), GFP_KERNEL); - *buf_inp = kzalloc(12 + NEURONSPI_GET_COIL_READ_PHASE2_BYTE_LENGTH(number), GFP_KERNEL); - (*buf_inp)[0] = 0x01; - (*buf_inp)[1] = 4 + NEURONSPI_GET_COIL_READ_PHASE2_BYTE_LENGTH(number); - (*buf_inp)[2] = start & 0xFF; - (*buf_inp)[3] = start >> 8; - crc1 = neuronspi_spi_crc(*buf_inp, 4, 0); - memcpy(&(*buf_inp)[4], &crc1, 2); - memcpy(&(*buf_inp)[6], *buf_inp, 4); - crc2 = neuronspi_spi_crc(&(*buf_inp)[6], 4 + NEURONSPI_GET_COIL_READ_PHASE2_BYTE_LENGTH(number), crc1); - memcpy(&(*buf_inp)[10 + NEURONSPI_GET_COIL_READ_PHASE2_BYTE_LENGTH(number)], &crc2, 2); - return 12 + NEURONSPI_GET_COIL_READ_PHASE2_BYTE_LENGTH(number); -} - -static __always_inline size_t neuronspi_spi_compose_single_register_write(u16 start, u8 **buf_inp, u8 **buf_outp, u16 data) -{ - u16 crc1, crc2; - *buf_outp = kzalloc(14, GFP_KERNEL); - *buf_inp = kzalloc(14, GFP_KERNEL); - (*buf_inp)[0] = 0x06; - (*buf_inp)[1] = 0x06; - (*buf_inp)[2] = start & 0xFF; - (*buf_inp)[3] = start >> 8; - printk(KERN_INFO "NEURONSPI: COMPOSE SINGLE WRITE DATA: %x\n", data); - crc1 = neuronspi_spi_crc(*buf_inp, 4, 0); - memcpy(&(*buf_inp)[4], &crc1, 2); - memcpy(&(*buf_inp)[6], *buf_inp, 4); - (*buf_inp)[7] = 0x01; - memcpy(&(*buf_inp)[10], &data, 2); - crc2 = neuronspi_spi_crc(&(*buf_inp)[6], 6, crc1); - memcpy(&(*buf_inp)[12], &crc2, 2); - return 14; -} - -static __always_inline size_t neuronspi_spi_compose_single_register_read(u16 start, u8 **buf_inp, u8 **buf_outp) -{ - u16 crc1, crc2; - *buf_outp = kzalloc(14, GFP_KERNEL); - *buf_inp = kzalloc(14, GFP_KERNEL); - (*buf_inp)[0] = 0x03; - (*buf_inp)[1] = 0x06; - (*buf_inp)[2] = start & 0xFF; - (*buf_inp)[3] = start >> 8; - crc1 = neuronspi_spi_crc(*buf_inp, 4, 0); - memcpy(&(*buf_inp)[4], &crc1, 2); - memcpy(&(*buf_inp)[6], *buf_inp, 4); - (*buf_inp)[7] = 0x01; - crc2 = neuronspi_spi_crc(&(*buf_inp)[6], 6, crc1); - memcpy(&(*buf_inp)[12], &crc2, 2); - return 14; -} - -static __always_inline size_t neuronspi_spi_compose_multiple_register_write(u8 number, u16 start, u8 **buf_inp, u8 **buf_outp, u8 *data) -{ - u16 crc1, crc2; - *buf_outp = kzalloc(12 + (number * 2), GFP_KERNEL); - *buf_inp = kzalloc(12 + (number * 2), GFP_KERNEL); - (*buf_inp)[0] = 0x10; - (*buf_inp)[1] = 4 + (number * 2); - (*buf_inp)[2] = start & 0xFF; - (*buf_inp)[3] = start >> 8; - crc1 = neuronspi_spi_crc(*buf_inp, 4, 0); - memcpy(&(*buf_inp)[4], &crc1, 2); - memcpy(&(*buf_inp)[6], *buf_inp, 4); - (*buf_inp)[7] = number; - memcpy(&(*buf_inp)[10], data, number * 2); - crc2 = neuronspi_spi_crc(&(*buf_inp)[6], 4 + (number * 2), crc1); - memcpy(&(*buf_inp)[10 + (number * 2)], &crc2, 2); - return 12 + (number * 2); -} - -static __always_inline size_t neuronspi_spi_compose_multiple_register_read(u8 number, u16 start, u8 **buf_inp, u8 **buf_outp) -{ - u16 crc1, crc2; - *buf_outp = kzalloc(12 + (number * 2), GFP_KERNEL); - *buf_inp = kzalloc(12 + (number * 2), GFP_KERNEL); - (*buf_inp)[0] = 0x03; - (*buf_inp)[1] = 4 + (number * 2); - (*buf_inp)[2] = start & 0xFF; - (*buf_inp)[3] = start >> 8; - crc1 = neuronspi_spi_crc(*buf_inp, 4, 0); - memcpy(&(*buf_inp)[4], &crc1, 2); - memcpy(&(*buf_inp)[6], *buf_inp, 4); - (*buf_inp)[7] = number; - crc2 = neuronspi_spi_crc(&(*buf_inp)[6], 4 + (number * 2), crc1); - memcpy(&(*buf_inp)[10 + (number * 2)], &crc2, 2); - return 12 + (number * 2); -} - -#endif /* MODULES_NEURON_SPI_SRC_UNIPI_SPI_H_ */ diff --git a/modules/neuron_spi/src/unipi_sysfs.c b/modules/neuron_spi/src/unipi_sysfs.c deleted file mode 100644 index e82f957..0000000 --- a/modules/neuron_spi/src/unipi_sysfs.c +++ /dev/null @@ -1,1098 +0,0 @@ -/* - * UniPi Neuron tty serial driver - Copyright (C) 2018 UniPi Technologies - * Author: Tomas Knot - * - * Based on the SC16IS7xx driver by Jon Ringle , - * which was in turn based on max310x.c, by Alexander Shiyan - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - */ - -/************ - * Includes * - ************/ - -#include "unipi_sysfs.h" - -/************************ - * Static Functions * - ************************/ - -static ssize_t neuronspi_show_model(struct device *dev, struct device_attribute *attr, char *buf) -{ - ssize_t ret = 0; - if (neuronspi_model_id != -1) { - ret = scnprintf(buf, 255, "%s\n", NEURONSPI_MODELTABLE[neuronspi_model_id].model_name); - } - return ret; -} - -static ssize_t neuronspi_show_eeprom(struct device *dev, struct device_attribute *attr, char *buf) -{ - ssize_t ret = 0; - if (neuronspi_model_id != -1) { - ret = scnprintf(buf, 255, "%s\n", NEURONSPI_MODELTABLE[neuronspi_model_id].eeprom_name); - } - return ret; -} - -static ssize_t neuronspi_spi_show_serial(struct device *dev, struct device_attribute *attr, char *buf) -{ - ssize_t ret = 0; - u32 val[2] = {0, 0}; - struct neuronspi_driver_data *n_spi; - struct platform_device *plat = to_platform_device(dev); - n_spi = platform_get_drvdata(plat); - if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) { - regmap_read(n_spi->reg_map, n_spi->regstart_table->sys_serial_num, val); - regmap_read(n_spi->reg_map, n_spi->regstart_table->sys_serial_num + 1, &(val[1])); - ret = scnprintf(buf, 255, "%d\n", val[0]); - } - return ret; -} - -static ssize_t neuronspi_spi_show_hw_version(struct device *dev, struct device_attribute *attr, char *buf) -{ - ssize_t ret = 0; - u32 val = 0; - struct neuronspi_driver_data *n_spi; - struct platform_device *plat = to_platform_device(dev); - n_spi = platform_get_drvdata(plat); - if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) { - regmap_read(n_spi->reg_map, n_spi->regstart_table->sys_hw_ver, &val); - ret = scnprintf(buf, 255, "%x.%x\n", (val & 0xF0) >> 4, val & 0xF); - } - return ret; -} - -static ssize_t neuronspi_spi_show_hw_flash_version(struct device *dev, struct device_attribute *attr, char *buf) -{ - ssize_t ret = 0; - u32 val = 0; - struct neuronspi_driver_data *n_spi; - struct platform_device *plat = to_platform_device(dev); - n_spi = platform_get_drvdata(plat); - if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) { - regmap_read(n_spi->reg_map, n_spi->regstart_table->sys_hw_flash_ver, &val); - ret = scnprintf(buf, 255, "%x.%x\n", (val & 0xF0) >> 4, val & 0xF); - } - return ret; -} - -static ssize_t neuronspi_spi_show_fw_version(struct device *dev, struct device_attribute *attr, char *buf) -{ - ssize_t ret = 0; - u32 val = 0; - struct neuronspi_driver_data *n_spi; - struct platform_device *plat = to_platform_device(dev); - n_spi = platform_get_drvdata(plat); - if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) { - regmap_read(n_spi->reg_map, n_spi->regstart_table->sys_sw_ver, &val); - ret = scnprintf(buf, 255, "%x.%x%x\n", (val & 0xF00) >> 8, (val & 0xF0) >> 4, val & 0xF); - } - return ret; -} - -static ssize_t neuronspi_spi_show_uart_queue_length(struct device *dev, struct device_attribute *attr, char *buf) -{ - ssize_t ret = 0; - u32 val = 0; - struct neuronspi_driver_data *n_spi; - struct platform_device *plat = to_platform_device(dev); - n_spi = platform_get_drvdata(plat); - if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map && n_spi->regstart_table->uart_queue_reg) { - regmap_read(n_spi->reg_map, n_spi->regstart_table->uart_queue_reg, &val); - ret = scnprintf(buf, 255, "%d\n", val); - } - return ret; -} - -static ssize_t neuronspi_spi_show_uart_config(struct device *dev, struct device_attribute *attr, char *buf) -{ - ssize_t ret = 0; - u32 val = 0; - struct neuronspi_driver_data *n_spi; - struct platform_device *plat = to_platform_device(dev); - n_spi = platform_get_drvdata(plat); - if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map && n_spi->regstart_table->uart_conf_reg) { - regmap_read(n_spi->reg_map, n_spi->regstart_table->uart_conf_reg, &val); - ret = scnprintf(buf, 255, "%x\n", val); - } - return ret; -} - -static ssize_t neuronspi_spi_store_uart_config(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) -{ - ssize_t err = 0; - unsigned int val = 0; - struct neuronspi_driver_data *n_spi; - struct platform_device *plat = to_platform_device(dev); - n_spi = platform_get_drvdata(plat); - err = kstrtouint(buf, 0, &val); - if (err < 0) goto err_end; - if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map && n_spi->regstart_table->uart_conf_reg) { - regmap_write(n_spi->reg_map, n_spi->regstart_table->uart_conf_reg, val); - } -err_end: - return count; -} - -static ssize_t neuronspi_spi_show_watchdog_status(struct device *dev, struct device_attribute *attr, char *buf) -{ - ssize_t ret = 0; - u32 val = 0; - struct neuronspi_driver_data *n_spi; - struct platform_device *plat = to_platform_device(dev); - n_spi = platform_get_drvdata(plat); - if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) { - regmap_read(n_spi->reg_map, n_spi->regstart_table->wd_val_reg, &val); - ret = scnprintf(buf, 255, "%x\n", val); - } - return ret; -} - -static ssize_t neuronspi_spi_store_watchdog_status(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) -{ - ssize_t err = 0; - unsigned int val = 0; - struct neuronspi_driver_data *n_spi; - struct platform_device *plat = to_platform_device(dev); - n_spi = platform_get_drvdata(plat); - err = kstrtouint(buf, 0, &val); - if (err < 0) goto err_end; - if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) { - regmap_write(n_spi->reg_map, n_spi->regstart_table->wd_val_reg, val); - } -err_end: - return count; -} - -static ssize_t neuronspi_spi_show_watchdog_timeout(struct device *dev, struct device_attribute *attr, char *buf) -{ - ssize_t ret = 0; - u32 val = 0; - struct neuronspi_driver_data *n_spi; - struct platform_device *plat = to_platform_device(dev); - n_spi = platform_get_drvdata(plat); - if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) { - regmap_read(n_spi->reg_map, n_spi->regstart_table->wd_timeout_reg, &val); - ret = scnprintf(buf, 255, "%d\n", val); - } - return ret; -} - -static ssize_t neuronspi_spi_store_watchdog_timeout(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) -{ - ssize_t err = 0; - unsigned int val = 0; - struct neuronspi_driver_data *n_spi; - struct platform_device *plat = to_platform_device(dev); - n_spi = platform_get_drvdata(plat); - err = kstrtouint(buf, 0, &val); - if (err < 0) goto err_end; - if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) { - regmap_write(n_spi->reg_map, n_spi->regstart_table->wd_timeout_reg, val); - } -err_end: - return count; -} - -static ssize_t neuronspi_spi_gpio_show_pwm_presc(struct device *dev, struct device_attribute *attr, char *buf) -{ - ssize_t ret = 0; - u32 val = 0; - struct neuronspi_do_driver *n_do; - struct neuronspi_driver_data *n_spi; - struct platform_device *plat = to_platform_device(dev); - n_do = platform_get_drvdata(plat); - n_spi = spi_get_drvdata(n_do->spi); - if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) { - regmap_read(n_spi->reg_map, n_spi->regstart_table->do_pwm_ps_reg, &val); - ret = scnprintf(buf, 255, "%d\n", val); - } - return ret; -} - -static ssize_t neuronspi_spi_gpio_store_pwm_presc(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) -{ - ssize_t err = 0; - unsigned int val = 0; - struct neuronspi_do_driver *n_do; - struct neuronspi_driver_data *n_spi; - struct platform_device *plat = to_platform_device(dev); - n_do = platform_get_drvdata(plat); - n_spi = spi_get_drvdata(n_do->spi); - err = kstrtouint(buf, 0, &val); - if (err < 0) goto err_end; - if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) { - regmap_write(n_spi->reg_map, n_spi->regstart_table->do_pwm_ps_reg, val); - } -err_end: - return count; -} - -static ssize_t neuronspi_spi_gpio_show_pwm_freq(struct device *dev, struct device_attribute *attr, char *buf) -{ - ssize_t ret = 0; - u32 val = 0; - struct neuronspi_do_driver *n_do; - struct neuronspi_driver_data *n_spi; - struct platform_device *plat = to_platform_device(dev); - n_do = platform_get_drvdata(plat); - n_spi = spi_get_drvdata(n_do->spi); - if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) { - regmap_read(n_spi->reg_map, n_spi->regstart_table->do_pwm_c_reg, &val); - ret = scnprintf(buf, 255, "%d\n", val); - } - return ret; -} - -static ssize_t neuronspi_spi_gpio_store_pwm_freq(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) -{ - ssize_t err = 0; - unsigned int val = 0; - struct neuronspi_do_driver *n_do; - struct neuronspi_driver_data *n_spi; - struct platform_device *plat = to_platform_device(dev); - n_do = platform_get_drvdata(plat); - n_spi = spi_get_drvdata(n_do->spi); - err = kstrtouint(buf, 0, &val); - if (err < 0) goto err_end; - if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) { - regmap_write(n_spi->reg_map, n_spi->regstart_table->do_pwm_c_reg, val); - } -err_end: - return count; -} - -static ssize_t neuronspi_spi_gpio_show_pwm_cycle(struct device *dev, struct device_attribute *attr, char *buf) -{ - ssize_t ret = 0; - u32 val = 0; - struct neuronspi_do_driver *n_do; - struct neuronspi_driver_data *n_spi; - struct platform_device *plat = to_platform_device(dev); - n_do = platform_get_drvdata(plat); - n_spi = spi_get_drvdata(n_do->spi); - if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) { - regmap_read(n_spi->reg_map, n_spi->regstart_table->do_pwm_reg + n_do->do_index, &val); - ret = scnprintf(buf, 255, "%d\n", val); - } - return ret; -} - -static ssize_t neuronspi_spi_gpio_store_pwm_cycle(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) -{ - ssize_t err = 0; - unsigned int val = 0; - struct neuronspi_do_driver *n_do; - struct neuronspi_driver_data *n_spi; - struct platform_device *plat = to_platform_device(dev); - n_do = platform_get_drvdata(plat); - n_spi = spi_get_drvdata(n_do->spi); - err = kstrtouint(buf, 0, &val); - if (err < 0) goto err_end; - if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) { - regmap_write(n_spi->reg_map, n_spi->regstart_table->do_pwm_reg + n_do->do_index, val); - } -err_end: - return count; -} - -static ssize_t neuronspi_spi_gpio_di_show_counter(struct device *dev, struct device_attribute *attr, char *buf) -{ - ssize_t ret = 0; - u32 val = 0; - struct neuronspi_di_driver *n_di; - struct neuronspi_driver_data *n_spi; - struct platform_device *plat = to_platform_device(dev); - n_di = platform_get_drvdata(plat); - n_spi = spi_get_drvdata(n_di->spi); - if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) { - regmap_read(n_spi->reg_map, n_spi->regstart_table->di_counter_reg + (2 * n_di->di_index), &val); - ret = scnprintf(buf, 255, "%d\n", val); - } - return ret; -} - -static ssize_t neuronspi_spi_gpio_di_store_counter(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) -{ - ssize_t err = 0; - unsigned int val = 0; - struct neuronspi_di_driver *n_di; - struct neuronspi_driver_data *n_spi; - struct platform_device *plat = to_platform_device(dev); - n_di = platform_get_drvdata(plat); - n_spi = spi_get_drvdata(n_di->spi); - err = kstrtouint(buf, 0, &val); - if (err < 0) goto err_end; - if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) { - regmap_write(n_spi->reg_map, n_spi->regstart_table->di_counter_reg + (2 * n_di->di_index), val); - } -err_end: - return count; -} - -static ssize_t neuronspi_spi_gpio_di_show_debounce(struct device *dev, struct device_attribute *attr, char *buf) -{ - ssize_t ret = 0; - u32 val = 0; - struct neuronspi_di_driver *n_di; - struct neuronspi_driver_data *n_spi; - struct platform_device *plat = to_platform_device(dev); - n_di = platform_get_drvdata(plat); - n_spi = spi_get_drvdata(n_di->spi); - if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map && n_spi->features && n_spi->features->di_count > n_di->di_index) { - regmap_read(n_spi->reg_map, n_spi->regstart_table->di_deboun_reg + n_di->di_index, &val); - ret = scnprintf(buf, 255, "%d\n", val); - } - return ret; -} - -static ssize_t neuronspi_spi_gpio_di_store_debounce(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) -{ - ssize_t err = 0; - unsigned int val = 0; - struct neuronspi_di_driver *n_di; - struct neuronspi_driver_data *n_spi; - struct platform_device *plat = to_platform_device(dev); - n_di = platform_get_drvdata(plat); - n_spi = spi_get_drvdata(n_di->spi); - err = kstrtouint(buf, 0, &val); - if (err < 0) goto err_end; - if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map && n_spi->features && n_spi->features->di_count > n_di->di_index) { - regmap_write(n_spi->reg_map, n_spi->regstart_table->di_deboun_reg + n_di->di_index, val); - } -err_end: - return count; -} - -static ssize_t neuronspi_spi_gpio_di_show_value(struct device *dev, struct device_attribute *attr, char *buf) -{ - ssize_t ret = 0; - int val; - struct neuronspi_di_driver *n_di; - struct neuronspi_driver_data *n_spi; - struct platform_device *plat = to_platform_device(dev); - n_di = platform_get_drvdata(plat); - n_spi = spi_get_drvdata(n_di->spi); - if (n_spi && n_spi->combination_id != -1 && n_spi->features && n_spi->features->di_count > n_di->di_index) { - regmap_read(n_spi->reg_map, n_spi->regstart_table->di_val_reg + (n_di->di_index / 16), &val); - val &= 0x1 << (n_di->di_index % 15); - val = val >> (n_di->di_index % 15); - ret = scnprintf(buf, 255, "%d\n", val); - } - return ret; -} - -static ssize_t neuronspi_spi_gpio_do_show_value(struct device *dev, struct device_attribute *attr, char *buf) -{ - ssize_t ret = 0; - int val; - struct neuronspi_do_driver *n_do; - struct neuronspi_driver_data *n_spi; - struct platform_device *plat = to_platform_device(dev); - n_do = platform_get_drvdata(plat); - n_spi = spi_get_drvdata(n_do->spi); - if (n_spi && n_spi->combination_id != -1 && n_spi->features && n_spi->features->do_count > n_do->do_index) { - regmap_read(n_spi->reg_map, n_spi->regstart_table->do_val_reg + (n_do->do_index / 16), &val); - val &= 0x1 << (n_do->do_index % 15); - val = val >> (n_do->do_index % 15); - ret = scnprintf(buf, 255, "%d\n", val); - } - return ret; -} - -static ssize_t neuronspi_spi_gpio_do_store_value(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) -{ - ssize_t err = 0; - int inp = 0; - unsigned int val; - struct neuronspi_do_driver *n_do; - struct neuronspi_driver_data *n_spi; - struct platform_device *plat = to_platform_device(dev); - n_do = platform_get_drvdata(plat); - n_spi = spi_get_drvdata(n_do->spi); - err = kstrtoint(buf, 0, &inp); - if (err < 0) goto err_end; - if (inp > 1 || inp < 0) { - goto err_end; - } - if (n_spi && n_spi->combination_id != -1 && n_spi->features && n_spi->features->do_count > n_do->do_index) { - regmap_read(n_spi->reg_map, n_spi->regstart_table->do_val_reg + (n_do->do_index / 16), &val); - val &= ~(0x1 << (n_do->do_index % 15)); - val |= inp << (n_do->do_index % 15); - regmap_write(n_spi->reg_map, n_spi->regstart_table->do_val_reg + (n_do->do_index / 16), val); - } -err_end: - return count; -} - -static ssize_t neuronspi_spi_gpio_ro_show_value(struct device *dev, struct device_attribute *attr, char *buf) -{ - ssize_t ret = 0; - int val; - struct neuronspi_ro_driver *n_ro; - struct neuronspi_driver_data *n_spi; - struct platform_device *plat = to_platform_device(dev); - n_ro = platform_get_drvdata(plat); - n_spi = spi_get_drvdata(n_ro->spi); - if (n_spi && n_spi->combination_id != -1 && n_spi->features && n_spi->features->ro_count > n_ro->ro_index) { - regmap_read(n_spi->reg_map, n_spi->regstart_table->ro_val_reg + (n_ro->ro_index / 16), &val); - val &= 0x1 << (n_ro->ro_index % 15); - val = val >> (n_ro->ro_index % 15); - ret = scnprintf(buf, 255, "%d\n", val); - } - return ret; -} - -static ssize_t neuronspi_spi_gpio_ro_store_value(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) -{ - ssize_t err = 0; - int inp = 0; - unsigned int val; - struct neuronspi_ro_driver *n_ro; - struct neuronspi_driver_data *n_spi; - struct platform_device *plat = to_platform_device(dev); - n_ro = platform_get_drvdata(plat); - n_spi = spi_get_drvdata(n_ro->spi); - err = kstrtoint(buf, 0, &inp); - if (err < 0) goto err_end; - if (inp > 1 || inp < 0) { - goto err_end; - } - if (n_spi && n_spi->combination_id != -1 && n_spi->features && n_spi->features->ro_count > n_ro->ro_index) { - regmap_read(n_spi->reg_map, n_spi->regstart_table->ro_val_reg + (n_ro->ro_index / 16), &val); - val &= ~(0x1 << (n_ro->ro_index % 15)); - val |= inp << (n_ro->ro_index % 15); - regmap_write(n_spi->reg_map, n_spi->regstart_table->ro_val_reg + (n_ro->ro_index / 16), val); - } -err_end: - return count; -} - - -static ssize_t neuronspi_spi_gpio_show_ds_enable(struct device *dev, struct device_attribute *attr, char *buf) -{ - ssize_t ret = 0; - int val; - struct neuronspi_di_driver *n_di; - struct neuronspi_driver_data *n_spi; - struct platform_device *plat = to_platform_device(dev); - n_di = platform_get_drvdata(plat); - n_spi = spi_get_drvdata(n_di->spi); - if (n_spi && n_spi->combination_id != -1 && n_spi->features && n_spi->features->ds_count) { - regmap_read(n_spi->reg_map, n_spi->regstart_table->di_direct_reg + (n_di->di_index / 16), &val); - val &= 0x1 << (n_di->di_index % 15); - val = val >> (n_di->di_index % 15); - ret = scnprintf(buf, 255, "%d\n", val); - } - return ret; -} - -static ssize_t neuronspi_spi_gpio_show_ds_toggle(struct device *dev, struct device_attribute *attr, char *buf) -{ - ssize_t ret = 0; - int val; - struct neuronspi_di_driver *n_di; - struct neuronspi_driver_data *n_spi; - struct platform_device *plat = to_platform_device(dev); - n_di = platform_get_drvdata(plat); - n_spi = spi_get_drvdata(n_di->spi); - if (n_spi && n_spi->combination_id != -1 && n_spi->features && n_spi->features->ds_count) { - regmap_read(n_spi->reg_map, n_spi->regstart_table->di_toggle_reg + (n_di->di_index / 16), &val); - val &= 0x1 << (n_di->di_index % 15); - val = val >> (n_di->di_index % 15); - ret = scnprintf(buf, 255, "%d\n", val); - } - return ret; -} - -static ssize_t neuronspi_spi_gpio_show_ds_polarity(struct device *dev, struct device_attribute *attr, char *buf) -{ - ssize_t ret = 0; - int val; - struct neuronspi_di_driver *n_di; - struct neuronspi_driver_data *n_spi; - struct platform_device *plat = to_platform_device(dev); - n_di = platform_get_drvdata(plat); - n_spi = spi_get_drvdata(n_di->spi); - if (n_spi && n_spi->combination_id != -1 && n_spi->features && n_spi->features->ds_count) { - regmap_read(n_spi->reg_map, n_spi->regstart_table->di_polar_reg + (n_di->di_index / 16), &val); - val &= 0x1 << (n_di->di_index % 15); - val = val >> (n_di->di_index % 15); - ret = scnprintf(buf, 255, "%d\n", val); - } - return ret; -} - -static ssize_t neuronspi_spi_gpio_store_ds_enable(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) -{ - ssize_t err = 0; - int inp = 0; - unsigned int val; - struct neuronspi_di_driver *n_di; - struct neuronspi_driver_data *n_spi; - struct platform_device *plat = to_platform_device(dev); - n_di = platform_get_drvdata(plat); - n_spi = spi_get_drvdata(n_di->spi); - err = kstrtoint(buf, 0, &inp); - if (err < 0) goto err_end; - if (inp > 1 || inp < 0) { - goto err_end; - } - if (n_spi && n_spi->combination_id != -1 && n_spi->features && n_spi->features->ds_count) { - regmap_read(n_spi->reg_map, n_spi->regstart_table->di_direct_reg + (n_di->di_index / 16), &val); - val &= ~(0x1 << (n_di->di_index % 15)); - val |= inp << (n_di->di_index % 15); - regmap_write(n_spi->reg_map, n_spi->regstart_table->di_direct_reg + (n_di->di_index / 16), val); - } -err_end: - return count; -} - -static ssize_t neuronspi_spi_gpio_store_ds_toggle(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) -{ - ssize_t err = 0; - int inp = 0; - unsigned int val; - struct neuronspi_di_driver *n_di; - struct neuronspi_driver_data *n_spi; - struct platform_device *plat = to_platform_device(dev); - n_di = platform_get_drvdata(plat); - n_spi = spi_get_drvdata(n_di->spi); - err = kstrtoint(buf, 0, &inp); - if (err < 0) goto err_end; - if (inp > 1 || inp < 0) { - goto err_end; - } - if (n_spi && n_spi->combination_id != -1 && n_spi->features && n_spi->features->ds_count) { - regmap_read(n_spi->reg_map, n_spi->regstart_table->di_toggle_reg + (n_di->di_index / 16), &val); - val &= ~(0x1 << (n_di->di_index % 15)); - val |= inp << (n_di->di_index % 15); - regmap_write(n_spi->reg_map, n_spi->regstart_table->di_toggle_reg + (n_di->di_index / 16), val); - } -err_end: - return count; -} - -static ssize_t neuronspi_spi_gpio_store_ds_polarity(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) -{ - ssize_t err = 0; - int inp = 0; - unsigned int val; - struct neuronspi_di_driver *n_di; - struct neuronspi_driver_data *n_spi; - struct platform_device *plat = to_platform_device(dev); - n_di = platform_get_drvdata(plat); - n_spi = spi_get_drvdata(n_di->spi); - err = kstrtoint(buf, 0, &inp); - if (err < 0) goto err_end; - if (inp > 1 || inp < 0) { - goto err_end; - } - if (n_spi && n_spi->combination_id != -1 && n_spi->features && n_spi->features->ds_count) { - regmap_read(n_spi->reg_map, n_spi->regstart_table->di_polar_reg + (n_di->di_index / 16), &val); - val &= ~(0x1 << (n_di->di_index % 15)); - val |= inp << (n_di->di_index % 15); - regmap_write(n_spi->reg_map, n_spi->regstart_table->di_polar_reg + (n_di->di_index / 16), val); - } -err_end: - return count; -} - -static ssize_t neuronspi_show_regmap(struct device *dev, struct device_attribute *attr, char *buf) -{ - ssize_t ret = 0; - u32 val = 0; - struct neuronspi_driver_data *n_spi; - struct platform_device *plat = to_platform_device(dev); - n_spi = platform_get_drvdata(plat); - if (n_spi && n_spi->reg_map) { - spin_lock(&n_spi->sysfs_regmap_lock); - regmap_read(n_spi->reg_map, n_spi->sysfs_regmap_target, &val); - ret = scnprintf(buf, 255, "%x\n", val); - spin_unlock(&n_spi->sysfs_regmap_lock); - } - return ret; -} - -static ssize_t neuronspi_store_regmap(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) -{ - ssize_t err = 0; - unsigned int val = 0; - struct neuronspi_driver_data *n_spi; - struct platform_device *plat = to_platform_device(dev); - n_spi = platform_get_drvdata(plat); - err = kstrtouint(buf, 0, &val); - if (err < 0) goto err_end; - if (n_spi && n_spi->reg_map && val < 65536) { - spin_lock(&n_spi->sysfs_regmap_lock); - n_spi->sysfs_regmap_target = val; - spin_unlock(&n_spi->sysfs_regmap_lock); - } -err_end: - return count; -} - -static ssize_t neuronspi_spi_show_board(struct device *dev, struct device_attribute *attr, char *buf) -{ - ssize_t ret = 0; - struct neuronspi_driver_data *n_spi; - struct platform_device *plat = to_platform_device(dev); - n_spi = platform_get_drvdata(plat); - if (n_spi->combination_id != -1 && n_spi->combination_id < NEURONSPI_BOARDTABLE_LEN) { - ret = scnprintf(buf, 255, "%s\n", NEURONSPI_BOARDTABLE[n_spi->combination_id].definition->combination_name); - } - return ret; -} - -static ssize_t neuronspi_spi_show_lboard_id(struct device *dev, struct device_attribute *attr, char *buf) -{ - ssize_t ret = 0; - struct neuronspi_driver_data *n_spi; - struct platform_device *plat = to_platform_device(dev); - n_spi = platform_get_drvdata(plat); - if (n_spi->combination_id != -1 && n_spi->combination_id < NEURONSPI_BOARDTABLE_LEN) { - ret = scnprintf(buf, 255, "%d\n", NEURONSPI_BOARDTABLE[n_spi->combination_id].definition->lower_board_id); - } - return ret; -} - -static ssize_t neuronspi_spi_show_uboard_id(struct device *dev, struct device_attribute *attr, char *buf) -{ - ssize_t ret = 0; - struct neuronspi_driver_data *n_spi; - struct platform_device *plat = to_platform_device(dev); - n_spi = platform_get_drvdata(plat); - if (n_spi->combination_id != -1 && n_spi->combination_id < NEURONSPI_BOARDTABLE_LEN) { - ret = scnprintf(buf, 255, "%d\n", NEURONSPI_BOARDTABLE[n_spi->combination_id].definition->upper_board_id); - } - return ret; -} - -static ssize_t neuronspi_spi_gpio_show_do_prefix(struct device *dev, struct device_attribute *attr, char *buf) -{ - ssize_t ret = 0; - struct neuronspi_do_driver *n_do; - struct neuronspi_driver_data *n_spi; - struct platform_device *plat = to_platform_device(dev); - n_do = platform_get_drvdata(plat); - n_spi = spi_get_drvdata(n_do->spi); - if (n_spi->features && n_spi->features->do_count > 0 && n_spi->do_driver) { - ret = scnprintf(buf, 255, "%s_%d\n", n_spi->do_driver[n_do->do_index]->gpio_c.label, n_spi->neuron_index + 1); - } - return ret; -} - -static ssize_t neuronspi_spi_gpio_show_di_prefix(struct device *dev, struct device_attribute *attr, char *buf) -{ - ssize_t ret = 0; - struct neuronspi_di_driver *n_di; - struct neuronspi_driver_data *n_spi; - struct platform_device *plat = to_platform_device(dev); - n_di = platform_get_drvdata(plat); - n_spi = spi_get_drvdata(n_di->spi); - if (n_spi->features && n_spi->features->di_count > 0 && n_spi->di_driver) { - ret = scnprintf(buf, 255, "%s_%d\n", n_spi->di_driver[n_di->di_index]->gpio_c.label, n_spi->neuron_index + 1); - } - return ret; -} - -static ssize_t neuronspi_spi_gpio_show_ro_prefix(struct device *dev, struct device_attribute *attr, char *buf) -{ - ssize_t ret = 0; - struct neuronspi_ro_driver *n_ro; - struct neuronspi_driver_data *n_spi; - struct platform_device *plat = to_platform_device(dev); - n_ro = platform_get_drvdata(plat); - n_spi = spi_get_drvdata(n_ro->spi); - if (n_spi->features && n_spi->features->ro_count > 0 && n_spi->ro_driver) { - ret = scnprintf(buf, 255, "%s_%d\n", n_spi->ro_driver[n_ro->ro_index]->gpio_c.label, n_spi->neuron_index + 1); - } - return ret; -} - -static ssize_t neuronspi_spi_gpio_show_do_base(struct device *dev, struct device_attribute *attr, char *buf) -{ - ssize_t ret = 0; - struct neuronspi_do_driver *n_do; - struct neuronspi_driver_data *n_spi; - struct platform_device *plat = to_platform_device(dev); - n_do = platform_get_drvdata(plat); - n_spi = spi_get_drvdata(n_do->spi); - if (n_spi->features && n_spi->features->do_count > 0 && n_spi->do_driver) { - ret = scnprintf(buf, 255, "%d\n", n_spi->do_driver[n_do->do_index]->gpio_c.base); - } - return ret; -} - -static ssize_t neuronspi_spi_gpio_show_di_base(struct device *dev, struct device_attribute *attr, char *buf) -{ - ssize_t ret = 0; - struct neuronspi_di_driver *n_di; - struct neuronspi_driver_data *n_spi; - struct platform_device *plat = to_platform_device(dev); - n_di = platform_get_drvdata(plat); - n_spi = spi_get_drvdata(n_di->spi); - if (n_spi->features && n_spi->features->di_count > 0 && n_spi->di_driver) { - ret = scnprintf(buf, 255, "%d\n", n_spi->di_driver[n_di->di_index]->gpio_c.base); - } - return ret; -} - -static ssize_t neuronspi_spi_gpio_show_ro_base(struct device *dev, struct device_attribute *attr, char *buf) -{ - ssize_t ret = 0; - struct neuronspi_ro_driver *n_ro; - struct neuronspi_driver_data *n_spi; - struct platform_device *plat = to_platform_device(dev); - n_ro = platform_get_drvdata(plat); - n_spi = spi_get_drvdata(n_ro->spi); - if (n_spi->features && n_spi->features->ro_count > 0 && n_spi->ro_driver) { - ret = scnprintf(buf, 255, "%d\n", n_spi->ro_driver[n_ro->ro_index]->gpio_c.base); - } - return ret; -} - -static ssize_t neuronspi_spi_gpio_show_do_count(struct device *dev, struct device_attribute *attr, char *buf) -{ - ssize_t ret = 0; - struct neuronspi_do_driver *n_do; - struct neuronspi_driver_data *n_spi; - struct platform_device *plat = to_platform_device(dev); - n_do = platform_get_drvdata(plat); - n_spi = spi_get_drvdata(n_do->spi); - if (n_spi->features && n_spi->features->do_count > 0 && n_spi->do_driver) { - ret = scnprintf(buf, 255, "%d\n", n_spi->do_driver[n_do->do_index]->gpio_c.ngpio); - } - return ret; -} - -static ssize_t neuronspi_spi_gpio_show_di_count(struct device *dev, struct device_attribute *attr, char *buf) -{ - ssize_t ret = 0; - struct neuronspi_di_driver *n_di; - struct neuronspi_driver_data *n_spi; - struct platform_device *plat = to_platform_device(dev); - n_di = platform_get_drvdata(plat); - n_spi = spi_get_drvdata(n_di->spi); - if (n_spi->features && n_spi->features->di_count > 0 && n_spi->di_driver) { - ret = scnprintf(buf, 255, "%d\n", n_spi->di_driver[n_di->di_index]->gpio_c.ngpio); - } - return ret; -} - -static ssize_t neuronspi_spi_gpio_show_ro_count(struct device *dev, struct device_attribute *attr, char *buf) -{ - ssize_t ret = 0; - struct neuronspi_ro_driver *n_ro; - struct neuronspi_driver_data *n_spi; - struct platform_device *plat = to_platform_device(dev); - n_ro = platform_get_drvdata(plat); - n_spi = spi_get_drvdata(n_ro->spi); - if (n_spi->features && n_spi->features->ro_count > 0 && n_spi->ro_driver) { - ret = scnprintf(buf, 255, "%d\n", n_spi->ro_driver[n_ro->ro_index]->gpio_c.ngpio); - } - return ret; -} - - -static ssize_t neuronspi_iio_show_primary_ai_mode(struct device *dev, struct device_attribute *attr, char *buf) -{ - int ret = 0; - unsigned int val = 0; - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct neuronspi_stm_ai_data *ai_data = iio_priv(indio_dev); - struct spi_device *spi = ai_data->parent; - struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi); - regmap_read(n_spi->reg_map, n_spi->regstart_table->stm_ai_mode_reg, &val); - ret = scnprintf(buf, 255, "%d\n", val); - return ret; -} - -static ssize_t neuronspi_iio_store_primary_ai_mode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) -{ - ssize_t err = 0; - unsigned int val = 0; - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct neuronspi_stm_ai_data *ai_data = iio_priv(indio_dev); - struct spi_device *spi = ai_data->parent; - struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi); - err = kstrtouint(buf, 0, &val); - if (err < 0) goto err_end; - if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) { - regmap_write(n_spi->reg_map, n_spi->regstart_table->stm_ai_mode_reg, val); - } -err_end: - return count; -} - -static ssize_t neuronspi_iio_show_primary_ao_mode(struct device *dev, struct device_attribute *attr, char *buf) -{ - int ret = 0; - unsigned int val = 0; - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct neuronspi_stm_ao_data *ao_data = iio_priv(indio_dev); - struct spi_device *spi = ao_data->parent; - struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi); - regmap_read(n_spi->reg_map, n_spi->regstart_table->stm_ao_mode_reg, &val); - ret = scnprintf(buf, 255, "%d\n", val); - return ret; -} - -static ssize_t neuronspi_iio_store_primary_ao_mode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) -{ - ssize_t err = 0; - unsigned int val = 0; - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct neuronspi_stm_ao_data *ao_data = iio_priv(indio_dev); - struct spi_device *spi = ao_data->parent; - struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi); - err = kstrtouint(buf, 0, &val); - if (err < 0) goto err_end; - if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) { - regmap_write(n_spi->reg_map, n_spi->regstart_table->stm_ao_mode_reg, val); - } -err_end: - return count; -} - -static ssize_t neuronspi_iio_show_secondary_ai_mode(struct device *dev, struct device_attribute *attr, char *buf) -{ - int ret = 0; - unsigned int val = 0; - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct neuronspi_sec_ai_data *ai_data = iio_priv(indio_dev); - struct spi_device *spi = ai_data->parent; - struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi); - regmap_read(n_spi->reg_map, n_spi->regstart_table->sec_ai_mode_reg + ai_data->index, &val); - ret = scnprintf(buf, 255, "%d\n", val); - return ret; -} -static ssize_t neuronspi_iio_store_secondary_ai_mode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) -{ - ssize_t err = 0; - unsigned int val = 0; - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct neuronspi_sec_ai_data *ai_data = iio_priv(indio_dev); - struct spi_device *spi = ai_data->parent; - struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi); - err = kstrtouint(buf, 0, &val); - if (err < 0) goto err_end; - if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) { - regmap_write(n_spi->reg_map, n_spi->regstart_table->sec_ai_mode_reg + ai_data->index, val); - } -err_end: - return count; -} -static ssize_t neuronspi_iio_show_secondary_ao_mode(struct device *dev, struct device_attribute *attr, char *buf) -{ - int ret = 0; - unsigned int val = 0; - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct neuronspi_sec_ao_data *ao_data = iio_priv(indio_dev); - struct spi_device *spi = ao_data->parent; - struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi); - regmap_read(n_spi->reg_map, n_spi->regstart_table->sec_ao_mode_reg + ao_data->index, &val); - ret = scnprintf(buf, 255, "%d\n", val); - return ret; -} -static ssize_t neuronspi_iio_store_secondary_ao_mode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) -{ - ssize_t err = 0; - unsigned int val = 0; - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct neuronspi_sec_ao_data *ao_data = iio_priv(indio_dev); - struct spi_device *spi = ao_data->parent; - struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi); - err = kstrtouint(buf, 0, &val); - if (err < 0) goto err_end; - if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) { - regmap_write(n_spi->reg_map, n_spi->regstart_table->sec_ao_mode_reg + ao_data->index, val); - } -err_end: - return count; -} - -/********************************** - * Function Structure Definitions * - **********************************/ - -static DEVICE_ATTR(model_name, 0440, neuronspi_show_model, NULL); -static DEVICE_ATTR(sys_eeprom_name, 0440, neuronspi_show_eeprom, NULL); -static DEVICE_ATTR(register_read, 0660, neuronspi_show_regmap, neuronspi_store_regmap); -static DEVICE_ATTR(sys_board_serial, 0440, neuronspi_spi_show_serial, NULL); -static DEVICE_ATTR(sys_board_name, 0440, neuronspi_spi_show_board, NULL); -static DEVICE_ATTR(sys_primary_major_id, 0440, neuronspi_spi_show_lboard_id, NULL); -static DEVICE_ATTR(sys_secondary_major_id, 0440, neuronspi_spi_show_uboard_id, NULL); -static DEVICE_ATTR(sys_primary_minor_id, 0440, neuronspi_spi_show_hw_version, NULL); -static DEVICE_ATTR(sys_secondary_minor_id, 0440, neuronspi_spi_show_hw_flash_version, NULL); -static DEVICE_ATTR(firmware_version, 0440, neuronspi_spi_show_fw_version, NULL); -static DEVICE_ATTR(watchdog_status, 0660, neuronspi_spi_show_watchdog_status, neuronspi_spi_store_watchdog_status); -static DEVICE_ATTR(watchdog_timeout, 0660, neuronspi_spi_show_watchdog_timeout, neuronspi_spi_store_watchdog_timeout); -static DEVICE_ATTR(sys_gpio_do_count, 0440, neuronspi_spi_gpio_show_do_count, NULL); -static DEVICE_ATTR(sys_gpio_do_prefix, 0440, neuronspi_spi_gpio_show_do_prefix, NULL); -static DEVICE_ATTR(sys_gpio_do_base, 0440, neuronspi_spi_gpio_show_do_base, NULL); -static DEVICE_ATTR(sys_gpio_di_count, 0440, neuronspi_spi_gpio_show_di_count, NULL); -static DEVICE_ATTR(sys_gpio_di_prefix, 0440, neuronspi_spi_gpio_show_di_prefix, NULL); -static DEVICE_ATTR(ro_value, 0660, neuronspi_spi_gpio_ro_show_value, neuronspi_spi_gpio_ro_store_value); -static DEVICE_ATTR(do_value, 0660, neuronspi_spi_gpio_do_show_value, neuronspi_spi_gpio_do_store_value); -static DEVICE_ATTR(counter, 0660, neuronspi_spi_gpio_di_show_counter, neuronspi_spi_gpio_di_store_counter); -static DEVICE_ATTR(debounce, 0660, neuronspi_spi_gpio_di_show_debounce, neuronspi_spi_gpio_di_store_debounce); -static DEVICE_ATTR(di_value, 0440, neuronspi_spi_gpio_di_show_value, NULL); -static DEVICE_ATTR(direct_switch_enable, 0660, neuronspi_spi_gpio_show_ds_enable, neuronspi_spi_gpio_store_ds_enable); -static DEVICE_ATTR(direct_switch_toggle, 0660, neuronspi_spi_gpio_show_ds_toggle, neuronspi_spi_gpio_store_ds_toggle); -static DEVICE_ATTR(direct_switch_polarity, 0660, neuronspi_spi_gpio_show_ds_polarity, neuronspi_spi_gpio_store_ds_polarity); -static DEVICE_ATTR(pwm_frequency_cycle, 0660, neuronspi_spi_gpio_show_pwm_freq, neuronspi_spi_gpio_store_pwm_freq); -static DEVICE_ATTR(pwm_prescale, 0660, neuronspi_spi_gpio_show_pwm_presc, neuronspi_spi_gpio_store_pwm_presc); -static DEVICE_ATTR(pwm_duty_cycle, 0660, neuronspi_spi_gpio_show_pwm_cycle, neuronspi_spi_gpio_store_pwm_cycle); -static DEVICE_ATTR(uart_queue_length, 0440, neuronspi_spi_show_uart_queue_length, NULL); -static DEVICE_ATTR(uart_config, 0660, neuronspi_spi_show_uart_config, neuronspi_spi_store_uart_config); -static DEVICE_ATTR(sys_gpio_di_base, 0440, neuronspi_spi_gpio_show_di_base, NULL); -static DEVICE_ATTR(sys_gpio_ro_count, 0440, neuronspi_spi_gpio_show_ro_count, NULL); -static DEVICE_ATTR(sys_gpio_ro_prefix, 0440, neuronspi_spi_gpio_show_ro_prefix, NULL); -static DEVICE_ATTR(sys_gpio_ro_base, 0440, neuronspi_spi_gpio_show_ro_base, NULL); -static DEVICE_ATTR(mode_ai_type_a, 0660, neuronspi_iio_show_primary_ai_mode, neuronspi_iio_store_primary_ai_mode); -static DEVICE_ATTR(mode_ao_type_a, 0660, neuronspi_iio_show_primary_ao_mode, neuronspi_iio_store_primary_ao_mode); -static DEVICE_ATTR(mode_ai_type_b, 0660, neuronspi_iio_show_secondary_ai_mode, neuronspi_iio_store_secondary_ai_mode); -static DEVICE_ATTR(mode_ao_type_b, 0660, neuronspi_iio_show_secondary_ao_mode, neuronspi_iio_store_secondary_ao_mode); - -static struct attribute *neuron_plc_attrs[] = { - &dev_attr_model_name.attr, - &dev_attr_sys_eeprom_name.attr, - NULL, -}; - -static struct attribute *neuron_board_attrs[] = { - &dev_attr_sys_board_name.attr, - &dev_attr_sys_primary_major_id.attr, - &dev_attr_sys_secondary_major_id.attr, - &dev_attr_sys_primary_minor_id.attr, - &dev_attr_sys_secondary_minor_id.attr, - &dev_attr_firmware_version.attr, - &dev_attr_watchdog_status.attr, - &dev_attr_watchdog_timeout.attr, - &dev_attr_sys_board_serial.attr, - &dev_attr_uart_queue_length.attr, - &dev_attr_uart_config.attr, - &dev_attr_register_read.attr, - NULL, -}; - -static struct attribute *neuron_gpio_di_attrs[] = { - &dev_attr_sys_gpio_di_count.attr, - &dev_attr_sys_gpio_di_prefix.attr, - &dev_attr_sys_gpio_di_base.attr, - &dev_attr_direct_switch_enable.attr, - &dev_attr_direct_switch_toggle.attr, - &dev_attr_direct_switch_polarity.attr, - &dev_attr_di_value.attr, - &dev_attr_counter.attr, - &dev_attr_debounce.attr, - NULL, -}; - -static struct attribute *neuron_gpio_do_attrs[] = { - &dev_attr_sys_gpio_do_count.attr, - &dev_attr_sys_gpio_do_prefix.attr, - &dev_attr_sys_gpio_do_base.attr, - &dev_attr_pwm_frequency_cycle.attr, - &dev_attr_pwm_prescale.attr, - &dev_attr_pwm_duty_cycle.attr, - &dev_attr_do_value.attr, - NULL, -}; - -static struct attribute *neuron_gpio_ro_attrs[] = { - &dev_attr_sys_gpio_ro_count.attr, - &dev_attr_sys_gpio_ro_prefix.attr, - &dev_attr_sys_gpio_ro_base.attr, - &dev_attr_ro_value.attr, - NULL, -}; - -static struct attribute *neuron_stm_ai_attrs[] = { - &dev_attr_mode_ai_type_a.attr, - NULL, -}; - -static struct attribute *neuron_stm_ao_attrs[] = { - &dev_attr_mode_ao_type_a.attr, - NULL, -}; - -static struct attribute *neuron_sec_ai_attrs[] = { - &dev_attr_mode_ai_type_b.attr, - NULL, -}; - -static struct attribute *neuron_sec_ao_attrs[] = { - &dev_attr_mode_ao_type_b.attr, - NULL, -}; - -static struct attribute_group neuron_plc_attr_group = { - .attrs = neuron_plc_attrs, -}; - -static struct attribute_group neuron_board_attr_group = { - .attrs = neuron_board_attrs, -}; - -static struct attribute_group neuron_gpio_di_attr_group = { - .attrs = neuron_gpio_di_attrs, -}; - -static struct attribute_group neuron_gpio_do_attr_group = { - .attrs = neuron_gpio_do_attrs, -}; - -static struct attribute_group neuron_gpio_ro_attr_group = { - .attrs = neuron_gpio_ro_attrs, -}; - -const struct attribute_group neuron_stm_ai_group = { - .attrs = neuron_stm_ai_attrs, -}; - -const struct attribute_group neuron_stm_ao_group = { - .attrs = neuron_stm_ao_attrs, -}; - -const struct attribute_group neuron_sec_ai_group = { - .attrs = neuron_sec_ai_attrs, -}; - -const struct attribute_group neuron_sec_ao_group = { - .attrs = neuron_sec_ao_attrs, -}; - -const struct attribute_group *neuron_plc_attr_groups[] = { - &neuron_plc_attr_group, - NULL, -}; - -const struct attribute_group *neuron_board_attr_groups[] = { - &neuron_board_attr_group, - NULL, -}; - -const struct attribute_group *neuron_gpio_di_attr_groups[] = { - &neuron_gpio_di_attr_group, - NULL, -}; - -const struct attribute_group *neuron_gpio_do_attr_groups[] = { - &neuron_gpio_do_attr_group, - NULL, -}; - -const struct attribute_group *neuron_gpio_ro_attr_groups[] = { - &neuron_gpio_ro_attr_group, - NULL, -}; diff --git a/modules/neuron_spi/src/unipi_sysfs.h b/modules/neuron_spi/src/unipi_sysfs.h deleted file mode 100644 index 72ae365..0000000 --- a/modules/neuron_spi/src/unipi_sysfs.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * UniPi Neuron tty serial driver - Copyright (C) 2018 UniPi Technologies - * Author: Tomas Knot - * - * Based on the SC16IS7xx driver by Jon Ringle , - * which was in turn based on max310x.c, by Alexander Shiyan - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - */ - -#ifndef MODULES_NEURON_SPI_SRC_UNIPI_SYSFS_H_ -#define MODULES_NEURON_SPI_SRC_UNIPI_SYSFS_H_ - -/************ - * Includes * - ************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "unipi_common.h" -#include "unipi_platform.h" - -extern const struct attribute_group neuron_stm_ai_group; -extern const struct attribute_group neuron_stm_ao_group; -extern const struct attribute_group neuron_sec_ai_group; -extern const struct attribute_group neuron_sec_ao_group; - -extern const struct attribute_group *neuron_plc_attr_groups[]; -extern const struct attribute_group *neuron_board_attr_groups[]; -extern const struct attribute_group *neuron_gpio_di_attr_groups[]; -extern const struct attribute_group *neuron_gpio_do_attr_groups[]; -extern const struct attribute_group *neuron_gpio_ro_attr_groups[]; - -#endif /* MODULES_NEURON_SPI_SRC_UNIPI_SYSFS_H_ */ diff --git a/modules/neuron_spi/src/unipi_uart.c b/modules/neuron_spi/src/unipi_uart.c deleted file mode 100644 index ed549f0..0000000 --- a/modules/neuron_spi/src/unipi_uart.c +++ /dev/null @@ -1,565 +0,0 @@ -/* - * UniPi Neuron tty serial driver - Copyright (C) 2018 UniPi Technologies - * Author: Tomas Knot - * - * Based on the SC16IS7xx driver by Jon Ringle , - * which was in turn based on max310x.c, by Alexander Shiyan - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - */ - -/************ - * Includes * - ************/ - -#include "unipi_uart.h" -#include "unipi_spi.h" - -/******************** - * Data Definitions * - ********************/ - -struct neuronspi_uart_data* neuronspi_uart_glob_data; -unsigned long neuronspi_lines; -struct uart_driver* neuronspi_uart; - -/************************ - * Non-static Functions * - ************************/ - -void neuronspi_uart_tx_proc(struct kthread_work *ws) -{ - struct neuronspi_port *port = to_neuronspi_port(ws, tx_work); - - if ((port->port.rs485.flags & SER_RS485_ENABLED) && - (port->port.rs485.delay_rts_before_send > 0)) { - msleep(port->port.rs485.delay_rts_before_send); - } - - neuronspi_uart_handle_tx(port); -} - -u32 neuronspi_uart_tx_empty(struct uart_port *port) -{ -#if NEURONSPI_DETAILED_DEBUG > 0 - printk(KERN_INFO "NEURONSPI: UART TX Empty\n"); -#endif - return TIOCSER_TEMT; -} - -u32 neuronspi_uart_get_mctrl(struct uart_port *port) -{ -#if NEURONSPI_DETAILED_DEBUG > 0 - printk(KERN_DEBUG "NEURONSPI: UART MCTRL Get\n"); -#endif - 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; - 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); - switch (ioctl_code) { - case TIOCSETD: { - printk(KERN_INFO "NEURONSPI: IOCTL TIOCSETD (processed via set_termios)\n"); - return 1; - } - case 0x5480: { - printk(KERN_INFO "NEURONSPI: IOCTL 0x5480\n"); - write_length = neuronspi_spi_compose_single_register_write(NEURONSPI_UART_TIMEOUT_REGISTER, &inp_buf, &outp_buf, (ioctl_arg * 1000000) / n_port->baud); - neuronspi_spi_send_message(spi, inp_buf, outp_buf, write_length, n_spi->ideal_frequency, 25, 1); - return 1; - } - case 0x5481: { - printk(KERN_INFO "NEURONSPI: IOCTL 0x5481\n"); - write_length = neuronspi_spi_compose_single_register_write(NEURONSPI_UART_TIMEOUT_REGISTER, &inp_buf, &outp_buf, ioctl_arg); - neuronspi_spi_send_message(spi, inp_buf, outp_buf, write_length, n_spi->ideal_frequency, 25, 1); - return 1; - } - default: { - return 0; - } - } -} - -void neuronspi_uart_set_parmrk(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); - printk(KERN_INFO "NEURONSPI: SET PARMRK to %d\n", 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); -} - -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); - printk(KERN_INFO "NEURONSPI: PROFIBUS discipline set\n"); - 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); -} - -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 (old && old->c_iflag && old->c_iflag != termios->c_iflag) { - printk(KERN_INFO "NEURONSPI: c_iflag termios:%d\n", termios->c_iflag); - } -#if NEURONSPI_DETAILED_DEBUG > 0 - printk(KERN_DEBUG "NEURONSPI: TERMIOS Set, p:%d, c_cflag:%x\n", port->line, termios->c_cflag); -#endif - neuronspi_spi_uart_set_cflag(neuronspi_s_dev[n_port->dev_index], n_port->dev_port, termios->c_cflag); - if (old && termios && (old->c_iflag & PARMRK) != (termios->c_iflag & PARMRK)) { - if (termios->c_iflag & PARMRK) { - neuronspi_uart_set_parmrk(port, 1); - } else { - neuronspi_uart_set_parmrk(port, 0); - } - } - if (old && termios && old->c_line != termios->c_line) { - if (termios->c_line == N_PROFIBUS_FDL) { - printk(KERN_INFO "NEURONSPI: Line Discipline change/n"); - neuronspi_uart_set_ldisc(port, termios); - } - } - n_port->baud = uart_get_baud_rate(port, termios, old, 2400, 115200); - uart_update_timeout(port, termios->c_cflag, n_port->baud); -} - -s32 neuronspi_uart_config_rs485(struct uart_port *port, struct serial_rs485 *rs485) -{ - port->rs485 = *rs485; - return 0; -} - -const char* neuronspi_uart_type(struct uart_port *port) -{ - return port->type == PORT_NEURONSPI ? "NEURONSPI_NAME" : NULL; -} - -s32 neuronspi_uart_request_port(struct uart_port *port) -{ -#if NEURONSPI_DETAILED_DEBUG > 0 - printk(KERN_DEBUG "NEURONSPI: Requested port %d\n", port->line); -#endif - return 0; -} - -void neuronspi_uart_fifo_read(struct uart_port *port, u32 rxlen) -{ - struct neuronspi_port *s = to_neuronspi_port(port,port); - struct neuronspi_driver_data *d_data = spi_get_drvdata(neuronspi_s_dev[s->dev_index]); -#if NEURONSPI_DETAILED_DEBUG > 0 - printk(KERN_INFO "NEURONSPI: FIFO Read len:%d\n", rxlen); -#endif - memcpy(s->buf, d_data->uart_buf, rxlen); -} - -void neuronspi_uart_fifo_write(struct neuronspi_port *port, u8 to_send) -{ - s32 i; -#if NEURONSPI_DETAILED_DEBUG > 0 - printk(KERN_INFO "NEURONSPI: FIFO Write to_send:%d\n", to_send); -#endif - for (i = 0; i < to_send; i++) { -#if NEURONSPI_DETAILED_DEBUG > 0 - printk(KERN_INFO "NEURONSPI: UART Char Send: %x\n", port->buf[i]); -#endif - } - neuronspi_spi_uart_write(neuronspi_s_dev[port->dev_index], port->buf, to_send, port->dev_port); -} - -s32 neuronspi_uart_alloc_line(void) -{ - s32 i; - BUILD_BUG_ON(NEURONSPI_MAX_DEVS > BITS_PER_LONG); - - for (i = 0; i < NEURONSPI_MAX_DEVS; i++) - if (!test_and_set_bit(i, &neuronspi_lines)) - break; - - return i; -} - -void neuronspi_uart_handle_rx(struct neuronspi_port *port, u32 rxlen, u32 iir) -{ - u32 ch, flag, bytes_read, i; - while (rxlen) { - - neuronspi_uart_fifo_read(&port->port, rxlen); - bytes_read = rxlen; - - port->port.icount.rx++; - flag = TTY_NORMAL; - - for (i = 0; i < bytes_read; ++i) { -#if NEURONSPI_DETAILED_DEBUG > 0 - printk(KERN_INFO "NEURONSPI: UART Insert Char:%x\n", port->buf[i]); -#endif - ch = port->buf[i]; - if (uart_handle_sysrq_char(port, ch)) - continue; - - uart_insert_char(&port->port, 0, 0, ch, flag); - } - rxlen -= bytes_read; - } - - tty_flip_buffer_push(&port->port.state->port); -} - -void neuronspi_uart_handle_tx(struct neuronspi_port *port) -{ - u32 txlen, to_send, i; - struct spi_device *spi; - struct neuronspi_driver_data *d_data; - struct circ_buf *xmit; - - spi = neuronspi_s_dev[port->dev_index]; - d_data = spi_get_drvdata(spi); - xmit = &port->port.state->xmit; - - if (unlikely(port->port.x_char)) { - neuronspi_spi_uart_write(spi, &port->port.x_char, 1, port->dev_port); - port->port.icount.tx++; - port->port.x_char = 0; - return; - } - - if (uart_circ_empty(xmit) || uart_tx_stopped(&port->port)) { - return; - } - - /* Get length of data pending in circular buffer */ - to_send = uart_circ_chars_pending(xmit); - if (likely(to_send)) { - /* Limit to size of TX FIFO */ - txlen = NEURONSPI_FIFO_SIZE; - to_send = (to_send > txlen) ? txlen : to_send; - - /* Add data to send */ - port->port.icount.tx += to_send; - - /* Convert to linear buffer */ - for (i = 0; i < to_send; ++i) { - port->buf[i] = xmit->buf[xmit->tail]; - xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); - } - - neuronspi_uart_fifo_write(port, to_send); - } - - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) { - uart_write_wakeup(&port->port); - } -} - -void neuronspi_uart_handle_irq(struct neuronspi_uart_data *uart_data, u32 portno) -{ - struct neuronspi_port *n_port = &uart_data->p[portno]; - struct spi_device *spi = neuronspi_s_dev[n_port->dev_index]; - u8 *send_buf = kzalloc(NEURONSPI_UART_PROBE_MESSAGE_LEN, GFP_KERNEL); - u8 *recv_buf = kzalloc(NEURONSPI_UART_PROBE_MESSAGE_LEN, GFP_KERNEL); - memcpy(send_buf, NEURONSPI_UART_PROBE_MESSAGE, NEURONSPI_UART_PROBE_MESSAGE_LEN); - neuronspi_spi_send_message(spi, send_buf, recv_buf, NEURONSPI_UART_PROBE_MESSAGE_LEN, NEURONSPI_DEFAULT_FREQ, 25, 1); - kfree(send_buf); - kfree(recv_buf); -} - -void neuronspi_uart_ist(struct kthread_work *ws) -{ - struct neuronspi_port *p = to_neuronspi_port(ws, irq_work); - neuronspi_uart_handle_irq(p->parent, p->line); -} - -void neuronspi_uart_config_port(struct uart_port *port, int flags) -{ - if (flags & UART_CONFIG_TYPE) { - port->type = PORT_NEURONSPI; - } -} - -s32 neuronspi_uart_verify_port(struct uart_port *port, - struct serial_struct *s) -{ - if ((s->type != PORT_UNKNOWN) && (s->type != PORT_NEURONSPI)) - return -EINVAL; - if (s->irq != port->irq) - return -EINVAL; - - return 0; -} - -void neuronspi_uart_pm(struct uart_port *port, u32 state, u32 oldstate) -{ - neuronspi_uart_power(port, (state == UART_PM_STATE_ON) ? 1 : 0); -} - -s32 neuronspi_uart_probe(struct spi_device* dev, u8 device_index) -{ - struct neuronspi_driver_data* driver_data = spi_get_drvdata(dev); - struct sched_param sched_param = { .sched_priority = MAX_RT_PRIO / 2 }; - s32 i, j, ret, new_uart_count; - struct neuronspi_uart_data *uart_data = driver_data->uart_data; - - if (uart_data->p == NULL) { - uart_data->p = kzalloc(sizeof(struct neuronspi_port[NEURONSPI_MAX_UART]), GFP_KERNEL); - for (i = 0; i < NEURONSPI_MAX_UART; i++) { - uart_data->p[i].parent = uart_data; - } -#if NEURONSPI_DETAILED_DEBUG > 0 - printk(KERN_DEBUG "NEURONSPI: Allocated port structure for %d potential UART devices\n", NEURONSPI_MAX_UART); -#endif - } - - new_uart_count = driver_data->uart_count + uart_data->p_count; - - // Initialise port data - for (i = uart_data->p_count; i < new_uart_count; i++) { - uart_data->p[i].dev_index = device_index; - uart_data->p[i].dev_port = i - uart_data->p_count; - uart_data->p[i].line = i; - uart_data->p[i].port.dev = &(dev->dev); - uart_data->p[i].port.irq = dev->irq; - uart_data->p[i].port.type = PORT_NEURONSPI; - uart_data->p[i].port.fifosize = NEURONSPI_FIFO_SIZE; - uart_data->p[i].port.flags = UPF_FIXED_TYPE | UPF_LOW_LATENCY; - uart_data->p[i].port.iotype = UPIO_PORT; - uart_data->p[i].port.uartclk = 9600; - uart_data->p[i].port.rs485_config = neuronspi_uart_config_rs485; - uart_data->p[i].port.ops = &neuronspi_uart_ops; - uart_data->p[i].port.line = neuronspi_uart_alloc_line(); - spin_lock_init(&uart_data->p[i].port.lock); - if (uart_data->p[i].port.line >= NEURONSPI_MAX_DEVS) { - ret = -ENOMEM; - } - kthread_init_work(&(uart_data->p[i].tx_work), neuronspi_uart_tx_proc); - kthread_init_work(&(uart_data->p[i].rx_work), neuronspi_uart_rx_proc); - kthread_init_work(&(uart_data->p[i].irq_work), neuronspi_uart_ist); - uart_add_one_port(driver_data->serial_driver, &uart_data->p[i].port); - printk(KERN_INFO "NEURONSPI: Added UART port %d\n", i); - } - - // For ports on multiple SPI devices renumber the ports to correspond to SPI chip-select numbering - if (uart_data->p_count) { - // First remove all existing ports - for (i = 0; i < new_uart_count; i++) { - uart_remove_one_port(driver_data->serial_driver, &uart_data->p[i].port); - clear_bit(uart_data->p[i].port.line, &neuronspi_lines); - kthread_flush_worker(&uart_data->kworker); - } - // Now add the ports in the correct order - for (i = 0; i < NEURONSPI_MAX_DEVS; i++) { - if (neuronspi_s_dev[i] != NULL) { - driver_data = spi_get_drvdata(neuronspi_s_dev[i]); -#if NEURONSPI_DETAILED_DEBUG > 0 - printk(KERN_DEBUG "NEURONSPI: Renumber not NULL %d UC:%d\n", i, driver_data->uart_count); -#endif - if (driver_data->uart_count) { - for (j = 0; j < new_uart_count; j++) { - if (uart_data->p[j].dev_index == i) { - uart_data->p[j].port.dev = &(neuronspi_s_dev[i]->dev); - uart_data->p[j].port.irq = neuronspi_s_dev[i]->irq; - uart_data->p[j].port.type = PORT_NEURONSPI; - uart_data->p[j].port.fifosize = NEURONSPI_FIFO_SIZE; - uart_data->p[j].port.flags = UPF_FIXED_TYPE | UPF_LOW_LATENCY; - uart_data->p[j].port.iotype = UPIO_PORT; - uart_data->p[j].port.uartclk = 9800; - uart_data->p[j].port.rs485_config = neuronspi_uart_config_rs485; - uart_data->p[j].port.ops = &neuronspi_uart_ops; - uart_data->p[j].port.line = neuronspi_uart_alloc_line(); - uart_add_one_port(driver_data->serial_driver, &uart_data->p[j].port); -#if NEURONSPI_DETAILED_DEBUG > 0 - printk(KERN_DEBUG "NEURONSPI: Added UART port %d\n", j); -#endif - } - } - } - } - } - } - - uart_data->p_count = new_uart_count; - if (uart_data->kworker_task == NULL) { -#if NEURONSPI_DETAILED_DEBUG > 0 - printk(KERN_DEBUG "NEURONSPI: KWorker Task is NULL\n"); -#endif - - kthread_init_worker(&uart_data->kworker); - - uart_data->kworker_task = kthread_run(kthread_worker_fn, &uart_data->kworker, - "neuronspi"); - if (IS_ERR(uart_data->kworker_task)) { - ret = PTR_ERR(uart_data->kworker_task); - } - sched_setscheduler(uart_data->kworker_task, SCHED_FIFO, &sched_param); - } - return ret; -} - -s32 neuronspi_uart_remove(struct neuronspi_uart_data *u_data) -{ - struct neuronspi_driver_data *d_data; - struct spi_device *spi; - s32 i; - - for (i = 0; i < NEURONSPI_MAX_DEVS; i++) { - if (!(neuronspi_s_dev[i] == NULL)) { - spi = neuronspi_s_dev[i]; - d_data = spi_get_drvdata(spi); - if (d_data->poll_thread != NULL) { - kthread_stop(d_data->poll_thread); - } - } - } - for (i = 0; i < u_data->p_count; i++) { - uart_remove_one_port(neuronspi_uart, &u_data->p[i].port); - clear_bit(u_data->p[i].port.line, &neuronspi_lines); - neuronspi_uart_power(&u_data->p[i].port, 0); - } - - kthread_flush_worker(&u_data->kworker); - return 0; -} - -void neuronspi_uart_rx_proc(struct kthread_work *ws) -{ - s32 end_flag = 0; - s32 read_count = 0; - struct neuronspi_port *n_port = to_neuronspi_port(ws, rx_work); - struct spi_device *spi = neuronspi_s_dev[n_port->dev_index]; - struct neuronspi_driver_data *d_data = spi_get_drvdata(spi); - - u8 *send_buf = kzalloc(NEURONSPI_BUFFER_MAX, GFP_KERNEL); - u8 *recv_buf = kzalloc(NEURONSPI_BUFFER_MAX, GFP_KERNEL); - - mutex_lock(&neuronspi_master_mutex); - read_count = d_data->uart_read; - mutex_unlock(&neuronspi_master_mutex); - - while (!end_flag) { - memset(recv_buf, 0, NEURONSPI_BUFFER_MAX); - neuronspi_spi_uart_read(spi, send_buf, recv_buf, read_count, n_port->dev_port); - if (recv_buf[6] == 0x65 && recv_buf[7] > 0) { - mutex_lock(&neuronspi_master_mutex); - memcpy(&d_data->uart_buf[0], &recv_buf[10], recv_buf[7]); - neuronspi_uart_handle_rx(n_port, recv_buf[7], 1); - read_count = recv_buf[9]; - mutex_unlock(&neuronspi_master_mutex); - } else if (recv_buf[0] != 0x41) { - mutex_lock(&neuronspi_master_mutex); - d_data->uart_read = 0; - end_flag = 1; - mutex_unlock(&neuronspi_master_mutex); - } - } - kfree(recv_buf); - kfree(send_buf); -} - -void neuronspi_uart_start_tx(struct uart_port *port) -{ - struct neuronspi_port *n_port = to_neuronspi_port(port,port); -#if NEURONSPI_DETAILED_DEBUG > 0 - printk(KERN_INFO "NEURONSPI: Start TX\n"); -#endif - kthread_queue_work(&n_port->parent->kworker, &n_port->tx_work); -} - -s32 neuronspi_uart_poll(void *data) -{ - struct neuronspi_driver_data *d_data = (struct neuronspi_driver_data*) data; - struct neuronspi_uart_data *u_data; - s32 i; - while (!kthread_should_stop()) { - usleep_range(2000,8000); - if (d_data->uart_count) { - u_data = d_data->uart_data; - for (i = 0; i < u_data->p_count; i++) { - if (u_data->p[i].dev_index == d_data->neuron_index) { - kthread_queue_work(&u_data->kworker, &u_data->p[i].irq_work); - } - } - } - } - return 0; -} - -// Initialise the driver -s32 neuronspi_uart_startup(struct uart_port *port) -{ - struct neuronspi_port *n_port = to_neuronspi_port(port, port); - struct spi_device *spi = neuronspi_s_dev[n_port->dev_index]; - struct neuronspi_driver_data *d_data = spi_get_drvdata(spi); - neuronspi_spi_set_irqs(spi, 0x5); - if (d_data->poll_thread != NULL) { - wake_up_process(d_data->poll_thread); - } else if (d_data->no_irq) { - d_data->poll_thread = kthread_create(neuronspi_uart_poll, (void *)d_data, "UART_poll_thread"); - } - neuronspi_uart_power(port, 1); - // TODO: /* Reset FIFOs*/ -#if NEURONSPI_DETAILED_DEBUG > 0 - printk(KERN_DEBUG "NEURONSPI: UART Startup\n"); -#endif - return 0; -} - -void neuronspi_uart_shutdown(struct uart_port *port) -{ - neuronspi_uart_power(port, 0); -} - -/******************* - * Empty functions * - *******************/ - -void neuronspi_uart_stop_tx(struct uart_port *port) -{ - /* Do Nothing */ -} - -void neuronspi_uart_stop_rx(struct uart_port *port) -{ - /* Do Nothing */ -} -void neuronspi_uart_set_mctrl(struct uart_port *port, u32 mctrl) -{ - /* Do Nothing */ -} -void neuronspi_uart_break_ctl(struct uart_port *port, int break_state) -{ - /* Do Nothing */ -} -void neuronspi_uart_power(struct uart_port *port, s32 on) -{ - /* Do nothing */ -} -void neuronspi_uart_null_void(struct uart_port *port) -{ - /* Do nothing */ -} diff --git a/modules/neuron_spi/src/unipi_uart.h b/modules/neuron_spi/src/unipi_uart.h deleted file mode 100644 index 81a702d..0000000 --- a/modules/neuron_spi/src/unipi_uart.h +++ /dev/null @@ -1,126 +0,0 @@ -/* - * UniPi Neuron tty serial driver - Copyright (C) 2018 UniPi Technologies - * Author: Tomas Knot - * - * Based on the SC16IS7xx driver by Jon Ringle , - * which was in turn based on max310x.c, by Alexander Shiyan - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - */ - -#ifndef MODULES_NEURON_SPI_SRC_UNIPI_UART_H_ -#define MODULES_NEURON_SPI_SRC_UNIPI_UART_H_ - -/************ - * Includes * - ************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "unipi_common.h" -#include "unipi_platform.h" - -/*************** - * Definitions * - ***************/ - -#define NEURONSPI_UART_IFLAGS_REGISTER 502 -#define NEURONSPI_UART_LDISC_REGISTER 503 -#define NEURONSPI_UART_TIMEOUT_REGISTER 504 - -/************************* - * Function Declarations * - *************************/ - -void neuronspi_uart_start_tx(struct uart_port *port); -void neuronspi_uart_stop_tx(struct uart_port *port); -void neuronspi_uart_stop_rx(struct uart_port *port); -void neuronspi_uart_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old); -u32 neuronspi_uart_tx_empty(struct uart_port *port); -void neuronspi_uart_break_ctl(struct uart_port *port, int break_state); -void neuronspi_uart_shutdown(struct uart_port *port); -s32 neuronspi_uart_startup(struct uart_port *port); -s32 neuronspi_uart_request_port(struct uart_port *port); -s32 neuronspi_uart_alloc_line(void); -void neuronspi_uart_set_mctrl(struct uart_port *port, u32 mctrl); -int neuronspi_uart_ioctl (struct uart_port *port, unsigned int ioctl_code, unsigned long ioctl_arg); -void neuronspi_uart_set_ldisc(struct uart_port *port, struct ktermios *kterm); -u32 neuronspi_uart_get_mctrl(struct uart_port *port); -const char *neuronspi_uart_type(struct uart_port *port); -void neuronspi_uart_null_void(struct uart_port *port); -void neuronspi_uart_config_port(struct uart_port *port, int flags); -s32 neuronspi_uart_verify_port(struct uart_port *port, struct serial_struct *s); -void neuronspi_uart_pm(struct uart_port *port, u32 state, u32 oldstate); -s32 neuronspi_uart_poll(void *data); -s32 neuronspi_uart_probe(struct spi_device* dev, u8 device_index); -s32 neuronspi_uart_remove(struct neuronspi_uart_data *u_data); -void neuronspi_uart_power(struct uart_port *port, s32 on); -s32 neuronspi_uart_config_rs485(struct uart_port *port, struct serial_rs485 *rs485); -void neuronspi_spi_uart_set_cflag(struct spi_device* spi_dev, u8 port, u32 to); -u32 neuronspi_spi_uart_get_cflag(struct spi_device* spi_dev, u8 port); -void neuronspi_uart_fifo_write(struct neuronspi_port *port, u8 to_send); -void neuronspi_uart_fifo_read(struct uart_port *port, u32 rxlen); -void neuronspi_uart_rx_proc(struct kthread_work *ws); -void neuronspi_uart_tx_proc(struct kthread_work *ws); -void neuronspi_uart_ist(struct kthread_work *ws); -void neuronspi_uart_handle_tx(struct neuronspi_port *port); -void neuronspi_uart_handle_rx(struct neuronspi_port *port, u32 rxlen, u32 iir); -void neuronspi_uart_handle_irq(struct neuronspi_uart_data *uart_data, u32 portno); - -/********************* - * Data Declarations * - *********************/ - -extern struct neuronspi_uart_data* neuronspi_uart_glob_data; -extern unsigned long neuronspi_lines; -extern struct uart_driver* neuronspi_uart; - -static const struct uart_ops neuronspi_uart_ops = -{ - .tx_empty = neuronspi_uart_tx_empty, - .set_mctrl = neuronspi_uart_set_mctrl, - .get_mctrl = neuronspi_uart_get_mctrl, - .stop_tx = neuronspi_uart_stop_tx, - .start_tx = neuronspi_uart_start_tx, - .stop_rx = neuronspi_uart_stop_rx, - .break_ctl = neuronspi_uart_break_ctl, - .startup = neuronspi_uart_startup, - .shutdown = neuronspi_uart_shutdown, - .set_termios = neuronspi_uart_set_termios, - .set_ldisc = neuronspi_uart_set_ldisc, - .type = neuronspi_uart_type, - .request_port = neuronspi_uart_request_port, - .release_port = neuronspi_uart_null_void, - .config_port = neuronspi_uart_config_port, - .verify_port = neuronspi_uart_verify_port, - .pm = neuronspi_uart_pm, - .ioctl = neuronspi_uart_ioctl, -}; - -#endif /* MODULES_NEURON_SPI_SRC_UNIPI_UART_H_ */ diff --git a/modules/unipi/Makefile b/modules/unipi/Makefile new file mode 100644 index 0000000..321946c --- /dev/null +++ b/modules/unipi/Makefile @@ -0,0 +1,69 @@ +# Note: Compiling kernel modules requires creating symlinks, which is not possible on certain +# filesystems (notably VirtualBox vmfs); therefore we allow using /run/ through the 'symlink' target, +# if necessary. + +SYMLINK_DIR_PATH = /run/kernel/neuron_spi +LINUX_DIR_PATH = /root/bokula/linux +SRC_DIR_PATH = $(PWD)/src +BIN_DIR_PATH = $(PWD)/bin + +MODULE_MAKE_FILE = Makefile + +C_SRC_FILES = unipi_spi.c +C_SRC_FILES += unipi_iio.c +C_SRC_FILES += unipi_gpio.c +C_SRC_FILES += unipi_uart.c +C_SRC_FILES += unipi_sysfs.c +C_SRC_FILES += unipi_misc.c +C_SRC_FILES += unipi_platform.c + +H_SRC_FILES = unipi_spi.h +H_SRC_FILES += unipi_iio.h +H_SRC_FILES += unipi_gpio.h +H_SRC_FILES += unipi_uart.h +H_SRC_FILES += unipi_sysfs.h +H_SRC_FILES += unipi_misc.h +H_SRC_FILES += unipi_platform.h +H_SRC_FILES += unipi_common.h + +OBJ_FILES = src/unipi_spi.o +OBJ_FILES += src/unipi_iio.o +OBJ_FILES += src/unipi_gpio.o +OBJ_FILES += src/unipi_uart.o +OBJ_FILES += src/unipi_sysfs.o +OBJ_FILES += src/unipi_misc.o +OBJ_FILES += src/unipi_platform.o + +KERNEL_MODULE_NAME = unipi +obj-m += ${KERNEL_MODULE_NAME}.o +unipi-objs := ${OBJ_FILES} + +TARGET_PLC_PATH = tomunipi:/root/ + +.PHONY: default +default: symlink ; + +all: + make ARCH=arm CROSS_COMPILE=${CCPREFIX} -C ${LINUX_DIR_PATH} M=${PWD} modules + +clean: + make -C ${LINUX_DIR_PATH} M=$(PWD) clean + rm -f ${BIN_DIR_PATH}/${KERNEL_MODULE_NAME}.ko + +transfer: clean symlink + scp ${BIN_DIR_PATH}/${KERNEL_MODULE_NAME}.ko ${TARGET_PLC_PATH} + +symlink: clean + rm -r -f ${SYMLINK_DIR_PATH} + mkdir -p ${SYMLINK_DIR_PATH}/src + mkdir -p ${SYMLINK_DIR_PATH}/bin + cp ${PWD}/${MODULE_MAKE_FILE} ${SYMLINK_DIR_PATH} + for f in ${C_SRC_FILES}; do\ + ln -s ${SRC_DIR_PATH}/$$f ${SYMLINK_DIR_PATH}/src ;\ + done + for f in ${H_SRC_FILES}; do\ + ln -s ${SRC_DIR_PATH}/$$f ${SYMLINK_DIR_PATH}/src ;\ + done + cd ${SYMLINK_DIR_PATH}; make all + mv ${SYMLINK_DIR_PATH}/${KERNEL_MODULE_NAME}.ko ${BIN_DIR_PATH} + rm -r -f ${SYMLINK_DIR_PATH} diff --git a/modules/unipi/bin b/modules/unipi/bin new file mode 100644 index 0000000..9cdf8fa Binary files /dev/null and b/modules/unipi/bin differ diff --git a/modules/unipi/src/unipi_common.h b/modules/unipi/src/unipi_common.h new file mode 100644 index 0000000..f7646a3 --- /dev/null +++ b/modules/unipi/src/unipi_common.h @@ -0,0 +1,300 @@ +/* + * UniPi Neuron tty serial driver - Copyright (C) 2018 UniPi Technologies + * Author: Tomas Knot + * + * Based on the SC16IS7xx driver by Jon Ringle , + * which was in turn based on max310x.c, by Alexander Shiyan + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +#ifndef MODULES_NEURON_SPI_SRC_UNIPI_COMMON_H_ +#define MODULES_NEURON_SPI_SRC_UNIPI_COMMON_H_ + +/************ + * Includes * + ************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/*************** + * Definitions * + ***************/ + +#define NEURONSPI_SCHED_REQUIRED 0 // Older kernels do not require sched/types to be specifically imported +#define NEURONSPI_MAJOR_VERSIONSTRING "Development Beta Version 0.02:12:02:2018" + +#define NEURONSPI_MAX_DEVS 3 +#define NEURONSPI_MAX_UART 128 +#define NEURONSPI_BUFFER_MAX 1152 +#define NEURONSPI_HEADER_LENGTH 10 +#define NEURONSPI_FIRST_MESSAGE_LENGTH 6 +#define NEURONSPI_EDGE_DELAY 10 +#define NEURONSPI_B_PER_WORD 8 +#define NEURONSPI_DEFAULT_FREQ 600000 +#define NEURONSPI_COMMON_FREQ 12000000 +#define NEURONSPI_SLOWER_FREQ 8000000 +#define NEURONSPI_MAX_TX 62 +#define NEURONSPI_MAX_BAUD 115200 +#define NEURONSPI_FIFO_SIZE 256 +#define NEURONSPI_DETAILED_DEBUG 0 +#define NEURONSPI_LAST_TRANSFER_DELAY 40 + +#define NEURON_DEVICE_NAME "neuronspi" +#define NEURON_DEVICE_CLASS "modbus_spi" +#define NEURON_DRIVER_NAME "NEURONSPI" +#define PORT_NEURONSPI 184 + +#define STRICT_RESERVING +#define NEURONSPI_ALWAYS_EXPORT + +#define NEURONSPI_GET_COIL_READ_PHASE2_BYTE_LENGTH(X) ((((X) + 15) >> 4) << 1) + +/******************** + * Module Constants * + ********************/ + +#define NEURONSPI_NO_INTERRUPT_MODELS_LEN 3 +static const u16 NEURONSPI_NO_INTERRUPT_MODELS[NEURONSPI_NO_INTERRUPT_MODELS_LEN] = { + 0xb10, 0xc10, 0xf10 +}; + +/******************* + * Data Structures * + *******************/ + +enum neuron_str_attribute_type { + NEURON_SATTR_MODEL, + NEURON_SATTR_EEPROM, + NEURON_SATTR_BOARD_NAME, + NEURON_SATTR_GPIO_GROUP_NAME +}; + +enum neuron_num_attribute_type { + NEURON_NATTR_BOARDCOUNT, + NEURON_NATTR_MODE, + NEURON_NATTR_CURRENT_VALUE +}; + +struct neuronspi_devtype +{ + u8 name[10]; + s32 nr_gpio; + s32 nr_uart; +}; + +struct neuronspi_port +{ + struct uart_port port; + u8 line; + struct kthread_work tx_work; + struct kthread_work rx_work; + struct kthread_work irq_work; + u32 flags; + u8 ier_clear; + u8 buf[NEURONSPI_FIFO_SIZE]; + struct neuronspi_uart_data *parent; + u8 dev_index; + u8 dev_port; + u8 parmrk_enabled; + u64 parmrk_frame_delay; + s32 baud; +}; + +struct neuronspi_uart_data +{ + const struct neuronspi_devtype *devtype; + struct kthread_worker kworker; + struct task_struct *kworker_task; + struct neuronspi_port *p; + u8 p_count; +}; + +// Instantiated once +struct neuronspi_char_driver +{ + s32 major_number; + u8 *message; + u16 message_size; + u32 open_counter; + struct class* driver_class; + struct device* dev; +}; + +// Instantiated once per SPI device +struct neuronspi_driver_data +{ + struct spi_driver *spi_driver; + struct neuronspi_char_driver *char_driver; + struct uart_driver *serial_driver; + struct neuronspi_uart_data *uart_data; + struct neuronspi_led_driver *led_driver; + struct neuronspi_di_driver **di_driver; + struct neuronspi_do_driver **do_driver; + struct neuronspi_ro_driver **ro_driver; + struct platform_device *board_device; + struct iio_dev *stm_ai_driver; + struct iio_dev *stm_ao_driver; + struct iio_dev **sec_ai_driver; + struct iio_dev **sec_ao_driver; + struct kthread_worker primary_worker; + struct task_struct *primary_worker_task; + struct regmap *reg_map; + struct task_struct *poll_thread; + struct mutex device_lock; + struct neuronspi_board_features *features; + struct neuronspi_board_regstart_table *regstart_table; + struct spinlock sysfs_regmap_lock; + char platform_name[sizeof("io_group0")]; + u8 *send_buf; + u8 *recv_buf; + u8 *first_probe_reply; + u8 *second_probe_reply; + u8 reserved_device; + u8 uart_count; + u8 uart_read; + u8 *uart_buf; + u8 slower_model; + u8 no_irq; + u8 lower_board_id; + u8 upper_board_id; + u8 combination_id; + s32 neuron_index; + u16 sysfs_regmap_target; + u16 sysfs_counter_target; + u32 ideal_frequency; +}; + +struct neuronspi_di_driver { + struct spi_device* spi; + struct gpio_chip gpio_c; + struct platform_device *plat_dev; + u8 di_index; + char name[sizeof("di_0_00")]; +}; + +struct neuronspi_do_driver +{ + struct spi_device* spi; + struct gpio_chip gpio_c; + struct platform_device *plat_dev; + u8 do_index; + char name[sizeof("do_0_00")]; +}; + +struct neuronspi_ro_driver +{ + struct spi_device* spi; + struct gpio_chip gpio_c; + struct platform_device *plat_dev; + u8 ro_index; + char name[sizeof("ro_0_00")]; +}; + +struct neuronspi_sec_ai_driver +{ + struct iio *devices; + u16 dev_count; +}; + +struct neuronspi_sec_ao_driver +{ + struct iio *devices; + u16 dev_count; +}; + +struct neuronspi_stm_ai_data +{ + u32 mode; + struct spi_device *parent; +}; + +struct neuronspi_stm_ao_data +{ + u32 mode; + struct spi_device *parent; +}; + +struct neuronspi_sec_ai_data +{ + u32 index; + u32 mode; + struct spi_device *parent; +}; + +struct neuronspi_sec_ao_data +{ + u32 index; + u32 mode; + struct spi_device *parent; +}; + +// Instantiated once per LED +struct neuronspi_led_driver +{ + struct led_classdev ldev; + struct spi_device *spi; + struct kthread_work led_work; + int id; + int brightness; + char name[sizeof("neuron:green:uled-x1")]; + spinlock_t lock; +}; + +struct neuronspi_file_data +{ + struct spi_device** spi_device; + struct mutex lock; + u8 *send_buf; + u8 *recv_buf; + u32 message_len; +}; + +struct neuronspi_direct_acc +{ + void __iomem *vaddr; + u32 size; +}; + +/********************* + * Data Declarations * + *********************/ + +extern struct mutex neuronspi_master_mutex; +extern struct neuronspi_char_driver neuronspi_cdrv; +extern struct spinlock* neuronspi_spi_w_spinlock; +extern struct spi_device* neuronspi_s_dev[NEURONSPI_MAX_DEVS]; +extern struct task_struct *neuronspi_invalidate_thread; + +extern u8 neuronspi_spi_w_flag; +extern u8 neuronspi_probe_count; +extern int neuronspi_model_id; +extern spinlock_t neuronspi_probe_spinlock; + +#endif /* MODULES_NEURON_SPI_SRC_UNIPI_COMMON_H_ */ diff --git a/modules/unipi/src/unipi_gpio.c b/modules/unipi/src/unipi_gpio.c new file mode 100644 index 0000000..e7d9de6 --- /dev/null +++ b/modules/unipi/src/unipi_gpio.c @@ -0,0 +1,59 @@ +/* + * UniPi Neuron tty serial driver - Copyright (C) 2018 UniPi Technologies + * Author: Tomas Knot + * + * Based on the SC16IS7xx driver by Jon Ringle , + * which was in turn based on max310x.c, by Alexander Shiyan + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +/************ + * Includes * + ************/ + +#include "unipi_gpio.h" +#include "unipi_spi.h" + +/************************ + * Non-static Functions * + ************************/ + +int neuronspi_gpio_di_direction_input(struct gpio_chip *chip, unsigned offset) { + return 0; +} + +int neuronspi_gpio_di_direction_output(struct gpio_chip *chip, unsigned offset, int value) { + return -EINVAL; +} + +int neuronspi_gpio_di_get(struct gpio_chip *chip, unsigned offset) { + struct neuronspi_di_driver *n_di = gpiochip_get_data(chip); + struct spi_device *spi = n_di->spi; + return neuronspi_spi_gpio_di_get(spi, n_di->di_index); +} + +int neuronspi_gpio_do_direction_output(struct gpio_chip *chip, unsigned offset, int value) { + return 0; +} + +void neuronspi_gpio_do_set(struct gpio_chip *chip, unsigned offset, int value) { + struct neuronspi_do_driver *n_do = gpiochip_get_data(chip); + struct spi_device *spi = n_do->spi; + neuronspi_spi_gpio_do_set(spi, n_do->do_index, value); +} + +int neuronspi_gpio_ro_direction_output(struct gpio_chip *chip, unsigned offset, int value) { + return 0; +} + +void neuronspi_gpio_ro_set(struct gpio_chip *chip, unsigned offset, int value) { + struct neuronspi_ro_driver *n_ro = gpiochip_get_data(chip); + struct spi_device *spi = n_ro->spi; + neuronspi_spi_gpio_ro_set(spi, n_ro->ro_index, value); +} + diff --git a/modules/unipi/src/unipi_gpio.h b/modules/unipi/src/unipi_gpio.h new file mode 100644 index 0000000..508fd78 --- /dev/null +++ b/modules/unipi/src/unipi_gpio.h @@ -0,0 +1,62 @@ +/* + * UniPi Neuron tty serial driver - Copyright (C) 2018 UniPi Technologies + * Author: Tomas Knot + * + * Based on the SC16IS7xx driver by Jon Ringle , + * which was in turn based on max310x.c, by Alexander Shiyan + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +#ifndef MODULES_NEURON_SPI_SRC_UNIPI_GPIO_H_ +#define MODULES_NEURON_SPI_SRC_UNIPI_GPIO_H_ + +/************ + * Includes * + ************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "unipi_common.h" + +/************************* + * Function Declarations * + *************************/ + +int neuronspi_gpio_di_direction_input(struct gpio_chip *chip, unsigned offset); +int neuronspi_gpio_di_direction_output(struct gpio_chip *chip, unsigned offset, int value); +int neuronspi_gpio_di_get(struct gpio_chip *chip, unsigned offset); +int neuronspi_gpio_do_direction_input(struct gpio_chip *chip, unsigned offset); +int neuronspi_gpio_do_direction_output(struct gpio_chip *chip, unsigned offset, int value); +void neuronspi_gpio_do_set(struct gpio_chip *chip, unsigned offset, int value); +int neuronspi_gpio_ro_direction_input(struct gpio_chip *chip, unsigned offset); +int neuronspi_gpio_ro_direction_output(struct gpio_chip *chip, unsigned offset, int value); +void neuronspi_gpio_ro_set(struct gpio_chip *chip, unsigned offset, int value); + +#endif /* MODULES_NEURON_SPI_SRC_UNIPI_GPIO_H_ */ diff --git a/modules/unipi/src/unipi_iio.c b/modules/unipi/src/unipi_iio.c new file mode 100644 index 0000000..eca3eae --- /dev/null +++ b/modules/unipi/src/unipi_iio.c @@ -0,0 +1,183 @@ +/* + * UniPi Neuron tty serial driver - Copyright (C) 2018 UniPi Technologies + * Author: Tomas Knot + * + * Based on the SC16IS7xx driver by Jon Ringle , + * which was in turn based on max310x.c, by Alexander Shiyan + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +/************ + * Includes * + ************/ + +#include "unipi_iio.h" +#include "unipi_spi.h" + +/************************ + * Non-static Functions * + ************************/ + +int neuronspi_iio_stm_ai_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *ch, int *val, int *val2, long mask) { + struct neuronspi_stm_ai_data *ai_data = iio_priv(indio_dev); + struct spi_device *spi = ai_data->parent; + struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi); + regmap_read(n_spi->reg_map, n_spi->regstart_table->stm_ai_mode_reg, &ai_data->mode); + switch(ai_data->mode) { + case 0: { + if (ch->type == IIO_VOLTAGE) { + neuronspi_spi_iio_stm_ai_read_voltage(indio_dev, ch, val, val2, mask); + return IIO_VAL_INT; + } else { + return -EINVAL; + } + break; + } + case 1: { + if (ch->type == IIO_CURRENT) { + neuronspi_spi_iio_stm_ai_read_current(indio_dev, ch, val, val2, mask); + return IIO_VAL_INT; + } else { + return -EINVAL; + } + break; + } + default: { + return -EINVAL; + break; + } + } +} + +int neuronspi_iio_stm_ao_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *ch, int *val, int *val2, long mask) +{ + struct neuronspi_stm_ao_data *ao_data = iio_priv(indio_dev); + struct spi_device *spi = ao_data->parent; + struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi); + regmap_read(n_spi->reg_map, n_spi->regstart_table->stm_ao_mode_reg, &ao_data->mode); + switch(ao_data->mode) { + case 3: { + if (ch->type == IIO_RESISTANCE) { + neuronspi_spi_iio_stm_ao_read_resistance(indio_dev, ch, val, val2, mask); + return IIO_VAL_INT; + } else { + return -EINVAL; + } + break; + } + default: { + return -EINVAL; + break; + } + } +} + +int neuronspi_iio_stm_ao_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *ch, int val, int val2, long mask) +{ + struct neuronspi_stm_ao_data *ao_data = iio_priv(indio_dev); + struct spi_device *spi = ao_data->parent; + struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi); + regmap_read(n_spi->reg_map, n_spi->regstart_table->stm_ao_mode_reg, &ao_data->mode); + switch(ao_data->mode) { + case 0: { + if (ch->type == IIO_VOLTAGE) { + neuronspi_spi_iio_stm_ao_set_voltage(indio_dev, ch, val, val2, mask); + return 0; + } else { + return -EINVAL; + } + break; + } + case 1: { + if (ch->type == IIO_CURRENT) { + neuronspi_spi_iio_stm_ao_set_current(indio_dev, ch, val, val2, mask); + return 0; + } else { + return -EINVAL; + } + break; + } + default: { + return -EINVAL; + break; + } + } +} + +int neuronspi_iio_sec_ai_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *ch, int *val, int *val2, long mask) +{ + struct neuronspi_sec_ai_data *ai_data = iio_priv(indio_dev); + struct spi_device *spi = ai_data->parent; + struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi); + regmap_read(n_spi->reg_map, n_spi->regstart_table->sec_ai_mode_reg, &ai_data->mode); + switch(ai_data->mode) { + case 0: { + return -EINVAL; + break; + } + case 1: { + if (ch->type == IIO_VOLTAGE) { + neuronspi_spi_iio_sec_ai_read_voltage(indio_dev, ch, val, val2, mask); + return IIO_VAL_FRACTIONAL; + } else { + return -EINVAL; + } + break; + } + case 2: { + if (ch->type == IIO_VOLTAGE) { + neuronspi_spi_iio_sec_ai_read_voltage(indio_dev, ch, val, val2, mask); + return IIO_VAL_FRACTIONAL; + } else { + return -EINVAL; + } + break; + } + case 3: { + if (ch->type == IIO_CURRENT) { + neuronspi_spi_iio_sec_ai_read_current(indio_dev, ch, val, val2, mask); + return IIO_VAL_FRACTIONAL; + } else { + return -EINVAL; + } + break; + } + case 4: { + if (ch->type == IIO_RESISTANCE) { + neuronspi_spi_iio_sec_ai_read_resistance(indio_dev, ch, val, val2, mask); + return IIO_VAL_FRACTIONAL; + } else { + return -EINVAL; + } + break; + } + case 5: { + if (ch->type == IIO_RESISTANCE) { + neuronspi_spi_iio_sec_ai_read_resistance(indio_dev, ch, val, val2, mask); + return IIO_VAL_FRACTIONAL; + } else { + return -EINVAL; + } + break; + } + default: { + return -EINVAL; + break; + } + } +} + +int neuronspi_iio_sec_ao_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *ch, int val, int val2, long mask) +{ + if (ch->type == IIO_VOLTAGE) { + neuronspi_spi_iio_stm_ao_set_voltage(indio_dev, ch, val, val2, mask); + return 0; + } else { + return -EINVAL; + } +} diff --git a/modules/unipi/src/unipi_iio.h b/modules/unipi/src/unipi_iio.h new file mode 100644 index 0000000..c6e96c9 --- /dev/null +++ b/modules/unipi/src/unipi_iio.h @@ -0,0 +1,58 @@ +/* + * UniPi Neuron tty serial driver - Copyright (C) 2018 UniPi Technologies + * Author: Tomas Knot + * + * Based on the SC16IS7xx driver by Jon Ringle , + * which was in turn based on max310x.c, by Alexander Shiyan + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +#ifndef MODULES_NEURON_SPI_SRC_UNIPI_IIO_H_ +#define MODULES_NEURON_SPI_SRC_UNIPI_IIO_H_ + +/************ + * Includes * + ************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "unipi_common.h" + +/************************* + * Function Declarations * + *************************/ + +int neuronspi_iio_stm_ai_read_raw(struct iio_dev *iio_dev, struct iio_chan_spec const *ch, int *val, int *val2, long mask); +int neuronspi_iio_stm_ao_read_raw(struct iio_dev *iio_dev, struct iio_chan_spec const *ch, int *val, int *val2, long mask); +int neuronspi_iio_stm_ao_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int val, int val2, long mask); +int neuronspi_iio_sec_ai_read_raw(struct iio_dev *iio_dev, struct iio_chan_spec const *ch, int *val, int *val2, long mask); +int neuronspi_iio_sec_ao_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int val, int val2, long mask); + +#endif /* MODULES_NEURON_SPI_SRC_UNIPI_IIO_H_ */ diff --git a/modules/unipi/src/unipi_misc.c b/modules/unipi/src/unipi_misc.c new file mode 100644 index 0000000..6efb89c --- /dev/null +++ b/modules/unipi/src/unipi_misc.c @@ -0,0 +1,41 @@ +/* + * UniPi Neuron tty serial driver - Copyright (C) 2018 UniPi Technologies + * Author: Tomas Knot + * + * Based on the SC16IS7xx driver by Jon Ringle , + * which was in turn based on max310x.c, by Alexander Shiyan + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +/************ + * Includes * + ************/ + +#include "unipi_misc.h" +#include "unipi_spi.h" + +/************************ + * Non-static Functions * + ************************/ + +void neuronspi_led_proc(struct kthread_work *ws) +{ + struct neuronspi_led_driver *led = to_led_driver(ws, led_work); + printk("NEURONSPI: BRIGHT id:%d\n", led->id); + neuronspi_spi_led_set_brightness(led->spi, led->brightness, led->id); +} + +void neuronspi_led_set_brightness(struct led_classdev *ldev, enum led_brightness brightness) +{ + struct neuronspi_led_driver *led = container_of(ldev, struct neuronspi_led_driver, ldev); + struct neuronspi_driver_data *n_spi = spi_get_drvdata(led->spi); + spin_lock(&led->lock); + led->brightness = brightness; + kthread_queue_work(&n_spi->primary_worker, &led->led_work); + spin_unlock(&led->lock); +} diff --git a/modules/unipi/src/unipi_misc.h b/modules/unipi/src/unipi_misc.h new file mode 100644 index 0000000..ebeb7e2 --- /dev/null +++ b/modules/unipi/src/unipi_misc.h @@ -0,0 +1,55 @@ +/* + * UniPi Neuron tty serial driver - Copyright (C) 2018 UniPi Technologies + * Author: Tomas Knot + * + * Based on the SC16IS7xx driver by Jon Ringle , + * which was in turn based on max310x.c, by Alexander Shiyan + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +#ifndef MODULES_NEURON_SPI_SRC_UNIPI_MISC_H_ +#define MODULES_NEURON_SPI_SRC_UNIPI_MISC_H_ + +/************ + * Includes * + ************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "unipi_common.h" + +/************************* + * Function Declarations * + *************************/ + +void neuronspi_led_proc(struct kthread_work *ws); +void neuronspi_led_set_brightness(struct led_classdev *ldev, enum led_brightness brightness); + +#endif /* MODULES_NEURON_SPI_SRC_UNIPI_MISC_H_ */ diff --git a/modules/unipi/src/unipi_platform.c b/modules/unipi/src/unipi_platform.c new file mode 100644 index 0000000..08a0ec8 --- /dev/null +++ b/modules/unipi/src/unipi_platform.c @@ -0,0 +1,1801 @@ +/* + * UniPi Neuron tty serial driver - Copyright (C) 2018 UniPi Technologies + * Author: Tomas Knot + * + * Based on the SC16IS7xx driver by Jon Ringle , + * which was in turn based on max310x.c, by Alexander Shiyan + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ +/************ + * Includes * + ************/ + +#include "unipi_platform.h" +#include "unipi_spi.h" +#include "unipi_common.h" + +/*************************** + * Static Data Definitions * + ***************************/ + +// B_1000 (S103) +#define NEURONSPI_BOARD_B1000_HW_DEFINITION_BLOCK_SIZE 57 +static u32 NEURONSPI_BOARD_B1000_HW_DEFINITION_BLOCK[NEURONSPI_BOARD_B1000_HW_DEFINITION_BLOCK_SIZE] = { + 0, 21, // Register block beginning and size + NEURONSPI_REGFUN_DI_READ | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 0 + NEURONSPI_REGFUN_DO_RW | NEURONSPI_REGFLAG_ACC_10HZ, // 1 + NEURONSPI_REGFUN_AO_BRAIN | NEURONSPI_REGFLAG_ACC_AFAP, // 2 + NEURONSPI_REGFUN_AI_BRAIN | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 3 + NEURONSPI_REGFUN_AIO_BRAIN | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 4 + NEURONSPI_REGFUN_V_REF_INP | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 5 + NEURONSPI_REGFUN_MWD_STATUS | NEURONSPI_REGFLAG_ACC_6SEC | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 6 + NEURONSPI_REGFUN_TX_QUEUE_LEN | NEURONSPI_REGFLAG_ACC_10HZ, // 7 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 8 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 9 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 10 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 11 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 12 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 13 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 14 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 15 + NEURONSPI_REGFUN_PWM_DUTY | NEURONSPI_REGFLAG_ACC_6SEC, // 16 + NEURONSPI_REGFUN_PWM_DUTY | NEURONSPI_REGFLAG_ACC_6SEC, // 17 + NEURONSPI_REGFUN_PWM_DUTY | NEURONSPI_REGFLAG_ACC_6SEC, // 18 + NEURONSPI_REGFUN_PWM_DUTY | NEURONSPI_REGFLAG_ACC_6SEC, // 19 + NEURONSPI_REGFUN_LED_RW | NEURONSPI_REGFLAG_ACC_AFAP, // 20 + 1000, 32, // Register block beginning and size + NEURONSPI_REGFUN_SW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1000 + NEURONSPI_REGFUN_DIDO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1001 + NEURONSPI_REGFUN_UAIO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1002 + NEURONSPI_REGFUN_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1003 + NEURONSPI_REGFUN_FLASH_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1004 + NEURONSPI_REGFUN_SERIAL_NR_LOWER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1005 + NEURONSPI_REGFUN_SERIAL_NR_UPPER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1006 + NEURONSPI_REGFUN_INTERRUPTS | NEURONSPI_REGFLAG_ACC_AFAP, // 1007 + NEURONSPI_REGFUN_MWD_TO | NEURONSPI_REGFLAG_ACC_6SEC | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1008 + NEURONSPI_REGFUN_V_REF_INT | NEURONSPI_REGFLAG_ACC_ONCE, // 1009 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1010 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1011 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1012 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1013 + NEURONSPI_REGFUN_DS_ENABLE | NEURONSPI_REGFLAG_ACC_1HZ, // 1014 + NEURONSPI_REGFUN_DS_POLARITY | NEURONSPI_REGFLAG_ACC_1HZ, // 1015 + NEURONSPI_REGFUN_DS_TOGGLE | NEURONSPI_REGFLAG_ACC_1HZ, // 1016 + NEURONSPI_REGFUN_PWM_PRESCALE | NEURONSPI_REGFLAG_ACC_1HZ, // 1017 + NEURONSPI_REGFUN_PWM_CYCLE | NEURONSPI_REGFLAG_ACC_1HZ, // 1018 + NEURONSPI_REGFUN_AO_BRAIN_MODE | NEURONSPI_REGFLAG_ACC_1HZ, // 1019 + NEURONSPI_REGFUN_AO_BRAIN_V_ERR | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1020 + NEURONSPI_REGFUN_AO_BRAIN_V_OFF | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1021 + NEURONSPI_REGFUN_AO_BRAIN_I_ERR | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1022 + NEURONSPI_REGFUN_AO_BRAIN_I_OFF | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1023 + NEURONSPI_REGFUN_AI_BRAIN_MODE | NEURONSPI_REGFLAG_ACC_1HZ, // 1024 + NEURONSPI_REGFUN_AI_BRAIN_V_ERR | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1025 + NEURONSPI_REGFUN_AI_BRAIN_V_OFF | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1026 + NEURONSPI_REGFUN_AI_BRAIN_I_ERR | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1027 + NEURONSPI_REGFUN_AI_BRAIN_I_OFF | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1028 + NEURONSPI_REGFUN_AIO_BRAIN_OFF | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1029 + NEURONSPI_REGFUN_AIO_BRAIN_ERR | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1030 + NEURONSPI_REGFUN_RS485_CONFIG | NEURONSPI_REGFLAG_ACC_6SEC // 1031 +}; + +#define NEURONSPI_BOARD_B1000_HW_FEATURES { \ + .do_count = 4, \ + .ro_count = 0, \ + .ds_count = 4, \ + .di_count = 4, \ + .led_count = 4, \ + .stm_ai_count = 1, \ + .stm_ao_count = 1, \ + .sec_ai_count = 0, \ + .sec_ao_count = 0, \ + .uart_master_count = 1, \ + .uart_slave_count = 0, \ + .pwm_channel_count = 4, \ + .wd_count = 1, \ + .extension_sys_count = 0, \ + .light_count = 0, \ + .owire_count = 1, \ +} + +#define NEURONSPI_BOARD_B1000_HW_DEFINITION { \ + .combination_board_id = 0, \ + .lower_board_id = NEURONSPI_BOARD_LOWER_B1000_ID, \ + .upper_board_id = NEURONSPI_BOARD_UPPER_NONE_ID, \ + .block_count = NEURONSPI_BOARD_B1000_HW_DEFINITION_BLOCK_SIZE, \ + .name_length = 6, \ + .combination_name = "B_1000", \ + .features = NEURONSPI_BOARD_B1000_HW_FEATURES, \ + .blocks = NEURONSPI_BOARD_B1000_HW_DEFINITION_BLOCK \ +} +struct neuronspi_board_combination NEURONSPI_BOARD_B1000_HW_COMBINATION[] = {NEURONSPI_BOARD_B1000_HW_DEFINITION}; + +// E-8Di8Ro (M103) +#define NEURONSPI_BOARD_E8DI8RO_HW_DEFINITION_BLOCK_SIZE 44 +static u32 NEURONSPI_BOARD_E8DI8RO_HW_DEFINITION_BLOCK[NEURONSPI_BOARD_E8DI8RO_HW_DEFINITION_BLOCK_SIZE] = { + 0, 19, // Register block beginning and size + NEURONSPI_REGFUN_DI_READ | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 0 + NEURONSPI_REGFUN_DO_RW | NEURONSPI_REGFLAG_ACC_10HZ, // 1 + NEURONSPI_REGFUN_MWD_STATUS | NEURONSPI_REGFLAG_ACC_6SEC | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 2 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 3 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 4 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 5 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 6 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 7 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 8 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 9 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 10 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 11 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 12 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 13 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 14 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 15 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 16 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 17 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 18 + 1000, 17, // Register block beginning and size + NEURONSPI_REGFUN_SW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1000 + NEURONSPI_REGFUN_DIDO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1001 + NEURONSPI_REGFUN_UAIO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1002 + NEURONSPI_REGFUN_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1003 + NEURONSPI_REGFUN_FLASH_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1004 + NEURONSPI_REGFUN_SERIAL_NR_LOWER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1005 + NEURONSPI_REGFUN_SERIAL_NR_UPPER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1006 + NEURONSPI_REGFUN_INTERRUPTS | NEURONSPI_REGFLAG_ACC_AFAP, // 1007 + NEURONSPI_REGFUN_MWD_TO | NEURONSPI_REGFLAG_ACC_6SEC, // 1008 + NEURONSPI_REGFUN_V_REF_INT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1009 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1010 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1011 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1012 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1013 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1014 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1015 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1016 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1017 + NEURONSPI_REGFUN_DS_ENABLE | NEURONSPI_REGFLAG_ACC_1HZ, // 1018 + NEURONSPI_REGFUN_DS_POLARITY | NEURONSPI_REGFLAG_ACC_1HZ, // 1019 + NEURONSPI_REGFUN_DS_TOGGLE | NEURONSPI_REGFLAG_ACC_1HZ, // 1020 +}; + +#define NEURONSPI_BOARD_E8DI8RO_HW_FEATURES { \ + .do_count = 0, \ + .ro_count = 8, \ + .ds_count = 8, \ + .di_count = 8, \ + .led_count = 0, \ + .stm_ai_count = 0, \ + .stm_ao_count = 0, \ + .sec_ai_count = 0, \ + .sec_ao_count = 0, \ + .uart_master_count = 0, \ + .uart_slave_count = 0, \ + .pwm_channel_count = 0, \ + .wd_count = 1, \ + .extension_sys_count = 0, \ + .light_count = 0, \ + .owire_count = 0, \ +} + +#define NEURONSPI_BOARD_E8DI8RO_HW_DEFINITION { \ + .combination_board_id = 1, \ + .lower_board_id = NEURONSPI_BOARD_LOWER_E8DI8RO_ID, \ + .upper_board_id = NEURONSPI_BOARD_UPPER_NONE_ID, \ + .block_count = NEURONSPI_BOARD_E8DI8RO_HW_DEFINITION_BLOCK_SIZE, \ + .name_length = 8, \ + .combination_name = "E_8Di8Ro", \ + .blocks = NEURONSPI_BOARD_E8DI8RO_HW_DEFINITION_BLOCK, \ + .features = NEURONSPI_BOARD_E8DI8RO_HW_FEATURES \ +} +struct neuronspi_board_combination NEURONSPI_BOARD_E8DI8RO_HW_COMBINATION[] = {NEURONSPI_BOARD_E8DI8RO_HW_DEFINITION}; + +// E-14Ro +#define NEURONSPI_BOARD_E14RO_HW_DEFINITION_BLOCK_SIZE 15 +static u32 NEURONSPI_BOARD_E14RO_HW_DEFINITION_BLOCK[NEURONSPI_BOARD_E14RO_HW_DEFINITION_BLOCK_SIZE] = { + 0, 1, // Register block beginning and size + NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE, // 0 + 1000, 10, + NEURONSPI_REGFUN_SW_VER | NEURONSPI_REGFLAG_ACC_ONCE, // 1000 + NEURONSPI_REGFUN_DIDO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE, // 1001 + NEURONSPI_REGFUN_UAIO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE, // 1002 + NEURONSPI_REGFUN_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE, // 1003 + NEURONSPI_REGFUN_FLASH_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE, // 1004 + NEURONSPI_REGFUN_SERIAL_NR_LOWER | NEURONSPI_REGFLAG_ACC_ONCE, // 1005 + NEURONSPI_REGFUN_SERIAL_NR_UPPER | NEURONSPI_REGFLAG_ACC_ONCE, // 1006 + NEURONSPI_REGFUN_INTERRUPTS | NEURONSPI_REGFLAG_ACC_AFAP, // 1007 + NEURONSPI_REGFUN_MWD_TO | NEURONSPI_REGFLAG_ACC_6SEC, // 1008 + NEURONSPI_REGFUN_V_REF_INT | NEURONSPI_REGFLAG_ACC_ONCE, // 1009 +}; + +#define NEURONSPI_BOARD_E14RO_HW_FEATURES { \ + .do_count = 0, \ + .ro_count = 14, \ + .ds_count = 0, \ + .di_count = 0, \ + .led_count = 0, \ + .stm_ai_count = 0, \ + .stm_ao_count = 0, \ + .sec_ai_count = 0, \ + .sec_ao_count = 0, \ + .uart_master_count = 0, \ + .uart_slave_count = 0, \ + .pwm_channel_count = 0, \ + .wd_count = 1, \ + .extension_sys_count = 0, \ + .light_count = 0, \ + .owire_count = 0, \ +} + +#define NEURONSPI_BOARD_E14RO_HW_DEFINITION { \ + .combination_board_id = 2, \ + .lower_board_id = NEURONSPI_BOARD_LOWER_E14RO_ID, \ + .upper_board_id = NEURONSPI_BOARD_UPPER_NONE_ID, \ + .block_count = NEURONSPI_BOARD_E14RO_HW_DEFINITION_BLOCK_SIZE, \ + .name_length = 6, \ + .combination_name = "E_14Ro", \ + .blocks = NEURONSPI_BOARD_E14RO_HW_DEFINITION_BLOCK, \ + .features = NEURONSPI_BOARD_E14RO_HW_FEATURES \ +} +struct neuronspi_board_combination NEURONSPI_BOARD_E14RO_HW_COMBINATION[] = {NEURONSPI_BOARD_E14RO_HW_DEFINITION}; + +// E-16Di +#define NEURONSPI_BOARD_E16DI_HW_DEFINITION_BLOCK_SIZE 15 +static u32 NEURONSPI_BOARD_E16DI_HW_DEFINITION_BLOCK[NEURONSPI_BOARD_E16DI_HW_DEFINITION_BLOCK_SIZE] = { + 0, 1, // Register block beginning and size + NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE, // 0 + 1000, 10, + NEURONSPI_REGFUN_SW_VER | NEURONSPI_REGFLAG_ACC_ONCE, // 1000 + NEURONSPI_REGFUN_DIDO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE, // 1001 + NEURONSPI_REGFUN_UAIO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE, // 1002 + NEURONSPI_REGFUN_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE, // 1003 + NEURONSPI_REGFUN_FLASH_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE, // 1004 + NEURONSPI_REGFUN_SERIAL_NR_LOWER | NEURONSPI_REGFLAG_ACC_ONCE, // 1005 + NEURONSPI_REGFUN_SERIAL_NR_UPPER | NEURONSPI_REGFLAG_ACC_ONCE, // 1006 + NEURONSPI_REGFUN_INTERRUPTS | NEURONSPI_REGFLAG_ACC_AFAP, // 1007 + NEURONSPI_REGFUN_MWD_TO | NEURONSPI_REGFLAG_ACC_6SEC, // 1008 + NEURONSPI_REGFUN_V_REF_INT | NEURONSPI_REGFLAG_ACC_ONCE, // 1009 +}; + +#define NEURONSPI_BOARD_E16DI_HW_FEATURES { \ + .do_count = 0, \ + .ro_count = 0, \ + .ds_count = 0, \ + .di_count = 16, \ + .led_count = 0, \ + .stm_ai_count = 0, \ + .stm_ao_count = 0, \ + .sec_ai_count = 0, \ + .sec_ao_count = 0, \ + .uart_master_count = 0, \ + .uart_slave_count = 0, \ + .pwm_channel_count = 0, \ + .wd_count = 1, \ + .extension_sys_count = 0, \ + .light_count = 0, \ + .owire_count = 0, \ +} + +#define NEURONSPI_BOARD_E16DI_HW_DEFINITION { \ + .combination_board_id = 3, \ + .lower_board_id = NEURONSPI_BOARD_LOWER_E16DI_ID, \ + .upper_board_id = NEURONSPI_BOARD_UPPER_NONE_ID, \ + .block_count = NEURONSPI_BOARD_E16DI_HW_DEFINITION_BLOCK_SIZE, \ + .name_length = 6, \ + .combination_name = "E_16Di", \ + .blocks = NEURONSPI_BOARD_E16DI_HW_DEFINITION_BLOCK, \ + .features = NEURONSPI_BOARD_E16DI_HW_FEATURES \ +} +struct neuronspi_board_combination NEURONSPI_BOARD_E16DI_HW_COMBINATION[] = {NEURONSPI_BOARD_E16DI_HW_DEFINITION}; + +// E-8Di8Ro_P-11DiR485 (xS10) +#define NEURONSPI_BOARD_E8DI8ROP11DIR485_HW_DEFINITION_BLOCK_SIZE 47 +static u32 NEURONSPI_BOARD_E8DI8ROP11DIR485_HW_DEFINITION_BLOCK[NEURONSPI_BOARD_E8DI8ROP11DIR485_HW_DEFINITION_BLOCK_SIZE] = { + 0, 20, // Register block beginning and size + NEURONSPI_REGFUN_DI_READ | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 0 + NEURONSPI_REGFUN_DO_RW | NEURONSPI_REGFLAG_ACC_10HZ, // 1 + NEURONSPI_REGFUN_MWD_STATUS | NEURONSPI_REGFLAG_ACC_6SEC | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 2 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 3 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 4 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 5 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 6 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 7 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 8 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 9 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 10 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 11 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 12 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 13 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 14 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 15 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 16 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 17 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 18 + NEURONSPI_REGFUN_LED_RW | NEURONSPI_REGFLAG_ACC_1HZ, // 19 + 1000, 23, // Register block beginning and size + NEURONSPI_REGFUN_SW_VER | NEURONSPI_REGFLAG_ACC_ONCE, // 1000 + NEURONSPI_REGFUN_DIDO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE, // 1001 + NEURONSPI_REGFUN_UAIO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE, // 1002 + NEURONSPI_REGFUN_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE, // 1003 + NEURONSPI_REGFUN_FLASH_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE, // 1004 + NEURONSPI_REGFUN_SERIAL_NR_LOWER | NEURONSPI_REGFLAG_ACC_ONCE, // 1005 + NEURONSPI_REGFUN_SERIAL_NR_UPPER | NEURONSPI_REGFLAG_ACC_ONCE, // 1006 + NEURONSPI_REGFUN_INTERRUPTS | NEURONSPI_REGFLAG_ACC_AFAP, // 1007 + NEURONSPI_REGFUN_MWD_TO | NEURONSPI_REGFLAG_ACC_6SEC, // 1008 + NEURONSPI_REGFUN_V_REF_INT | NEURONSPI_REGFLAG_ACC_ONCE, // 1009 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1010 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1011 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1012 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1013 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1014 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1015 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1016 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1017 + NEURONSPI_REGFUN_DS_ENABLE | NEURONSPI_REGFLAG_ACC_1HZ, // 1018 + NEURONSPI_REGFUN_DS_POLARITY | NEURONSPI_REGFLAG_ACC_1HZ, // 1019 + NEURONSPI_REGFUN_DS_TOGGLE | NEURONSPI_REGFLAG_ACC_1HZ, // 1020 + NEURONSPI_REGFUN_RS485_CONFIG | NEURONSPI_REGFLAG_ACC_6SEC, // 1021 + NEURONSPI_REGFUN_RS485_ADDRESS | NEURONSPI_REGFLAG_ACC_6SEC // 1022 +}; + +#define NEURONSPI_BOARD_E8DI8ROP11DIR485_HW_FEATURES { \ + .do_count = 0, \ + .ro_count = 8, \ + .ds_count = 8, \ + .di_count = 8, \ + .led_count = 0, \ + .stm_ai_count = 0, \ + .stm_ao_count = 0, \ + .sec_ai_count = 0, \ + .sec_ao_count = 0, \ + .uart_master_count = 0, \ + .uart_slave_count = 1, \ + .pwm_channel_count = 0, \ + .wd_count = 1, \ + .extension_sys_count = 1, \ + .light_count = 0, \ + .owire_count = 0, \ +} + +#define NEURONSPI_BOARD_E8DI8ROP11DIR485_HW_DEFINITION { \ + .combination_board_id = 4, \ + .lower_board_id = NEURONSPI_BOARD_LOWER_E8DI8RO_ID, \ + .upper_board_id = NEURONSPI_BOARD_UPPER_P11DIR485_ID, \ + .block_count = NEURONSPI_BOARD_E8DI8ROP11DIR485_HW_DEFINITION_BLOCK_SIZE, \ + .name_length = 19, \ + .combination_name = "E_8Di8Ro_P_11DiR485", \ + .blocks = NEURONSPI_BOARD_E8DI8ROP11DIR485_HW_DEFINITION_BLOCK, \ + .features = NEURONSPI_BOARD_E8DI8ROP11DIR485_HW_FEATURES \ +} +struct neuronspi_board_combination NEURONSPI_BOARD_E8DI8ROP11DIR485_HW_COMBINATION[] = {NEURONSPI_BOARD_E8DI8ROP11DIR485_HW_DEFINITION}; + +// E-14Ro_P-11DiR485 (xS40) +#define NEURONSPI_BOARD_E14ROP11DIR485_HW_DEFINITION_BLOCK_SIZE 71 +static u32 NEURONSPI_BOARD_E14ROP11DIR485_HW_DEFINITION_BLOCK[NEURONSPI_BOARD_E14ROP11DIR485_HW_DEFINITION_BLOCK_SIZE] = { + 0, 36, // Register block beginning and size + NEURONSPI_REGFUN_DI_READ | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 0 + NEURONSPI_REGFUN_DO_RW | NEURONSPI_REGFLAG_ACC_10HZ, // 1 + NEURONSPI_REGFUN_MWD_STATUS | NEURONSPI_REGFLAG_ACC_6SEC | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 2 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 3 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 4 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 5 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 6 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 7 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 8 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 9 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 10 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 11 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 12 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 13 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 14 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 15 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 16 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 17 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 18 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 19 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 20 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 21 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 22 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 23 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 24 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 25 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 26 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 27 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 28 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 29 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 30 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 31 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 32 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 33 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 34 + NEURONSPI_REGFUN_LED_RW | NEURONSPI_REGFLAG_ACC_1HZ, // 35 + 1000, 31, // Register block beginning and size + NEURONSPI_REGFUN_SW_VER | NEURONSPI_REGFLAG_ACC_ONCE, // 1000 + NEURONSPI_REGFUN_DIDO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE, // 1001 + NEURONSPI_REGFUN_UAIO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE, // 1002 + NEURONSPI_REGFUN_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE, // 1003 + NEURONSPI_REGFUN_FLASH_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE, // 1004 + NEURONSPI_REGFUN_SERIAL_NR_LOWER | NEURONSPI_REGFLAG_ACC_ONCE, // 1005 + NEURONSPI_REGFUN_SERIAL_NR_UPPER | NEURONSPI_REGFLAG_ACC_ONCE, // 1006 + NEURONSPI_REGFUN_INTERRUPTS | NEURONSPI_REGFLAG_ACC_AFAP, // 1007 + NEURONSPI_REGFUN_MWD_TO | NEURONSPI_REGFLAG_ACC_6SEC, // 1008 + NEURONSPI_REGFUN_V_REF_INT | NEURONSPI_REGFLAG_ACC_ONCE, // 1009 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1010 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1011 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1012 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1013 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1014 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1015 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1016 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1017 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1018 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1019 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1020 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1021 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1022 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1023 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1024 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1025 + NEURONSPI_REGFUN_DS_ENABLE | NEURONSPI_REGFLAG_ACC_1HZ, // 1026 + NEURONSPI_REGFUN_DS_POLARITY | NEURONSPI_REGFLAG_ACC_1HZ, // 1027 + NEURONSPI_REGFUN_DS_TOGGLE | NEURONSPI_REGFLAG_ACC_1HZ, // 1028 + NEURONSPI_REGFUN_RS485_CONFIG | NEURONSPI_REGFLAG_ACC_6SEC, // 1029 + NEURONSPI_REGFUN_RS485_ADDRESS | NEURONSPI_REGFLAG_ACC_6SEC // 1030 +}; + +#define NEURONSPI_BOARD_E14ROP11DIR485_HW_FEATURES { \ + .do_count = 0, \ + .ro_count = 14, \ + .ds_count = 8, \ + .di_count = 8, \ + .led_count = 0, \ + .stm_ai_count = 0, \ + .stm_ao_count = 0, \ + .sec_ai_count = 0, \ + .sec_ao_count = 0, \ + .uart_master_count = 0, \ + .uart_slave_count = 1, \ + .pwm_channel_count = 0, \ + .wd_count = 1, \ + .extension_sys_count = 1, \ + .light_count = 0, \ + .owire_count = 0, \ +} + +#define NEURONSPI_BOARD_E14ROP11DIR485_HW_DEFINITION { \ + .combination_board_id = 5, \ + .lower_board_id = NEURONSPI_BOARD_LOWER_E14RO_ID, \ + .upper_board_id = NEURONSPI_BOARD_UPPER_P11DIR485_ID, \ + .name_length = 17, \ + .combination_name = "E_14Ro_P_11DiR485", \ + .block_count = NEURONSPI_BOARD_E14ROP11DIR485_HW_DEFINITION_BLOCK_SIZE, \ + .blocks = NEURONSPI_BOARD_E14ROP11DIR485_HW_DEFINITION_BLOCK, \ + .features = NEURONSPI_BOARD_E14ROP11DIR485_HW_FEATURES \ +} +struct neuronspi_board_combination NEURONSPI_BOARD_E14ROP11DIR485_HW_COMBINATION[] = {NEURONSPI_BOARD_E14ROP11DIR485_HW_DEFINITION}; + +// E-16Di_P-11DiR485 (xS30) +#define NEURONSPI_BOARD_E16DIP11DIR485_HW_DEFINITION_BLOCK_SIZE 92 +static u32 NEURONSPI_BOARD_E16DIP11DIR485_HW_DEFINITION_BLOCK[NEURONSPI_BOARD_E16DIP11DIR485_HW_DEFINITION_BLOCK_SIZE] = { + 0, 52, // Register block beginning and size + NEURONSPI_REGFUN_DI_READ | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 0 + NEURONSPI_REGFUN_DI_READ | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1 + NEURONSPI_REGFUN_MWD_STATUS | NEURONSPI_REGFLAG_ACC_6SEC, // 2 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 3 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 4 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 5 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 6 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 7 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 8 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 9 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 10 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 11 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 12 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 13 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 14 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 15 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 16 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 17 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 18 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 19 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 20 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 21 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 22 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 23 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 24 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 25 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 26 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 27 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 28 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 29 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 30 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 31 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 32 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 33 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 34 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 35 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 36 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 37 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 38 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 39 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 40 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 41 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 42 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 43 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 44 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 45 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 46 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 47 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 48 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 49 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 50 + NEURONSPI_REGFUN_LED_RW | NEURONSPI_REGFLAG_ACC_1HZ, // 51 + 1000, 36, // Register block beginning and size + NEURONSPI_REGFUN_SW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1000 + NEURONSPI_REGFUN_DIDO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1001 + NEURONSPI_REGFUN_UAIO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1002 + NEURONSPI_REGFUN_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1003 + NEURONSPI_REGFUN_FLASH_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1004 + NEURONSPI_REGFUN_SERIAL_NR_LOWER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1005 + NEURONSPI_REGFUN_SERIAL_NR_UPPER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1006 + NEURONSPI_REGFUN_INTERRUPTS | NEURONSPI_REGFLAG_ACC_AFAP, // 1007 + NEURONSPI_REGFUN_MWD_TO | NEURONSPI_REGFLAG_ACC_6SEC, // 1008 + NEURONSPI_REGFUN_V_REF_INT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1009 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1010 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1011 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1012 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1013 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1014 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1015 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1016 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1017 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1018 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1019 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1020 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1021 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1022 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1023 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1024 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1025 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1026 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1027 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1028 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1029 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1030 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1031 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1032 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1033 + NEURONSPI_REGFUN_RS485_CONFIG | NEURONSPI_REGFLAG_ACC_6SEC, // 1034 + NEURONSPI_REGFUN_RS485_ADDRESS | NEURONSPI_REGFLAG_ACC_6SEC // 1035 +}; + +#define NEURONSPI_BOARD_E16DIP11DIR485_HW_FEATURES { \ + .do_count = 0, \ + .ro_count = 0, \ + .ds_count = 0, \ + .di_count = 23, \ + .led_count = 0, \ + .stm_ai_count = 0, \ + .stm_ao_count = 0, \ + .sec_ai_count = 0, \ + .sec_ao_count = 0, \ + .uart_master_count = 0, \ + .uart_slave_count = 1, \ + .pwm_channel_count = 0, \ + .wd_count = 1, \ + .extension_sys_count = 1, \ + .light_count = 0, \ + .owire_count = 0, \ +} + +#define NEURONSPI_BOARD_E16DIP11DIR485_HW_DEFINITION { \ + .combination_board_id = 6, \ + .lower_board_id = NEURONSPI_BOARD_LOWER_E16DI_ID, \ + .upper_board_id = NEURONSPI_BOARD_UPPER_P11DIR485_ID, \ + .name_length = 17, \ + .combination_name = "E_16Di_P_11DiR485", \ + .block_count = NEURONSPI_BOARD_E16DIP11DIR485_HW_DEFINITION_BLOCK_SIZE, \ + .blocks = NEURONSPI_BOARD_E16DIP11DIR485_HW_DEFINITION_BLOCK, \ + .features = NEURONSPI_BOARD_E16DIP11DIR485_HW_FEATURES \ +} +struct neuronspi_board_combination NEURONSPI_BOARD_E16DIP11DIR485_HW_COMBINATION[] = {NEURONSPI_BOARD_E16DIP11DIR485_HW_DEFINITION}; + +// E-14Ro_U-14Ro (M403) +#define NEURONSPI_BOARD_E14ROU14RO_HW_DEFINITION_BLOCK_SIZE 17 +static u32 NEURONSPI_BOARD_E14ROU14RO_HW_DEFINITION_BLOCK[NEURONSPI_BOARD_E14ROU14RO_HW_DEFINITION_BLOCK_SIZE] = { + 0, 3, // Register block beginning and size + NEURONSPI_REGFUN_DO_RW | NEURONSPI_REGFLAG_ACC_10HZ, // 0 + NEURONSPI_REGFUN_DO_RW | NEURONSPI_REGFLAG_ACC_10HZ, // 1 + NEURONSPI_REGFUN_MWD_STATUS | NEURONSPI_REGFLAG_ACC_6SEC | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 2 + 1000, 10, // Register block beginning and size + NEURONSPI_REGFUN_SW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1000 + NEURONSPI_REGFUN_DIDO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1001 + NEURONSPI_REGFUN_UAIO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1002 + NEURONSPI_REGFUN_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1003 + NEURONSPI_REGFUN_FLASH_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1004 + NEURONSPI_REGFUN_SERIAL_NR_LOWER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1005 + NEURONSPI_REGFUN_SERIAL_NR_UPPER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1006 + NEURONSPI_REGFUN_INTERRUPTS | NEURONSPI_REGFLAG_ACC_AFAP, // 1007 + NEURONSPI_REGFUN_MWD_TO | NEURONSPI_REGFLAG_ACC_6SEC, // 1008 + NEURONSPI_REGFUN_V_REF_INT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1009 +}; + +#define NEURONSPI_BOARD_E14ROU14RO_HW_FEATURES { \ + .do_count = 0, \ + .ro_count = 28, \ + .ds_count = 0, \ + .di_count = 0, \ + .led_count = 0, \ + .stm_ai_count = 0, \ + .stm_ao_count = 0, \ + .sec_ai_count = 0, \ + .sec_ao_count = 0, \ + .uart_master_count = 0, \ + .uart_slave_count = 0, \ + .pwm_channel_count = 0, \ + .wd_count = 1, \ + .extension_sys_count = 1, \ + .light_count = 0, \ + .owire_count = 0, \ +} + +#define NEURONSPI_BOARD_E14ROU14RO_HW_DEFINITION { \ + .combination_board_id = 7, \ + .lower_board_id = NEURONSPI_BOARD_LOWER_E14RO_ID, \ + .upper_board_id = NEURONSPI_BOARD_UPPER_U14RO_ID, \ + .name_length = 13, \ + .combination_name = "E_14Ro_U_14Ro", \ + .block_count = NEURONSPI_BOARD_E14ROU14RO_HW_DEFINITION_BLOCK_SIZE, \ + .blocks = NEURONSPI_BOARD_E14ROU14RO_HW_DEFINITION_BLOCK, \ + .features = NEURONSPI_BOARD_E14ROU14RO_HW_FEATURES \ +} +struct neuronspi_board_combination NEURONSPI_BOARD_E14ROU14RO_HW_COMBINATION[] = {NEURONSPI_BOARD_E14ROU14RO_HW_DEFINITION}; + +// E-16Di_U-14Ro (M203) +#define NEURONSPI_BOARD_E16DIU14RO_HW_DEFINITION_BLOCK_SIZE 68 +static u32 NEURONSPI_BOARD_E16DIU14RO_HW_DEFINITION_BLOCK[NEURONSPI_BOARD_E16DIU14RO_HW_DEFINITION_BLOCK_SIZE] = { + 0, 35, // Register block beginning and size + NEURONSPI_REGFUN_DI_READ | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 0 + NEURONSPI_REGFUN_DO_RW | NEURONSPI_REGFLAG_ACC_10HZ, // 1 + NEURONSPI_REGFUN_MWD_STATUS | NEURONSPI_REGFLAG_ACC_6SEC | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 2 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 3 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 4 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 5 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 6 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 7 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 8 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 9 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 10 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 11 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 12 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 13 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 14 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 15 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 16 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 17 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 18 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 19 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 20 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 21 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 22 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 23 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 24 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 25 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 26 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 27 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 28 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 29 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 30 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 31 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 32 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 33 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 34 + 1000, 29, // Register block beginning and size + NEURONSPI_REGFUN_SW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1000 + NEURONSPI_REGFUN_DIDO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1001 + NEURONSPI_REGFUN_UAIO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1002 + NEURONSPI_REGFUN_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1003 + NEURONSPI_REGFUN_FLASH_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1004 + NEURONSPI_REGFUN_SERIAL_NR_LOWER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1005 + NEURONSPI_REGFUN_SERIAL_NR_UPPER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1006 + NEURONSPI_REGFUN_INTERRUPTS | NEURONSPI_REGFLAG_ACC_AFAP, // 1007 + NEURONSPI_REGFUN_MWD_TO | NEURONSPI_REGFLAG_ACC_6SEC, // 1008 + NEURONSPI_REGFUN_V_REF_INT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1009 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1010 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1011 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1012 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1013 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1014 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1015 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1016 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1017 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1018 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1019 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1020 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1021 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1022 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1023 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1024 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1025 + NEURONSPI_REGFUN_DS_ENABLE | NEURONSPI_REGFLAG_ACC_1HZ, // 1026 + NEURONSPI_REGFUN_DS_POLARITY | NEURONSPI_REGFLAG_ACC_1HZ, // 1027 + NEURONSPI_REGFUN_DS_TOGGLE | NEURONSPI_REGFLAG_ACC_1HZ, // 1028 +}; + +#define NEURONSPI_BOARD_E16DIU14RO_HW_FEATURES { \ + .do_count = 0, \ + .ro_count = 14, \ + .ds_count = 14, \ + .di_count = 16, \ + .led_count = 0, \ + .stm_ai_count = 0, \ + .stm_ao_count = 0, \ + .sec_ai_count = 0, \ + .sec_ao_count = 0, \ + .uart_master_count = 0, \ + .uart_slave_count = 0, \ + .pwm_channel_count = 0, \ + .wd_count = 1, \ + .extension_sys_count = 0, \ + .light_count = 0, \ + .owire_count = 0, \ +} + +#define NEURONSPI_BOARD_E16DIU14RO_HW_DEFINITION { \ + .combination_board_id = 8, \ + .lower_board_id = NEURONSPI_BOARD_LOWER_E16DI_ID, \ + .upper_board_id = NEURONSPI_BOARD_UPPER_U14RO_ID, \ + .name_length = 13, \ + .combination_name = "E_16Di_U_14Ro", \ + .block_count = NEURONSPI_BOARD_E16DIU14RO_HW_DEFINITION_BLOCK_SIZE, \ + .blocks = NEURONSPI_BOARD_E16DIU14RO_HW_DEFINITION_BLOCK, \ + .features = NEURONSPI_BOARD_E16DIU14RO_HW_FEATURES \ +} +struct neuronspi_board_combination NEURONSPI_BOARD_E16DIU14RO_HW_COMBINATION[] = {NEURONSPI_BOARD_E16DIU14RO_HW_DEFINITION}; + +// E-14Ro_U-14Di (L503) +#define NEURONSPI_BOARD_E14ROU14DI_HW_DEFINITION_BLOCK_SIZE 62 +static u32 NEURONSPI_BOARD_E14ROU14DI_HW_DEFINITION_BLOCK[NEURONSPI_BOARD_E14ROU14DI_HW_DEFINITION_BLOCK_SIZE] = { + 0, 31, // Register block beginning and size + NEURONSPI_REGFUN_DI_READ | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 0 + NEURONSPI_REGFUN_DO_RW | NEURONSPI_REGFLAG_ACC_10HZ, // 1 + NEURONSPI_REGFUN_MWD_STATUS | NEURONSPI_REGFLAG_ACC_6SEC | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 2 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 3 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 4 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 5 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 6 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 7 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 8 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 9 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 10 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 11 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 12 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 13 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 14 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 15 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 16 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 17 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 18 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 19 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 20 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 21 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 22 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 23 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 24 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 25 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 26 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 27 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 28 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 29 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 30 + 1000, 27, // Register block beginning and size + NEURONSPI_REGFUN_SW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1000 + NEURONSPI_REGFUN_DIDO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1001 + NEURONSPI_REGFUN_UAIO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1002 + NEURONSPI_REGFUN_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1003 + NEURONSPI_REGFUN_FLASH_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1004 + NEURONSPI_REGFUN_SERIAL_NR_LOWER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1005 + NEURONSPI_REGFUN_SERIAL_NR_UPPER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1006 + NEURONSPI_REGFUN_INTERRUPTS | NEURONSPI_REGFLAG_ACC_AFAP, // 1007 + NEURONSPI_REGFUN_MWD_TO | NEURONSPI_REGFLAG_ACC_6SEC, // 1008 + NEURONSPI_REGFUN_V_REF_INT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1009 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1010 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1011 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1012 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1013 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1014 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1015 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1016 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1017 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1018 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1019 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1020 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1021 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1022 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1023 + NEURONSPI_REGFUN_DS_ENABLE | NEURONSPI_REGFLAG_ACC_1HZ, // 1024 + NEURONSPI_REGFUN_DS_POLARITY | NEURONSPI_REGFLAG_ACC_1HZ, // 1025 + NEURONSPI_REGFUN_DS_TOGGLE | NEURONSPI_REGFLAG_ACC_1HZ // 1026 +}; + +#define NEURONSPI_BOARD_E14ROU14DI_HW_FEATURES { \ + .do_count = 0, \ + .ro_count = 14, \ + .ds_count = 14, \ + .di_count = 14, \ + .led_count = 0, \ + .stm_ai_count = 0, \ + .stm_ao_count = 0, \ + .sec_ai_count = 0, \ + .sec_ao_count = 0, \ + .uart_master_count = 0, \ + .uart_slave_count = 0, \ + .pwm_channel_count = 0, \ + .wd_count = 1, \ + .extension_sys_count = 0, \ + .light_count = 0, \ + .owire_count = 0, \ +} + +#define NEURONSPI_BOARD_E14ROU14DI_HW_DEFINITION { \ + .combination_board_id = 9, \ + .lower_board_id = NEURONSPI_BOARD_LOWER_E14RO_ID, \ + .upper_board_id = NEURONSPI_BOARD_UPPER_U14DI_ID, \ + .name_length = 13, \ + .combination_name = "E_14Ro_U_14Di", \ + .block_count = NEURONSPI_BOARD_E14ROU14DI_HW_DEFINITION_BLOCK_SIZE, \ + .blocks = NEURONSPI_BOARD_E14ROU14DI_HW_DEFINITION_BLOCK, \ + .features = NEURONSPI_BOARD_E14ROU14DI_HW_FEATURES \ +} +struct neuronspi_board_combination NEURONSPI_BOARD_E14ROU14DI_HW_COMBINATION[] = {NEURONSPI_BOARD_E14ROU14DI_HW_DEFINITION}; + + +// E-16Di_U-14Di (M303) +#define NEURONSPI_BOARD_E16DIU14DI_HW_DEFINITION_BLOCK_SIZE 107 +static u32 NEURONSPI_BOARD_E16DIU14DI_HW_DEFINITION_BLOCK[NEURONSPI_BOARD_E16DIU14DI_HW_DEFINITION_BLOCK_SIZE] = { + 0, 63, // Register block beginning and size + NEURONSPI_REGFUN_DI_READ | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 0 + NEURONSPI_REGFUN_DO_RW | NEURONSPI_REGFLAG_ACC_10HZ, // 1 + NEURONSPI_REGFUN_MWD_STATUS | NEURONSPI_REGFLAG_ACC_6SEC | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 2 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 3 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 4 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 5 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 6 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 7 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 8 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 9 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 10 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 11 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 12 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 13 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 14 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 15 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 16 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 17 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 18 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 19 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 20 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 21 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 22 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 23 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 24 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 25 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 26 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 27 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 28 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 29 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 30 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 31 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 32 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 33 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 34 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 35 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 36 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 37 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 38 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 39 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 40 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 41 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 42 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 43 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 44 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 45 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 46 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 47 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 48 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 49 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 50 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 51 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 52 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 53 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 54 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 55 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 56 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 57 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 58 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 59 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 60 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 61 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 62 + 1000, 40, // Register block beginning and size + NEURONSPI_REGFUN_SW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1000 + NEURONSPI_REGFUN_DIDO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1001 + NEURONSPI_REGFUN_UAIO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1002 + NEURONSPI_REGFUN_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1003 + NEURONSPI_REGFUN_FLASH_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1004 + NEURONSPI_REGFUN_SERIAL_NR_LOWER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1005 + NEURONSPI_REGFUN_SERIAL_NR_UPPER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1006 + NEURONSPI_REGFUN_INTERRUPTS | NEURONSPI_REGFLAG_ACC_AFAP, // 1007 + NEURONSPI_REGFUN_MWD_TO | NEURONSPI_REGFLAG_ACC_6SEC, // 1008 + NEURONSPI_REGFUN_V_REF_INT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1009 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1010 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1011 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1012 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1013 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1014 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1015 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1016 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1017 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1018 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1019 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1020 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1021 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1022 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1023 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1024 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1025 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1026 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1027 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1028 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1029 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1030 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1031 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1032 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1033 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1034 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1035 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1036 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1037 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1038 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1039 +}; + +#define NEURONSPI_BOARD_E16DIU14DI_HW_FEATURES { \ + .do_count = 0, \ + .ro_count = 0, \ + .ds_count = 0, \ + .di_count = 30, \ + .led_count = 0, \ + .stm_ai_count = 0, \ + .stm_ao_count = 0, \ + .sec_ai_count = 0, \ + .sec_ao_count = 0, \ + .uart_master_count = 0, \ + .uart_slave_count = 0, \ + .pwm_channel_count = 0, \ + .wd_count = 1, \ + .extension_sys_count = 0, \ + .light_count = 0, \ + .owire_count = 0, \ +} + +#define NEURONSPI_BOARD_E16DIU14DI_HW_DEFINITION { \ + .combination_board_id = 10, \ + .lower_board_id = NEURONSPI_BOARD_LOWER_E16DI_ID, \ + .upper_board_id = NEURONSPI_BOARD_UPPER_U14DI_ID, \ + .name_length = 13, \ + .combination_name = "E_16Di_U_14Di", \ + .block_count = NEURONSPI_BOARD_E16DIU14DI_HW_DEFINITION_BLOCK_SIZE, \ + .blocks = NEURONSPI_BOARD_E16DIU14DI_HW_DEFINITION_BLOCK, \ + .features = NEURONSPI_BOARD_E16DIU14DI_HW_FEATURES \ +} +struct neuronspi_board_combination NEURONSPI_BOARD_E16DIU14DI_HW_COMBINATION[] = {NEURONSPI_BOARD_E16DIU14DI_HW_DEFINITION}; + +// E-4Ai4Ao +#define NEURONSPI_BOARD_E4AI4AO_HW_DEFINITION_BLOCK_SIZE 15 +static u32 NEURONSPI_BOARD_E4AI4AO_HW_DEFINITION_BLOCK[NEURONSPI_BOARD_E4AI4AO_HW_DEFINITION_BLOCK_SIZE] = { + 0, 1, // Register block beginning and size + NEURONSPI_REGFUN_DO_RW | NEURONSPI_REGFLAG_ACC_10HZ | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 0 + 1000, 10, // Register block beginning and size + NEURONSPI_REGFUN_SW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1000 + NEURONSPI_REGFUN_DIDO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1001 + NEURONSPI_REGFUN_UAIO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1002 + NEURONSPI_REGFUN_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1003 + NEURONSPI_REGFUN_FLASH_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1004 + NEURONSPI_REGFUN_SERIAL_NR_LOWER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1005 + NEURONSPI_REGFUN_SERIAL_NR_UPPER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1006 + NEURONSPI_REGFUN_INTERRUPTS | NEURONSPI_REGFLAG_ACC_AFAP, // 1007 + NEURONSPI_REGFUN_MWD_TO | NEURONSPI_REGFLAG_ACC_6SEC, // 1008 + NEURONSPI_REGFUN_V_REF_INT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1009 +}; + +#define NEURONSPI_BOARD_E4AI4AO_HW_FEATURES { \ + .do_count = 0, \ + .ro_count = 0, \ + .ds_count = 0, \ + .di_count = 0, \ + .led_count = 0, \ + .stm_ai_count = 0, \ + .stm_ao_count = 0, \ + .sec_ai_count = 4, \ + .sec_ao_count = 4, \ + .uart_master_count = 0, \ + .uart_slave_count = 0, \ + .pwm_channel_count = 0, \ + .wd_count = 1, \ + .extension_sys_count = 0, \ + .light_count = 0, \ + .owire_count = 0, \ +} + + +#define NEURONSPI_BOARD_E4AI4AO_HW_DEFINITION { \ + .combination_board_id = 11, \ + .lower_board_id = NEURONSPI_BOARD_LOWER_E4AI4AO_ID, \ + .upper_board_id = NEURONSPI_BOARD_UPPER_NONE_ID, \ + .name_length = 8, \ + .combination_name = "E_4Ai4Ao", \ + .block_count = NEURONSPI_BOARD_E4AI4AO_HW_DEFINITION_BLOCK_SIZE, \ + .blocks = NEURONSPI_BOARD_E4AI4AO_HW_DEFINITION_BLOCK, \ + .features = NEURONSPI_BOARD_E4AI4AO_HW_FEATURES \ +} +struct neuronspi_board_combination NEURONSPI_BOARD_E4AI4AO_HW_COMBINATION[] = {NEURONSPI_BOARD_E4AI4AO_HW_DEFINITION}; + +// E-4Ai4Ao_P-6Di5Ro (xS50) +#define NEURONSPI_BOARD_E4AI4AOP6DI5RO_HW_DEFINITION_BLOCK_SIZE 56 +static u32 NEURONSPI_BOARD_E4AI4AOP6DI5RO_HW_DEFINITION_BLOCK[NEURONSPI_BOARD_E4AI4AOP6DI5RO_HW_DEFINITION_BLOCK_SIZE] = { + 0, 27, // Register block beginning and size + NEURONSPI_REGFUN_DI_READ | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 0 + NEURONSPI_REGFUN_DO_RW | NEURONSPI_REGFLAG_ACC_10HZ, // 1 + NEURONSPI_REGFUN_AO_VER2_RW | NEURONSPI_REGFLAG_ACC_10HZ, // 2 + NEURONSPI_REGFUN_AO_VER2_RW | NEURONSPI_REGFLAG_ACC_10HZ, // 3 + NEURONSPI_REGFUN_AO_VER2_RW | NEURONSPI_REGFLAG_ACC_10HZ, // 4 + NEURONSPI_REGFUN_AO_VER2_RW | NEURONSPI_REGFLAG_ACC_10HZ, // 5 + NEURONSPI_REGFUN_AI_VER2_READ_LOWER | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 6 + NEURONSPI_REGFUN_AI_VER2_READ_UPPER | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 7 + NEURONSPI_REGFUN_AI_VER2_READ_LOWER | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 8 + NEURONSPI_REGFUN_AI_VER2_READ_UPPER | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 9 + NEURONSPI_REGFUN_AI_VER2_READ_LOWER | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 10 + NEURONSPI_REGFUN_AI_VER2_READ_UPPER | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 11 + NEURONSPI_REGFUN_AI_VER2_READ_LOWER | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 12 + NEURONSPI_REGFUN_AI_VER2_READ_UPPER | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 13 + NEURONSPI_REGFUN_MWD_STATUS | NEURONSPI_REGFLAG_ACC_6SEC, // 14 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 15 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 16 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 17 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 18 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 19 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 20 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 21 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 22 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 23 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 24 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 25 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 26 + 1000, 25, // Register block beginning and size + NEURONSPI_REGFUN_SW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1000 + NEURONSPI_REGFUN_DIDO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1001 + NEURONSPI_REGFUN_UAIO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1002 + NEURONSPI_REGFUN_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1003 + NEURONSPI_REGFUN_FLASH_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1004 + NEURONSPI_REGFUN_SERIAL_NR_LOWER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1005 + NEURONSPI_REGFUN_SERIAL_NR_UPPER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1006 + NEURONSPI_REGFUN_INTERRUPTS | NEURONSPI_REGFLAG_ACC_AFAP, // 1007 + NEURONSPI_REGFUN_MWD_TO | NEURONSPI_REGFLAG_ACC_6SEC, // 1008 + NEURONSPI_REGFUN_V_REF_INT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1009 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1010 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1011 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1012 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1013 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1014 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1015 + NEURONSPI_REGFUN_DS_ENABLE | NEURONSPI_REGFLAG_ACC_1HZ, // 1016 + NEURONSPI_REGFUN_DS_POLARITY | NEURONSPI_REGFLAG_ACC_1HZ, // 1017 + NEURONSPI_REGFUN_DS_TOGGLE | NEURONSPI_REGFLAG_ACC_1HZ, // 1018 + NEURONSPI_REGFUN_AI_VER2_MODE | NEURONSPI_REGFLAG_ACC_1HZ, // 1019 + NEURONSPI_REGFUN_AI_VER2_MODE | NEURONSPI_REGFLAG_ACC_1HZ, // 1020 + NEURONSPI_REGFUN_AI_VER2_MODE | NEURONSPI_REGFLAG_ACC_1HZ, // 1021 + NEURONSPI_REGFUN_AI_VER2_MODE | NEURONSPI_REGFLAG_ACC_1HZ, // 1022 + NEURONSPI_REGFUN_RS485_CONFIG | NEURONSPI_REGFLAG_ACC_6SEC, // 1023 + NEURONSPI_REGFUN_RS485_ADDRESS | NEURONSPI_REGFLAG_ACC_6SEC // 1024 +}; + +#define NEURONSPI_BOARD_E4AI4AOP6DI5RO_HW_FEATURES { \ + .do_count = 0, \ + .ro_count = 6, \ + .ds_count = 5, \ + .di_count = 5, \ + .led_count = 0, \ + .stm_ai_count = 0, \ + .stm_ao_count = 0, \ + .sec_ai_count = 4, \ + .sec_ao_count = 4, \ + .uart_master_count = 0, \ + .uart_slave_count = 1, \ + .pwm_channel_count = 0, \ + .wd_count = 1, \ + .extension_sys_count = 1, \ + .light_count = 0, \ + .owire_count = 0, \ +} + +#define NEURONSPI_BOARD_E4AI4AOP6DI5RO_HW_DEFINITION { \ + .combination_board_id = 12, \ + .lower_board_id = NEURONSPI_BOARD_LOWER_E4AI4AO_ID, \ + .upper_board_id = NEURONSPI_BOARD_UPPER_P6DI5RO_ID, \ + .name_length = 17, \ + .combination_name = "E_4Ai4Ao_P_6Di5Ro", \ + .block_count = NEURONSPI_BOARD_E4AI4AOP6DI5RO_HW_DEFINITION_BLOCK_SIZE, \ + .blocks = NEURONSPI_BOARD_E4AI4AOP6DI5RO_HW_DEFINITION_BLOCK, \ + .features = NEURONSPI_BOARD_E4AI4AOP6DI5RO_HW_FEATURES \ +} +struct neuronspi_board_combination NEURONSPI_BOARD_E4AI4AOP6DI5RO_HW_COMBINATION[] = {NEURONSPI_BOARD_E4AI4AOP6DI5RO_HW_DEFINITION}; + +// B-485 +#define NEURONSPI_BOARD_B485_HW_DEFINITION_BLOCK_SIZE 15 +static u32 NEURONSPI_BOARD_B485_HW_DEFINITION_BLOCK[NEURONSPI_BOARD_B485_HW_DEFINITION_BLOCK_SIZE] = { + 0, 1, // Register block beginning and size + NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE, // 0 + 1000, 10, + NEURONSPI_REGFUN_SW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1000 + NEURONSPI_REGFUN_DIDO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1001 + NEURONSPI_REGFUN_UAIO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1002 + NEURONSPI_REGFUN_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1003 + NEURONSPI_REGFUN_FLASH_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1004 + NEURONSPI_REGFUN_SERIAL_NR_LOWER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1005 + NEURONSPI_REGFUN_SERIAL_NR_UPPER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1006 + NEURONSPI_REGFUN_INTERRUPTS | NEURONSPI_REGFLAG_ACC_AFAP, // 1007 + NEURONSPI_REGFUN_MWD_TO | NEURONSPI_REGFLAG_ACC_6SEC, // 1008 + NEURONSPI_REGFUN_V_REF_INT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1009 +}; + +#define NEURONSPI_BOARD_B485_HW_FEATURES { \ + .do_count = 0, \ + .ro_count = 0, \ + .ds_count = 0, \ + .di_count = 0, \ + .led_count = 0, \ + .stm_ai_count = 0, \ + .stm_ao_count = 0, \ + .sec_ai_count = 4, \ + .sec_ao_count = 4, \ + .uart_master_count = 1, \ + .uart_slave_count = 0, \ + .pwm_channel_count = 0, \ + .wd_count = 1, \ + .extension_sys_count = 0, \ + .light_count = 0, \ + .owire_count = 0, \ +} + +#define NEURONSPI_BOARD_B485_HW_DEFINITION { \ + .combination_board_id = 13, \ + .lower_board_id = NEURONSPI_BOARD_LOWER_B485_ID, \ + .upper_board_id = NEURONSPI_BOARD_UPPER_NONE_ID, \ + .name_length = 5, \ + .combination_name = "B_485", \ + .block_count = NEURONSPI_BOARD_B485_HW_DEFINITION_BLOCK_SIZE, \ + .blocks = NEURONSPI_BOARD_B485_HW_DEFINITION_BLOCK, \ + .features = NEURONSPI_BOARD_B485_HW_FEATURES \ +} +struct neuronspi_board_combination NEURONSPI_BOARD_B485_HW_COMBINATION[] = {NEURONSPI_BOARD_B485_HW_DEFINITION}; + +// E-4Light (M613) +#define NEURONSPI_BOARD_E4LIGHT_HW_DEFINITION_BLOCK_SIZE 35 +static u32 NEURONSPI_BOARD_E4LIGHT_HW_DEFINITION_BLOCK[NEURONSPI_BOARD_E4LIGHT_HW_DEFINITION_BLOCK_SIZE] = { + 0, 21, // Register block beginning and size + NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE, // 0 + NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE, // 1 + NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE, // 2 + NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE, // 3 + NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE, // 4 + NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE, // 5 + NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE, // 6 + NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE, // 7 + NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE, // 8 + NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE, // 9 + NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE, // 10 + NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE, // 11 + NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE, // 12 + NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE, // 13 + NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE, // 14 + NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE, // 15 + NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE, // 16 + NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE, // 17 + NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE, // 18 + NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE, // 19 + NEURONSPI_REGFUN_NONE_TEST | NEURONSPI_REGFLAG_ACC_ONCE, // 20 + 1000, 10, + NEURONSPI_REGFUN_SW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1000 + NEURONSPI_REGFUN_DIDO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1001 + NEURONSPI_REGFUN_UAIO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1002 + NEURONSPI_REGFUN_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1003 + NEURONSPI_REGFUN_FLASH_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1004 + NEURONSPI_REGFUN_SERIAL_NR_LOWER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1005 + NEURONSPI_REGFUN_SERIAL_NR_UPPER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY,// 1006 + NEURONSPI_REGFUN_INTERRUPTS | NEURONSPI_REGFLAG_ACC_AFAP, // 1007 + NEURONSPI_REGFUN_MWD_TO | NEURONSPI_REGFLAG_ACC_6SEC, // 1008 + NEURONSPI_REGFUN_V_REF_INT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1009 +}; + +#define NEURONSPI_BOARD_E4LIGHT_HW_FEATURES { \ + .do_count = 0, \ + .ro_count = 0, \ + .ds_count = 0, \ + .di_count = 0, \ + .led_count = 0, \ + .stm_ai_count = 0, \ + .stm_ao_count = 0, \ + .sec_ai_count = 0, \ + .sec_ao_count = 0, \ + .uart_master_count = 0, \ + .uart_slave_count = 0, \ + .pwm_channel_count = 0, \ + .wd_count = 1, \ + .extension_sys_count = 0, \ + .light_count = 4, \ + .owire_count = 0, \ +} + +#define NEURONSPI_BOARD_E4LIGHT_HW_DEFINITION { \ + .combination_board_id = 14, \ + .lower_board_id = NEURONSPI_BOARD_LOWER_E4LIGHT_ID, \ + .upper_board_id = NEURONSPI_BOARD_UPPER_NONE_ID, \ + .name_length = 8, \ + .combination_name = "E_4Light", \ + .block_count = NEURONSPI_BOARD_E4LIGHT_HW_DEFINITION_BLOCK_SIZE, \ + .blocks = NEURONSPI_BOARD_E4LIGHT_HW_DEFINITION_BLOCK, \ + .features = NEURONSPI_BOARD_E4LIGHT_HW_FEATURES \ +} +struct neuronspi_board_combination NEURONSPI_BOARD_E4LIGHT_HW_COMBINATION[] = {NEURONSPI_BOARD_E4LIGHT_HW_DEFINITION}; + +// E-4Ai4Ao_U-6Di5Ro (L503) +#define NEURONSPI_BOARD_E4AI4AOU6DI5RO_HW_DEFINITION_BLOCK_SIZE 56 +static u32 NEURONSPI_BOARD_E4AI4AOU6DI5RO_HW_DEFINITION_BLOCK[NEURONSPI_BOARD_E4AI4AOU6DI5RO_HW_DEFINITION_BLOCK_SIZE] = { + 0, 28, // Register block beginning and size + NEURONSPI_REGFUN_DI_READ | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 0 + NEURONSPI_REGFUN_DO_RW | NEURONSPI_REGFLAG_ACC_10HZ, // 1 + NEURONSPI_REGFUN_AO_VER2_RW | NEURONSPI_REGFLAG_ACC_AFAP, // 2 + NEURONSPI_REGFUN_AO_VER2_RW | NEURONSPI_REGFLAG_ACC_AFAP, // 3 + NEURONSPI_REGFUN_AO_VER2_RW | NEURONSPI_REGFLAG_ACC_AFAP, // 4 + NEURONSPI_REGFUN_AO_VER2_RW | NEURONSPI_REGFLAG_ACC_AFAP, // 5 + NEURONSPI_REGFUN_AI_VER2_READ_LOWER | NEURONSPI_REGFLAG_ACC_AFAP, // 6 + NEURONSPI_REGFUN_AI_VER2_READ_UPPER | NEURONSPI_REGFLAG_ACC_AFAP, // 7 + NEURONSPI_REGFUN_AI_VER2_READ_LOWER | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 8 + NEURONSPI_REGFUN_AI_VER2_READ_UPPER | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 9 + NEURONSPI_REGFUN_AI_VER2_READ_LOWER | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 10 + NEURONSPI_REGFUN_AI_VER2_READ_UPPER | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 11 + NEURONSPI_REGFUN_AI_VER2_READ_LOWER | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 12 + NEURONSPI_REGFUN_AI_VER2_READ_UPPER | NEURONSPI_REGFLAG_ACC_AFAP | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 13 + NEURONSPI_REGFUN_MWD_STATUS | NEURONSPI_REGFLAG_ACC_6SEC | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 14 + NEURONSPI_REGFUN_TX_QUEUE_LEN | NEURONSPI_REGFLAG_ACC_10HZ, // 15 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 16 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 17 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 18 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 19 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 20 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 21 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 22 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 23 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 24 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 25 + NEURONSPI_REGFUN_DI_COUNTER_LOWER | NEURONSPI_REGFLAG_ACC_6SEC, // 26 + NEURONSPI_REGFUN_DI_COUNTER_UPPER | NEURONSPI_REGFLAG_ACC_6SEC, // 27 + 1000, 24, // Register block beginning and size + NEURONSPI_REGFUN_SW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1000 + NEURONSPI_REGFUN_DIDO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1001 + NEURONSPI_REGFUN_UAIO_COUNT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1002 + NEURONSPI_REGFUN_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1003 + NEURONSPI_REGFUN_FLASH_HW_VER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1004 + NEURONSPI_REGFUN_SERIAL_NR_LOWER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1005 + NEURONSPI_REGFUN_SERIAL_NR_UPPER | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1006 + NEURONSPI_REGFUN_INTERRUPTS | NEURONSPI_REGFLAG_ACC_AFAP, // 1007 + NEURONSPI_REGFUN_MWD_TO | NEURONSPI_REGFLAG_ACC_6SEC, // 1008 + NEURONSPI_REGFUN_V_REF_INT | NEURONSPI_REGFLAG_ACC_ONCE | NEURONSPI_REGFLAG_SYS_READ_ONLY, // 1009 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1010 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1011 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1012 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1013 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1014 + NEURONSPI_REGFUN_DI_DEBOUNCE | NEURONSPI_REGFLAG_ACC_6SEC, // 1015 + NEURONSPI_REGFUN_DS_ENABLE | NEURONSPI_REGFLAG_ACC_1HZ, // 1016 + NEURONSPI_REGFUN_DS_POLARITY | NEURONSPI_REGFLAG_ACC_1HZ, // 1017 + NEURONSPI_REGFUN_DS_TOGGLE | NEURONSPI_REGFLAG_ACC_1HZ, // 1018 + NEURONSPI_REGFUN_AI_VER2_MODE | NEURONSPI_REGFLAG_ACC_1HZ, // 1019 + NEURONSPI_REGFUN_AI_VER2_MODE | NEURONSPI_REGFLAG_ACC_1HZ, // 1020 + NEURONSPI_REGFUN_AI_VER2_MODE | NEURONSPI_REGFLAG_ACC_1HZ, // 1021 + NEURONSPI_REGFUN_AI_VER2_MODE | NEURONSPI_REGFLAG_ACC_1HZ, // 1022 + NEURONSPI_REGFUN_RS485_CONFIG | NEURONSPI_REGFLAG_ACC_6SEC // 1023 +}; + +#define NEURONSPI_BOARD_E4AI4AOU6DI5RO_HW_FEATURES { \ + .do_count = 0, \ + .ro_count = 5, \ + .ds_count = 5, \ + .di_count = 6, \ + .led_count = 0, \ + .stm_ai_count = 0, \ + .stm_ao_count = 0, \ + .sec_ai_count = 4, \ + .sec_ao_count = 4, \ + .uart_master_count = 0, \ + .uart_slave_count = 0, \ + .pwm_channel_count = 0, \ + .wd_count = 1, \ + .extension_sys_count = 0, \ + .light_count = 4, \ + .owire_count = 0, \ +} + +#define NEURONSPI_BOARD_E4AI4AOU6DI5RO_HW_DEFINITION { \ + .combination_board_id = 15, \ + .lower_board_id = NEURONSPI_BOARD_LOWER_E4AI4AO_ID, \ + .upper_board_id = NEURONSPI_BOARD_UPPER_U6DI5RO_ID, \ + .name_length = 17, \ + .combination_name = "E_4Ai4Ao_U_6Di5Ro", \ + .block_count = NEURONSPI_BOARD_E4AI4AOU6DI5RO_HW_DEFINITION_BLOCK_SIZE, \ + .blocks = NEURONSPI_BOARD_E4AI4AOU6DI5RO_HW_DEFINITION_BLOCK, \ + .features = NEURONSPI_BOARD_E4AI4AOU6DI5RO_HW_FEATURES \ +} +struct neuronspi_board_combination NEURONSPI_BOARD_E4AI4AOU6DI5RO_HW_COMBINATION[] = {NEURONSPI_BOARD_E4AI4AOU6DI5RO_HW_DEFINITION}; + +/******************** + * Data Definitions * + ********************/ + +struct platform_device *neuron_plc_dev; + +struct neuronspi_board_combination NEURONSPI_MODEL_S103_HW_DEFINITION_BOARD[NEURONSPI_MODEL_S103_HW_DEFINITION_BOARD_SIZE] = { + NEURONSPI_BOARD_B1000_HW_DEFINITION +}; + +struct neuronspi_board_combination NEURONSPI_MODEL_S103G_HW_DEFINITION_BOARD[NEURONSPI_MODEL_S103G_HW_DEFINITION_BOARD_SIZE] = { + NEURONSPI_BOARD_B1000_HW_DEFINITION +}; + +struct neuronspi_board_combination NEURONSPI_MODEL_S103IQ_HW_DEFINITION_BOARD[NEURONSPI_MODEL_S103IQ_HW_DEFINITION_BOARD_SIZE] = { + NEURONSPI_BOARD_B1000_HW_DEFINITION +}; + +struct neuronspi_board_combination NEURONSPI_MODEL_S103EO_HW_DEFINITION_BOARD[NEURONSPI_MODEL_S103EO_HW_DEFINITION_BOARD_SIZE] = { + NEURONSPI_BOARD_B1000_HW_DEFINITION +}; + +struct neuronspi_board_combination NEURONSPI_MODEL_M103_HW_DEFINITION_BOARD[NEURONSPI_MODEL_M103_HW_DEFINITION_BOARD_SIZE] = { + NEURONSPI_BOARD_B1000_HW_DEFINITION, NEURONSPI_BOARD_E8DI8RO_HW_DEFINITION +}; + +struct neuronspi_board_combination NEURONSPI_MODEL_M203_HW_DEFINITION_BOARD[NEURONSPI_MODEL_M203_HW_DEFINITION_BOARD_SIZE] = { + NEURONSPI_BOARD_B1000_HW_DEFINITION, NEURONSPI_BOARD_E16DIU14RO_HW_DEFINITION +}; + +struct neuronspi_board_combination NEURONSPI_MODEL_M303_HW_DEFINITION_BOARD[NEURONSPI_MODEL_M303_HW_DEFINITION_BOARD_SIZE] = { + NEURONSPI_BOARD_B1000_HW_DEFINITION, NEURONSPI_BOARD_E16DIU14DI_HW_DEFINITION +}; + +struct neuronspi_board_combination NEURONSPI_MODEL_M403_HW_DEFINITION_BOARD[NEURONSPI_MODEL_M403_HW_DEFINITION_BOARD_SIZE] = { + NEURONSPI_BOARD_B1000_HW_DEFINITION, NEURONSPI_BOARD_E14ROU14RO_HW_DEFINITION +}; + +struct neuronspi_board_combination NEURONSPI_MODEL_M503_HW_DEFINITION_BOARD[NEURONSPI_MODEL_M503_HW_DEFINITION_BOARD_SIZE] = { + NEURONSPI_BOARD_B1000_HW_DEFINITION, NEURONSPI_BOARD_E4AI4AOU6DI5RO_HW_DEFINITION +}; + +struct neuronspi_board_combination NEURONSPI_MODEL_M603_HW_DEFINITION_BOARD[NEURONSPI_MODEL_M603_HW_DEFINITION_BOARD_SIZE] = { + NEURONSPI_BOARD_B1000_HW_DEFINITION, NEURONSPI_BOARD_E4LIGHT_HW_DEFINITION +}; + +struct neuronspi_board_combination NEURONSPI_MODEL_L203_HW_DEFINITION_BOARD[NEURONSPI_MODEL_L203_HW_DEFINITION_BOARD_SIZE] = { + NEURONSPI_BOARD_B1000_HW_DEFINITION, NEURONSPI_BOARD_E16DIU14RO_HW_DEFINITION, NEURONSPI_BOARD_E16DIU14RO_HW_DEFINITION +}; + +struct neuronspi_board_combination NEURONSPI_MODEL_L303_HW_DEFINITION_BOARD[NEURONSPI_MODEL_L303_HW_DEFINITION_BOARD_SIZE] = { + NEURONSPI_BOARD_B1000_HW_DEFINITION, NEURONSPI_BOARD_E16DIU14DI_HW_DEFINITION, NEURONSPI_BOARD_E16DIU14DI_HW_DEFINITION +}; + +struct neuronspi_board_combination NEURONSPI_MODEL_L403_HW_DEFINITION_BOARD[NEURONSPI_MODEL_L403_HW_DEFINITION_BOARD_SIZE] = { + NEURONSPI_BOARD_B1000_HW_DEFINITION, NEURONSPI_BOARD_E14ROU14RO_HW_DEFINITION, NEURONSPI_BOARD_E14ROU14RO_HW_DEFINITION +}; + +struct neuronspi_board_combination NEURONSPI_MODEL_L503_HW_DEFINITION_BOARD[NEURONSPI_MODEL_L503_HW_DEFINITION_BOARD_SIZE] = { + NEURONSPI_BOARD_B1000_HW_DEFINITION, NEURONSPI_BOARD_E4AI4AOU6DI5RO_HW_DEFINITION, NEURONSPI_BOARD_E14ROU14DI_HW_DEFINITION +}; + +struct neuronspi_board_combination NEURONSPI_MODEL_L513_HW_DEFINITION_BOARD[NEURONSPI_MODEL_L513_HW_DEFINITION_BOARD_SIZE] = { + NEURONSPI_BOARD_B1000_HW_DEFINITION, NEURONSPI_BOARD_E4AI4AOU6DI5RO_HW_DEFINITION, NEURONSPI_BOARD_E4AI4AOU6DI5RO_HW_DEFINITION +}; + +// Board table +// Column 4 is the number of 0-indexed registers and column 5 is the number of 1000-indexed ones +struct neuronspi_board_entry NEURONSPI_BOARDTABLE[NEURONSPI_BOARDTABLE_LEN] = { + {.index = 0, .lower_board_id = NEURONSPI_BOARD_LOWER_B1000_ID, .upper_board_id = NEURONSPI_BOARD_UPPER_NONE_ID, + .data_register_count = 21, .config_register_count = 32, .definition = NEURONSPI_BOARD_B1000_HW_COMBINATION}, // B_1000 (S103) + {.index = 1, .lower_board_id = NEURONSPI_BOARD_LOWER_E8DI8RO_ID, .upper_board_id = NEURONSPI_BOARD_UPPER_NONE_ID, + .data_register_count = 19, .config_register_count = 21, .definition = NEURONSPI_BOARD_E8DI8RO_HW_COMBINATION}, // E-8Di8Ro (M103) + {.index = 2, .lower_board_id = NEURONSPI_BOARD_LOWER_E14RO_ID, .upper_board_id = NEURONSPI_BOARD_UPPER_NONE_ID, + .data_register_count = 1, .config_register_count = 0, .definition = NEURONSPI_BOARD_E14RO_HW_COMBINATION}, // E-14Ro + {.index = 3, .lower_board_id = NEURONSPI_BOARD_LOWER_E16DI_ID, .upper_board_id = NEURONSPI_BOARD_UPPER_NONE_ID, + .data_register_count = 1, .config_register_count = 0, .definition = NEURONSPI_BOARD_E16DI_HW_COMBINATION}, // E-16Di + {.index = 4, .lower_board_id = NEURONSPI_BOARD_LOWER_E8DI8RO_ID, .upper_board_id = NEURONSPI_BOARD_UPPER_P11DIR485_ID, + .data_register_count = 36, .config_register_count = 31, .definition = NEURONSPI_BOARD_E8DI8ROP11DIR485_HW_COMBINATION}, // E-8Di8Ro_P-11DiR485 (xS10) + {.index = 5, .lower_board_id = NEURONSPI_BOARD_LOWER_E14RO_ID, .upper_board_id = NEURONSPI_BOARD_UPPER_P11DIR485_ID, + .data_register_count = 20, .config_register_count = 23, .definition = NEURONSPI_BOARD_E14ROP11DIR485_HW_COMBINATION}, // E-14Ro_P-11DiR485 (xS40) + {.index = 6, .lower_board_id = NEURONSPI_BOARD_LOWER_E16DI_ID, .upper_board_id = NEURONSPI_BOARD_UPPER_P11DIR485_ID, + .data_register_count = 52, .config_register_count = 36, .definition = NEURONSPI_BOARD_E16DIP11DIR485_HW_COMBINATION}, // E-16Di_P-11DiR485 (xS30) + {.index = 7, .lower_board_id = NEURONSPI_BOARD_LOWER_E14RO_ID, .upper_board_id = NEURONSPI_BOARD_UPPER_U14RO_ID, + .data_register_count = 3, .config_register_count = 10, .definition = NEURONSPI_BOARD_E14ROU14RO_HW_COMBINATION}, // E-14Ro_U-14Ro (M403) + {.index = 8, .lower_board_id = NEURONSPI_BOARD_LOWER_E16DI_ID, .upper_board_id = NEURONSPI_BOARD_UPPER_U14RO_ID, + .data_register_count = 35, .config_register_count = 29, .definition = NEURONSPI_BOARD_E16DIU14RO_HW_COMBINATION}, // E-16Di_U-14Ro (M203) + {.index = 9, .lower_board_id = NEURONSPI_BOARD_LOWER_E14RO_ID, .upper_board_id = NEURONSPI_BOARD_UPPER_U14DI_ID, + .data_register_count = 31, .config_register_count = 27, .definition = NEURONSPI_BOARD_E14ROU14DI_HW_COMBINATION}, // E-14Ro_U-14Di (L503) + {.index = 10, .lower_board_id = NEURONSPI_BOARD_LOWER_E16DI_ID, .upper_board_id = NEURONSPI_BOARD_UPPER_U14DI_ID, + .data_register_count = 63, .config_register_count = 40, .definition = NEURONSPI_BOARD_E16DIU14DI_HW_COMBINATION}, // E-16Di_U-14Di (M303) + {.index = 11, .lower_board_id = NEURONSPI_BOARD_LOWER_E4AI4AO_ID, .upper_board_id = NEURONSPI_BOARD_UPPER_NONE_ID, + .data_register_count = 1, .config_register_count = 0, .definition = NEURONSPI_BOARD_E4AI4AO_HW_COMBINATION}, // E-4Ai4Ao + {.index = 12, .lower_board_id = NEURONSPI_BOARD_LOWER_E4AI4AO_ID, .upper_board_id = NEURONSPI_BOARD_UPPER_P6DI5RO_ID, + .data_register_count = 27, .config_register_count = 25, .definition = NEURONSPI_BOARD_E4AI4AOP6DI5RO_HW_COMBINATION}, // E-4Ai4Ao_P-6Di5Ro (xS50) + {.index = 13, .lower_board_id = NEURONSPI_BOARD_LOWER_B485_ID, .upper_board_id = NEURONSPI_BOARD_UPPER_NONE_ID, + .data_register_count = 1, .config_register_count = 0, .definition = NEURONSPI_BOARD_B485_HW_COMBINATION}, // B-485 + {.index = 14, .lower_board_id = NEURONSPI_BOARD_LOWER_E4LIGHT_ID, .upper_board_id = NEURONSPI_BOARD_UPPER_NONE_ID, + .data_register_count = 21, .config_register_count = 8, .definition = NEURONSPI_BOARD_E4LIGHT_HW_COMBINATION}, // E-4Light (M603) + {.index = 15, .lower_board_id = NEURONSPI_BOARD_LOWER_E4AI4AO_ID, .upper_board_id = NEURONSPI_BOARD_UPPER_U6DI5RO_ID, + .data_register_count = 28, .config_register_count = 24, .definition = NEURONSPI_BOARD_E4AI4AOU6DI5RO_HW_COMBINATION} // E-4Ai4Ao_U-6Di5Ro (M503) +}; + +// Module table +struct neuronspi_model_definition NEURONSPI_MODELTABLE[NEURONSPI_MODELTABLE_LEN] = { + {.eeprom_length = 4, .eeprom_name = "S103", .name_length = 4, .model_name = "S103", + .combination_count = 1, .combinations = NEURONSPI_MODEL_S103_HW_DEFINITION_BOARD}, + {.eeprom_length = 4, .eeprom_name = "S103", .name_length = 6, .model_name = "S103-G", + .combination_count = 1, .combinations = NEURONSPI_MODEL_S103G_HW_DEFINITION_BOARD}, + {.eeprom_length = 6, .eeprom_name = "S103IQ", .name_length = 7, .model_name = "S103-IQ", + .combination_count = 1, .combinations = NEURONSPI_MODEL_S103IQ_HW_DEFINITION_BOARD}, + {.eeprom_length = 6, .eeprom_name = "S103EO", .name_length = 7, .model_name = "S103-EO", + .combination_count = 1, .combinations = NEURONSPI_MODEL_S103EO_HW_DEFINITION_BOARD}, + {.eeprom_length = 4, .eeprom_name = "M103", .name_length = 4, .model_name = "M103", + .combination_count = 2, .combinations = NEURONSPI_MODEL_M103_HW_DEFINITION_BOARD}, + {.eeprom_length = 4, .eeprom_name = "M203", .name_length = 4, .model_name = "M203", + .combination_count = 2, .combinations = NEURONSPI_MODEL_M203_HW_DEFINITION_BOARD}, + {.eeprom_length = 4, .eeprom_name = "M303", .name_length = 4, .model_name = "M303", + .combination_count = 2, .combinations = NEURONSPI_MODEL_M303_HW_DEFINITION_BOARD}, + {.eeprom_length = 4, .eeprom_name = "M403", .name_length = 4, .model_name = "M403", + .combination_count = 2, .combinations = NEURONSPI_MODEL_M403_HW_DEFINITION_BOARD}, + {.eeprom_length = 4, .eeprom_name = "M503", .name_length = 4, .model_name = "M503", + .combination_count = 2, .combinations = NEURONSPI_MODEL_M503_HW_DEFINITION_BOARD}, + {.eeprom_length = 4, .eeprom_name = "M603", .name_length = 4, .model_name = "M603", + .combination_count = 2, .combinations = NEURONSPI_MODEL_M603_HW_DEFINITION_BOARD}, + {.eeprom_length = 4, .eeprom_name = "L203", .name_length = 4, .model_name = "L203", + .combination_count = 3, .combinations = NEURONSPI_MODEL_L203_HW_DEFINITION_BOARD}, + {.eeprom_length = 4, .eeprom_name = "L303", .name_length = 4, .model_name = "L303", + .combination_count = 3, .combinations = NEURONSPI_MODEL_L303_HW_DEFINITION_BOARD}, + {.eeprom_length = 4, .eeprom_name = "L403", .name_length = 4, .model_name = "L403", + .combination_count = 3, .combinations = NEURONSPI_MODEL_L403_HW_DEFINITION_BOARD}, + {.eeprom_length = 4, .eeprom_name = "L503", .name_length = 4, .model_name = "L503", + .combination_count = 3, .combinations = NEURONSPI_MODEL_L503_HW_DEFINITION_BOARD}, + {.eeprom_length = 4, .eeprom_name = "L513", .name_length = 4, .model_name = "L513", + .combination_count = 3, .combinations = NEURONSPI_MODEL_L513_HW_DEFINITION_BOARD} +}; + +/************************ + * Non-static Functions * + ************************/ + +s32 neuronspi_regmap_invalidate(void *data) +{ + int i; + int freq_cnt = 0; + while (!kthread_should_stop()) { + usleep_range(15000,25000); + if (freq_cnt == 450001) freq_cnt = 0; + for (i = 0; i < NEURONSPI_MAX_DEVS; i++) { + if (neuronspi_s_dev[i] != NULL) { + struct neuronspi_driver_data *d_data = spi_get_drvdata(neuronspi_s_dev[i]); + if (d_data->combination_id == 0xFF) { + continue; + } + neuronspi_regmap_invalidate_device(d_data->reg_map, NEURONSPI_BOARDTABLE[d_data->combination_id].definition, freq_cnt); + } + } + freq_cnt++; + } + return 0; +} + +void neuronspi_regmap_invalidate_device(struct regmap *reg_map, struct neuronspi_board_combination *device_def, u32 period_counter) +{ + int block_start, block_len, block_counter, current_period, period_len; + int i; + block_start = -1; + block_len = -1; + block_counter = 0; + period_len = 1; + + for (i = 0; i < device_def->block_count; i++) { + if (block_start == -1) { + block_start = device_def->blocks[i]; + block_counter = 0; + } else if (block_len == -1) { + block_len = device_def->blocks[i]; + } else if ((block_counter != block_len)) { + current_period = device_def->blocks[i] & 0x00FF0000; + if ((block_counter + 1 != block_len) && ((device_def->blocks[i + 1] & 0x00FF0000) == current_period)) { + period_len++; + } else { + switch (current_period) { + case NEURONSPI_REGFLAG_ACC_AFAP: { + regcache_drop_region(reg_map, block_start + block_counter - period_len + 1, block_start + block_counter); + break; + } + case NEURONSPI_REGFLAG_ACC_10HZ: { + if ((period_counter) % 5) { + regcache_drop_region(reg_map, block_start + block_counter - period_len + 1, block_start + block_counter); + } + break; + } + case NEURONSPI_REGFLAG_ACC_1HZ: { + if ((period_counter % 50) == 0) { + regcache_drop_region(reg_map, block_start + block_counter - period_len + 1, block_start + block_counter); + } + break; + } + case NEURONSPI_REGFLAG_ACC_6SEC: { + if ((period_counter % 300) == 0) { + regcache_drop_region(reg_map, block_start + block_counter - period_len + 1, block_start + block_counter); + } + break; + } + case NEURONSPI_REGFLAG_ACC_1MIN: { + if ((period_counter % 3000) == 0) { + regcache_drop_region(reg_map, block_start + block_counter - period_len + 1, block_start + block_counter); + } + break; + } + case NEURONSPI_REGFLAG_ACC_15MIN: { + if ((period_counter % 45000) == 0) { + regcache_drop_region(reg_map, block_start + block_counter - period_len + 1, block_start + block_counter); + } + break; + } + default: + break; + } + period_len = 1; + } + block_counter++; + } + if (block_counter == block_len) { + block_counter = 0; + block_start = -1; + block_len = -1; + } + } +} + +int neuronspi_regmap_hw_reg_read(void *context, unsigned int reg, unsigned int *val) +{ + struct spi_device *spi = context; + struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi); + u8 *inp_buf; + u8 *outp_buf; + int write_length; + printk(KERN_INFO "NEURONSPI: RM_REG_READ\n"); + write_length = neuronspi_spi_compose_single_register_read(reg, &inp_buf, &outp_buf); + neuronspi_spi_send_message(spi, inp_buf, outp_buf, write_length, n_spi->ideal_frequency, 25, 1); + memcpy(val, &outp_buf[NEURONSPI_HEADER_LENGTH], sizeof(u16)); + kfree(inp_buf); + kfree(outp_buf); + return 0; +} + +int neuronspi_regmap_hw_write(void *context, const void *data, size_t count) +{ + BUG_ON(count < 1); + return neuronspi_regmap_hw_gather_write(context, data, 1, data + 1, count - 1); +} + +int neuronspi_regmap_hw_reg_write(void *context, unsigned int reg, unsigned int val) +{ + struct spi_device *spi = context; + struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi); + u8 *inp_buf; + u8 *outp_buf; + int write_length; + write_length = neuronspi_spi_compose_single_register_write(reg, &inp_buf, &outp_buf, (val >> 8)); + printk(KERN_INFO "HW_REG_WRITE l:%d, r:%d, v:%d\n", write_length, reg, (val >> 8)); + neuronspi_spi_send_message(spi, inp_buf, outp_buf, write_length, n_spi->ideal_frequency, 25, 1); + memcpy(&val, &outp_buf[NEURONSPI_HEADER_LENGTH], sizeof(u16)); + kfree(inp_buf); + kfree(outp_buf); + return 0; +} + +int neuronspi_regmap_hw_gather_write(void *context, const void *reg, size_t reg_size, const void *val, size_t val_size) +{ + u16 *mb_reg_buf = (u16*)reg; + u32 *mb_val_buf = (u32*)val; + struct spi_device *spi = context; + struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi); + u8 *inp_buf; + u8 *outp_buf; + int i, write_length; + int block_counter = 0; + printk(KERN_INFO "HW_REG_GATHER_WRITE:%d, %d, %x, %x\n", val_size, reg_size, mb_reg_buf[0], mb_val_buf[0]); + if (reg_size == 1) { + neuronspi_regmap_hw_reg_write(context,mb_reg_buf[0],mb_val_buf[0]); + } else { + for (i = 0; i < reg_size; i++) { + // Swap endianness + cpu_to_be16s((u16*)&(mb_val_buf[i])); + // Check for continuity and read the largest possible continuous block + if (block_counter == (reg_size - 1) || ((mb_reg_buf[i] + 1) != mb_reg_buf[i + 1])) { + write_length = neuronspi_spi_compose_multiple_register_write(block_counter, mb_reg_buf[i - block_counter], &inp_buf, &outp_buf, + (u8*)(&mb_val_buf[i - block_counter])); + neuronspi_spi_send_message(spi, inp_buf, outp_buf, write_length, n_spi->ideal_frequency, 125, 1); + block_counter = 0; + kfree(inp_buf); + kfree(outp_buf); + } else { + block_counter++; + } + } + } + return 0; +} + +int neuronspi_create_reg_starts(struct neuronspi_board_regstart_table *out_table, struct neuronspi_board_combination *board) { + if (board->features.di_count > 0) { + out_table->di_val_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_DI_READ); + out_table->di_counter_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_DI_COUNTER_UPPER); + out_table->di_deboun_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_DI_DEBOUNCE); + out_table->di_direct_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_DS_ENABLE); + out_table->di_polar_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_DS_POLARITY); + out_table->di_toggle_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_DS_TOGGLE); + } + if (board->features.do_count > 0) { + out_table->do_val_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_DO_RW); + out_table->do_pwm_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_PWM_DUTY); + out_table->do_pwm_c_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_PWM_CYCLE); + out_table->do_pwm_ps_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_PWM_PRESCALE); + } + if (board->features.led_count > 0) { + out_table->led_val_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_LED_RW); + } + if (board->features.light_count > 0) { + // TODO: Fill in light bus registers + } + if (board->features.ro_count > 0) { + out_table->ro_val_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_DO_RW); + } + if (board->features.sec_ai_count > 0) { + out_table->sec_ai_val_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_AI_VER2_READ_LOWER); + out_table->sec_ai_mode_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_AI_VER2_MODE); + } + if (board->features.sec_ao_count > 0) { + out_table->sec_ao_val_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_AO_VER2_RW); + } + if (board->features.stm_ao_count > 0) { + out_table->stm_ao_val_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_AO_BRAIN); + out_table->stm_ao_mode_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_AO_BRAIN_MODE); + out_table->stm_ao_vol_err = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_AO_BRAIN_V_ERR); + out_table->stm_ao_vol_off = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_AO_BRAIN_V_OFF); + out_table->stm_ao_curr_err = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_AO_BRAIN_I_ERR); + out_table->stm_ao_curr_off = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_AO_BRAIN_I_OFF); + } + if (board->features.stm_ai_count > 0) { + out_table->stm_ai_val_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_AI_BRAIN); + out_table->stm_ai_mode_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_AI_BRAIN_MODE); + out_table->stm_ai_vol_err = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_AI_BRAIN_V_ERR); + out_table->stm_ai_vol_off = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_AI_BRAIN_V_OFF); + out_table->stm_ai_curr_err = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_AI_BRAIN_I_ERR); + out_table->stm_ai_curr_off = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_AI_BRAIN_I_OFF); + out_table->stm_aio_val_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_AIO_BRAIN); + out_table->stm_aio_vol_err = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_AIO_BRAIN_ERR); + out_table->stm_aio_vol_off = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_AIO_BRAIN_OFF); + out_table->vref_inp = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_V_REF_INP); + } + out_table->uart_queue_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_TX_QUEUE_LEN); + out_table->uart_conf_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_RS485_CONFIG); + out_table->vref_int = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_V_REF_INT); + out_table->wd_timeout_reg = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_MWD_TO); + out_table->sys_serial_num = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_SERIAL_NR_LOWER); + out_table->sys_sw_ver = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_SW_VER); + out_table->sys_hw_ver = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_HW_VER); + out_table->sys_hw_flash_ver = neuronspi_find_reg_start(board, NEURONSPI_REGFUN_FLASH_HW_VER); + return 0; +} + +s32 neuronspi_find_reg_start(struct neuronspi_board_combination *board, u16 regfun) { + int i; + int block_start = -1; + int block_len = -1; + int block_counter = 0; + for (i = 0; i < board->block_count; i++) { + if (block_start == -1) { + block_start = board->blocks[i]; + } else if (block_len == -1) { + block_len = board->blocks[i]; + } else if ((board->blocks[i] & 0xFFFF) == regfun) { + //printk(KERN_INFO "NEURONSPI: Reg Start Fun: %x RegS: %d", regfun, block_start + block_counter); + return block_start + block_counter; + } else { + block_counter++; + } + if (block_counter == block_len) { + block_counter = 0; + block_start = -1; + block_len = -1; + } + } + return -1; +} + +int neuronspi_regmap_hw_read(void *context, const void *reg_buf, size_t reg_size, void *val_buf, size_t val_size) { + const u16 *mb_reg_buf = reg_buf; + u16 *mb_val_buf = val_buf; + struct spi_device *spi; + struct neuronspi_driver_data *n_spi; + u8 *inp_buf; + u8 *outp_buf; + int i, write_length; + int block_counter = 0; + if (context == NULL) { + return 0; + } + spi = context; + n_spi = spi_get_drvdata(spi); + if (n_spi == NULL) { + return 0; + } + for (i = 0; i < (reg_size / 2); i++) { + // Check for continuity and read the largest possible continuous block + if (block_counter == ((reg_size / 2) - 1) || ((mb_reg_buf[i] + 1) != mb_reg_buf[i + 1])) { + write_length = neuronspi_spi_compose_multiple_register_read(block_counter + 1, mb_reg_buf[i - block_counter], &inp_buf, &outp_buf); + neuronspi_spi_send_message(spi, inp_buf, outp_buf, write_length, n_spi->ideal_frequency, 125, 1); + memcpy(&mb_val_buf[i - block_counter], &outp_buf[NEURONSPI_HEADER_LENGTH], (block_counter + 1) * 2); + kfree(inp_buf); + kfree(outp_buf); + block_counter = 0; + } else { + block_counter++; + } + } + printk(KERN_INFO "NEURONSPI: RM_READ %d %x %d %x\n", reg_size, mb_reg_buf[0], val_size, mb_val_buf[0]); + return 0; +} + +s32 neuronspi_find_model_id(u32 probe_count) +{ + struct neuronspi_driver_data *n_spi; + int i,j, ret = -1; + u8 *inv = kzalloc(sizeof(*inv) * NEURONSPI_MODELTABLE_LEN, GFP_KERNEL); + for (i = 0; i < probe_count; i++) { + if (neuronspi_s_dev[i]) { + n_spi = spi_get_drvdata(neuronspi_s_dev[i]); + for (j = 0; j < NEURONSPI_MODELTABLE_LEN; j++) { + if (i + 1 > NEURONSPI_MODELTABLE[j].combination_count) { + inv[j] = 1; + } else if (NEURONSPI_MODELTABLE[j].combinations[i].combination_board_id != n_spi->combination_id) { + inv[j] = 1; + } + } + } else { + for (j = 0; j < NEURONSPI_MODELTABLE_LEN; j++) { + if (i + 1 < NEURONSPI_MODELTABLE[j].combination_count) { + inv[j] = 1; + } + } + } + } + for (i = 0; i < NEURONSPI_MODELTABLE_LEN; i++) { + if (inv[i] != 1) { + ret = i; + break; + } + } + kfree(inv); + return ret; +} + + diff --git a/modules/unipi/src/unipi_platform.h b/modules/unipi/src/unipi_platform.h new file mode 100644 index 0000000..8178ebb --- /dev/null +++ b/modules/unipi/src/unipi_platform.h @@ -0,0 +1,358 @@ +/* + * UniPi Neuron tty serial driver - Copyright (C) 2018 UniPi Technologies + * Author: Tomas Knot + * + * Based on the SC16IS7xx driver by Jon Ringle , + * which was in turn based on max310x.c, by Alexander Shiyan + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +#ifndef MODULES_NEURON_SPI_SRC_UNIPI_PLATFORM_H_ +#define MODULES_NEURON_SPI_SRC_UNIPI_PLATFORM_H_ + +/************ + * Includes * + ************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "unipi_common.h" + +/******************* + * Data Structures * + *******************/ + +struct neuronspi_board_entry { + u16 index; + u16 lower_board_id; + u16 upper_board_id; + u16 data_register_count; + u16 config_register_count; + struct neuronspi_board_combination *definition; +}; + +struct neuronspi_register_block +{ + u32 starting_register; + u32 register_count; + u32 *register_flags; +}; + +struct neuronspi_board_features +{ + u32 do_count; + u32 ro_count; + u32 ds_count; + u32 di_count; + u32 led_count; + u32 stm_ai_count; + u32 stm_ao_count; + u32 sec_ai_count; + u32 sec_ao_count; + u32 uart_master_count; + u32 uart_slave_count; + u32 pwm_channel_count; + u32 wd_count; + u32 extension_sys_count; + u32 light_count; + u32 owire_count; +}; + +struct neuronspi_board_regstart_table +{ + u32 do_val_reg; + u32 do_val_coil; + u32 do_pwm_reg; + u32 do_pwm_ps_reg; + u32 do_pwm_c_reg; + u32 di_val_reg; + u32 di_counter_reg; + u32 di_direct_reg; + u32 di_deboun_reg; + u32 di_polar_reg; + u32 di_toggle_reg; + u32 uart_queue_reg; + u32 uart_conf_reg; + u32 uart_address_reg; + u32 led_val_coil; + u32 led_val_reg; + u32 wd_val_reg; + u32 wd_timeout_reg; + u32 wd_nv_sav_coil; + u32 wd_reset_coil; + u32 reg_start_reg; + u32 ro_val_reg; + u32 ro_val_coil; + u32 vref_inp; + u32 vref_int; + u32 stm_ao_val_reg; + u32 stm_ao_mode_reg; + u32 stm_ao_vol_err; + u32 stm_ao_vol_off; + u32 stm_ao_curr_err; + u32 stm_ao_curr_off; + u32 stm_ai_val_reg; + u32 stm_ai_mode_reg; + u32 stm_ai_curr_err; + u32 stm_ai_curr_off; + u32 stm_ai_vol_err; + u32 stm_ai_vol_off; + u32 stm_aio_val_reg; + u32 stm_aio_vol_err; + u32 stm_aio_vol_off; + u32 sec_ao_val_reg; + u32 sec_ao_mode_reg; + u32 sec_ai_val_reg; + u32 sec_ai_mode_reg; + u32 sys_serial_num; + u32 sys_hw_ver; + u32 sys_hw_flash_ver; + u32 sys_sw_ver; +}; + +struct neuronspi_board_combination +{ + u32 combination_board_id; + u16 lower_board_id; + u16 upper_board_id; + u32 block_count; + size_t name_length; + const char* combination_name; + struct neuronspi_board_features features; + u32 *blocks; +}; + +struct neuronspi_model_definition +{ + size_t eeprom_length; + const char* eeprom_name; + size_t name_length; + const char* model_name; + u32 combination_count; + struct neuronspi_board_combination *combinations; +}; + +/*************** + * Definitions * + ***************/ + +// Lower Boards +#define NEURONSPI_BOARD_LOWER_B1000_ID 0 +#define NEURONSPI_BOARD_LOWER_E8DI8RO_ID 1 +#define NEURONSPI_BOARD_LOWER_E14RO_ID 2 +#define NEURONSPI_BOARD_LOWER_E16DI_ID 3 +#define NEURONSPI_BOARD_LOWER_E4AI4AO_ID 11 +#define NEURONSPI_BOARD_LOWER_B485_ID 13 +#define NEURONSPI_BOARD_LOWER_E4LIGHT_ID 14 + +// Upper Boards +#define NEURONSPI_BOARD_UPPER_NONE_ID 0 +#define NEURONSPI_BOARD_UPPER_P11DIR485_ID 1 +#define NEURONSPI_BOARD_UPPER_U14RO_ID 2 +#define NEURONSPI_BOARD_UPPER_U14DI_ID 3 +#define NEURONSPI_BOARD_UPPER_P6DI5RO_ID 4 +#define NEURONSPI_BOARD_UPPER_U6DI5RO_ID 5 + +// Register function codes +// Digital Input Functions +#define NEURONSPI_FUNGROUP_DI 0 +#define NEURONSPI_REGFUN_DI_READ 0 | NEURONSPI_FUNGROUP_DI << 8 +#define NEURONSPI_REGFUN_DI_COUNTER_LOWER 1 | NEURONSPI_FUNGROUP_DI << 8 +#define NEURONSPI_REGFUN_DI_COUNTER_UPPER 2 | NEURONSPI_FUNGROUP_DI << 8 +#define NEURONSPI_REGFUN_DI_DEBOUNCE 3 | NEURONSPI_FUNGROUP_DI << 8 +#define NEURONSPI_REGFUN_DS_ENABLE 4 | NEURONSPI_FUNGROUP_DI << 8 +#define NEURONSPI_REGFUN_DS_POLARITY 5 | NEURONSPI_FUNGROUP_DI << 8 +#define NEURONSPI_REGFUN_DS_TOGGLE 6 | NEURONSPI_FUNGROUP_DI << 8 + +// Digital Output Functions +#define NEURONSPI_FUNGROUP_DO 1 +#define NEURONSPI_REGFUN_DO_RW 0 | NEURONSPI_FUNGROUP_DO << 8 + +// B1000 Analog Output Functions +#define NEURONSPI_FUNGROUP_AO_BRAIN 2 +#define NEURONSPI_REGFUN_AO_BRAIN 0 | NEURONSPI_FUNGROUP_AO_BRAIN << 8 +#define NEURONSPI_REGFUN_AO_BRAIN_MODE 1 | NEURONSPI_FUNGROUP_AO_BRAIN << 8 +#define NEURONSPI_REGFUN_AO_BRAIN_V_ERR 2 | NEURONSPI_FUNGROUP_AO_BRAIN << 8 +#define NEURONSPI_REGFUN_AO_BRAIN_V_OFF 3 | NEURONSPI_FUNGROUP_AO_BRAIN << 8 +#define NEURONSPI_REGFUN_AO_BRAIN_I_ERR 4 | NEURONSPI_FUNGROUP_AO_BRAIN << 8 +#define NEURONSPI_REGFUN_AO_BRAIN_I_OFF 5 | NEURONSPI_FUNGROUP_AO_BRAIN << 8 + +// B1000 Analog Input Functions +#define NEURONSPI_FUNGROUP_AI_BRAIN 3 +#define NEURONSPI_REGFUN_AI_BRAIN 0 | NEURONSPI_FUNGROUP_AI_BRAIN << 8 +#define NEURONSPI_REGFUN_AIO_BRAIN 1 | NEURONSPI_FUNGROUP_AI_BRAIN << 8 +#define NEURONSPI_REGFUN_AI_BRAIN_MODE 2 | NEURONSPI_FUNGROUP_AI_BRAIN << 8 +#define NEURONSPI_REGFUN_AI_BRAIN_V_ERR 3 | NEURONSPI_FUNGROUP_AI_BRAIN << 8 +#define NEURONSPI_REGFUN_AI_BRAIN_V_OFF 4 | NEURONSPI_FUNGROUP_AI_BRAIN << 8 +#define NEURONSPI_REGFUN_AI_BRAIN_I_ERR 5 | NEURONSPI_FUNGROUP_AI_BRAIN << 8 +#define NEURONSPI_REGFUN_AI_BRAIN_I_OFF 6 | NEURONSPI_FUNGROUP_AI_BRAIN << 8 +#define NEURONSPI_REGFUN_AIO_BRAIN_ERR 7 | NEURONSPI_FUNGROUP_AI_BRAIN << 8 +#define NEURONSPI_REGFUN_AIO_BRAIN_OFF 8 | NEURONSPI_FUNGROUP_AI_BRAIN << 8 + +// System Functions +#define NEURONSPI_FUNGROUP_SYSTEM 4 +#define NEURONSPI_REGFUN_V_REF_INT 0 | NEURONSPI_FUNGROUP_SYSTEM << 8 +#define NEURONSPI_REGFUN_V_REF_INP 1 | NEURONSPI_FUNGROUP_SYSTEM << 8 +#define NEURONSPI_REGFUN_LED_RW 2 | NEURONSPI_FUNGROUP_SYSTEM << 8 +#define NEURONSPI_REGFUN_SW_VER 3 | NEURONSPI_FUNGROUP_SYSTEM << 8 +#define NEURONSPI_REGFUN_DIDO_COUNT 4 | NEURONSPI_FUNGROUP_SYSTEM << 8 +#define NEURONSPI_REGFUN_UAIO_COUNT 5 | NEURONSPI_FUNGROUP_SYSTEM << 8 +#define NEURONSPI_REGFUN_HW_VER 6 | NEURONSPI_FUNGROUP_SYSTEM << 8 +#define NEURONSPI_REGFUN_FLASH_HW_VER 7 | NEURONSPI_FUNGROUP_SYSTEM << 8 +#define NEURONSPI_REGFUN_SERIAL_NR_LOWER 8 | NEURONSPI_FUNGROUP_SYSTEM << 8 +#define NEURONSPI_REGFUN_SERIAL_NR_UPPER 9 | NEURONSPI_FUNGROUP_SYSTEM << 8 +#define NEURONSPI_REGFUN_INTERRUPTS 10 | NEURONSPI_FUNGROUP_SYSTEM << 8 +#define NEURONSPI_REGFUN_NONE_TEST 11 | NEURONSPI_FUNGROUP_SYSTEM << 8 + +// Watchdog Functions +#define NEURONSPI_FUNGROUP_MWD 5 +#define NEURONSPI_REGFUN_MWD_TO 0 | NEURONSPI_FUNGROUP_MWD << 8 +#define NEURONSPI_REGFUN_MWD_STATUS 1 | NEURONSPI_FUNGROUP_MWD << 8 + +// PWM Functions +#define NEURONSPI_FUNGROUP_PWM 6 +#define NEURONSPI_REGFUN_PWM_DUTY 0 | NEURONSPI_FUNGROUP_PWM << 8 +#define NEURONSPI_REGFUN_PWM_PRESCALE 1 | NEURONSPI_FUNGROUP_PWM << 8 +#define NEURONSPI_REGFUN_PWM_CYCLE 2 | NEURONSPI_FUNGROUP_PWM << 8 + +// UART Functions +#define NEURONSPI_FUNGROUP_RS485 7 +#define NEURONSPI_REGFUN_TX_QUEUE_LEN 0 | NEURONSPI_FUNGROUP_RS485 << 8 +#define NEURONSPI_REGFUN_RS485_CONFIG 1 | NEURONSPI_FUNGROUP_RS485 << 8 +#define NEURONSPI_REGFUN_RS485_ADDRESS 2 | NEURONSPI_FUNGROUP_RS485 << 8 + +// Secondary Analog Output Functions +#define NEURONSPI_FUNGROUP_AO_VER2 8 +#define NEURONSPI_REGFUN_AO_VER2_RW 0 | NEURONSPI_FUNGROUP_AO_VER2 << 8 + +// Secondary Analog Input Functions +#define NEURONSPI_FUNGROUP_AI_VER2 9 +#define NEURONSPI_REGFUN_AI_VER2_READ_LOWER 0 | NEURONSPI_FUNGROUP_AI_VER2 << 8 +#define NEURONSPI_REGFUN_AI_VER2_READ_UPPER 0 | NEURONSPI_FUNGROUP_AI_VER2 << 8 +#define NEURONSPI_REGFUN_AI_VER2_MODE 1 | NEURONSPI_FUNGROUP_AI_VER2 << 8 + +// Register access flags +#define NEURONSPI_REGFLAG_ACC_NEVER 0 +#define NEURONSPI_REGFLAG_ACC_AFAP 0x1 << 16 +#define NEURONSPI_REGFLAG_ACC_10HZ 0x2 << 16 +#define NEURONSPI_REGFLAG_ACC_1HZ 0x3 << 16 +#define NEURONSPI_REGFLAG_ACC_6SEC 0x4 << 16 +#define NEURONSPI_REGFLAG_ACC_1MIN 0x5 << 16 +#define NEURONSPI_REGFLAG_ACC_15MIN 0x6 << 16 +#define NEURONSPI_REGFLAG_ACC_ONCE 0x7 << 16 + +// Register system flags +#define NEURONSPI_REGFLAG_SYS_READ_ONLY 0x10 << 24 + +// IIO Modes +#define NEURONSPI_IIO_AI_STM_MODE_VOLTAGE 0x0 +#define NEURONSPI_IIO_AI_STM_MODE_CURRENT 0x1 +#define NEURONSPI_IIO_AI_STM_MODE_RESISTANCE 0x3 + +/********************* + * Data Declarations * + *********************/ + +extern struct platform_device *neuron_plc_dev; + +// Board Definitions +extern struct neuronspi_board_combination NEURONSPI_BOARD_B1000_HW_COMBINATION[]; // B_1000 (S103) +extern struct neuronspi_board_combination NEURONSPI_BOARD_E8DI8RO_HW_COMBINATION[]; // E-8Di8Ro (M103) +extern struct neuronspi_board_combination NEURONSPI_BOARD_E14RO_HW_COMBINATION[]; // E-14Ro +extern struct neuronspi_board_combination NEURONSPI_BOARD_E16DI_HW_COMBINATION[]; // E-16Di +extern struct neuronspi_board_combination NEURONSPI_BOARD_E8DI8ROP11DIR485_HW_COMBINATION[]; // E-8Di8Ro_P-11DiR485 (xS10) +extern struct neuronspi_board_combination NEURONSPI_BOARD_E14ROP11DIR485_HW_COMBINATION[]; // E-14Ro_P-11DiR485 (xS40) +extern struct neuronspi_board_combination NEURONSPI_BOARD_E16DIP11DIR485_HW_COMBINATION[]; // E-16Di_P-11DiR485 (xS30) +extern struct neuronspi_board_combination NEURONSPI_BOARD_E14ROU14RO_HW_COMBINATION[]; // E-14Ro_U-14Ro (M403) +extern struct neuronspi_board_combination NEURONSPI_BOARD_E16DIU14RO_HW_COMBINATION[]; // E-16Di_U-14Ro (M203) +extern struct neuronspi_board_combination NEURONSPI_BOARD_E14ROU14DI_HW_COMBINATION[]; // E-14Ro_U-14Di (L503) +extern struct neuronspi_board_combination NEURONSPI_BOARD_E16DIU14DI_HW_COMBINATION[]; // E-16Di_U-14Di (M303) +extern struct neuronspi_board_combination NEURONSPI_BOARD_E4AI4AO_HW_COMBINATION[]; // E-4Ai4Ao +extern struct neuronspi_board_combination NEURONSPI_BOARD_E4AI4AOP6DI5RO_HW_COMBINATION[]; // E-4Ai4Ao_P-6Di5Ro (xS50) +extern struct neuronspi_board_combination NEURONSPI_BOARD_B485_HW_COMBINATION[]; // B-485 +extern struct neuronspi_board_combination NEURONSPI_BOARD_E4LIGHT_HW_COMBINATION[]; // E-4Light (M613) +extern struct neuronspi_board_combination NEURONSPI_BOARD_E4AI4AOU6DI5RO_HW_COMBINATION[]; // E-4Ai4Ao_U-6Di5Ro (L503) + +// Model Definitions +#define NEURONSPI_MODEL_S103_HW_DEFINITION_BOARD_SIZE 1 +extern struct neuronspi_board_combination NEURONSPI_MODEL_S103_HW_DEFINITION_BOARD[NEURONSPI_MODEL_S103_HW_DEFINITION_BOARD_SIZE]; +#define NEURONSPI_MODEL_S103G_HW_DEFINITION_BOARD_SIZE 1 +extern struct neuronspi_board_combination NEURONSPI_MODEL_S103G_HW_DEFINITION_BOARD[NEURONSPI_MODEL_S103G_HW_DEFINITION_BOARD_SIZE]; +#define NEURONSPI_MODEL_S103IQ_HW_DEFINITION_BOARD_SIZE 1 +extern struct neuronspi_board_combination NEURONSPI_MODEL_S103IQ_HW_DEFINITION_BOARD[NEURONSPI_MODEL_S103IQ_HW_DEFINITION_BOARD_SIZE]; +#define NEURONSPI_MODEL_S103EO_HW_DEFINITION_BOARD_SIZE 1 +extern struct neuronspi_board_combination NEURONSPI_MODEL_S103EO_HW_DEFINITION_BOARD[NEURONSPI_MODEL_S103EO_HW_DEFINITION_BOARD_SIZE]; +#define NEURONSPI_MODEL_M103_HW_DEFINITION_BOARD_SIZE 2 +extern struct neuronspi_board_combination NEURONSPI_MODEL_M103_HW_DEFINITION_BOARD[NEURONSPI_MODEL_M103_HW_DEFINITION_BOARD_SIZE]; +#define NEURONSPI_MODEL_M203_HW_DEFINITION_BOARD_SIZE 2 +extern struct neuronspi_board_combination NEURONSPI_MODEL_M203_HW_DEFINITION_BOARD[NEURONSPI_MODEL_M203_HW_DEFINITION_BOARD_SIZE]; +#define NEURONSPI_MODEL_M303_HW_DEFINITION_BOARD_SIZE 2 +extern struct neuronspi_board_combination NEURONSPI_MODEL_M303_HW_DEFINITION_BOARD[NEURONSPI_MODEL_M303_HW_DEFINITION_BOARD_SIZE]; +#define NEURONSPI_MODEL_M403_HW_DEFINITION_BOARD_SIZE 2 +extern struct neuronspi_board_combination NEURONSPI_MODEL_M403_HW_DEFINITION_BOARD[NEURONSPI_MODEL_M403_HW_DEFINITION_BOARD_SIZE]; +#define NEURONSPI_MODEL_M503_HW_DEFINITION_BOARD_SIZE 2 +extern struct neuronspi_board_combination NEURONSPI_MODEL_M503_HW_DEFINITION_BOARD[NEURONSPI_MODEL_M503_HW_DEFINITION_BOARD_SIZE]; +#define NEURONSPI_MODEL_M603_HW_DEFINITION_BOARD_SIZE 2 +extern struct neuronspi_board_combination NEURONSPI_MODEL_M603_HW_DEFINITION_BOARD[NEURONSPI_MODEL_M603_HW_DEFINITION_BOARD_SIZE]; +#define NEURONSPI_MODEL_L203_HW_DEFINITION_BOARD_SIZE 3 +extern struct neuronspi_board_combination NEURONSPI_MODEL_L203_HW_DEFINITION_BOARD[NEURONSPI_MODEL_L203_HW_DEFINITION_BOARD_SIZE]; +#define NEURONSPI_MODEL_L303_HW_DEFINITION_BOARD_SIZE 3 +extern struct neuronspi_board_combination NEURONSPI_MODEL_L303_HW_DEFINITION_BOARD[NEURONSPI_MODEL_L303_HW_DEFINITION_BOARD_SIZE]; +#define NEURONSPI_MODEL_L403_HW_DEFINITION_BOARD_SIZE 3 +extern struct neuronspi_board_combination NEURONSPI_MODEL_L403_HW_DEFINITION_BOARD[NEURONSPI_MODEL_L403_HW_DEFINITION_BOARD_SIZE]; +#define NEURONSPI_MODEL_L503_HW_DEFINITION_BOARD_SIZE 3 +extern struct neuronspi_board_combination NEURONSPI_MODEL_L503_HW_DEFINITION_BOARD[NEURONSPI_MODEL_L503_HW_DEFINITION_BOARD_SIZE]; +#define NEURONSPI_MODEL_L513_HW_DEFINITION_BOARD_SIZE 3 +extern struct neuronspi_board_combination NEURONSPI_MODEL_L513_HW_DEFINITION_BOARD[]; + +// Board table +#define NEURONSPI_BOARDTABLE_LEN 16 +extern struct neuronspi_board_entry NEURONSPI_BOARDTABLE[]; + +// Module table +#define NEURONSPI_MODELTABLE_LEN 15 +extern struct neuronspi_model_definition NEURONSPI_MODELTABLE[]; + +/************************* + * Function Declarations * + *************************/ + +int neuronspi_regmap_hw_gather_write(void *context, const void *reg, size_t reg_size, const void *val, size_t val_size); +int neuronspi_regmap_hw_read(void *context, const void *reg_buf, size_t reg_size, void *val_buf, size_t val_size); +int neuronspi_regmap_hw_reg_read(void *context, unsigned int reg, unsigned int *val); +int neuronspi_regmap_hw_reg_write(void *context, unsigned int reg, unsigned int val); +int neuronspi_regmap_hw_write(void *context, const void *data, size_t count); +void neuronspi_regmap_invalidate_device(struct regmap *reg_map, struct neuronspi_board_combination *device_def, u32 period_counter); +s32 neuronspi_regmap_invalidate(void *data); +int neuronspi_create_reg_starts(struct neuronspi_board_regstart_table *out_table, struct neuronspi_board_combination *board); +s32 neuronspi_find_reg_start(struct neuronspi_board_combination *board, u16 regfun); +s32 neuronspi_find_model_id(u32 probe_count); + +#endif /* MODULES_NEURON_SPI_SRC_UNIPI_PLATFORM_H_ */ diff --git a/modules/unipi/src/unipi_spi.c b/modules/unipi/src/unipi_spi.c new file mode 100644 index 0000000..d58c5c4 --- /dev/null +++ b/modules/unipi/src/unipi_spi.c @@ -0,0 +1,1587 @@ +/* + * UniPi Neuron tty serial driver - Copyright (C) 2017 UniPi Tech +nologies + * Author: Tomas Knot + * + * Based on the SC16IS7xx driver by Jon Ringle , + * which was in turn based on max310x.c, by Alexander Shiyan + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +/************ + * Includes * + ************/ + +#include "unipi_common.h" +#include "unipi_sysfs.h" +#include "unipi_uart.h" +#include "unipi_platform.h" +#include "unipi_gpio.h" +#include "unipi_iio.h" +#include "unipi_misc.h" +#include "unipi_spi.h" + +/******************** + * Data Definitions * + ********************/ + +MODULE_DEVICE_TABLE(of, neuronspi_id_match); + +struct spi_driver neuronspi_spi_driver = +{ + .driver = + { + .name = NEURON_DRIVER_NAME, + .of_match_table = of_match_ptr(neuronspi_id_match) + }, + .probe = neuronspi_spi_probe, + .remove = neuronspi_spi_remove, +}; + +struct file_operations file_ops = +{ + .open = neuronspi_open, + .read = neuronspi_read, + .write = neuronspi_write, + .release = neuronspi_release, + .owner = THIS_MODULE +}; + +struct neuronspi_char_driver neuronspi_cdrv = +{ + .dev = NULL +}; + +struct mutex neuronspi_master_mutex; +struct spinlock* neuronspi_spi_w_spinlock; +u8 neuronspi_spi_w_flag = 1; +u8 neuronspi_probe_count = 0; +int neuronspi_model_id = -1; +spinlock_t neuronspi_probe_spinlock; +struct spi_device* neuronspi_s_dev[NEURONSPI_MAX_DEVS]; +struct task_struct *neuronspi_invalidate_thread; + +/************************ + * Non-static Functions * + ************************/ + +int neuronspi_open (struct inode *inode_p, struct file *file_p) +{ + struct neuronspi_file_data *f_internal_data; + if (neuronspi_s_dev == NULL || file_p == NULL || inode_p == NULL) { + return -1; + } + neuronspi_cdrv.open_counter += 1; + f_internal_data = kzalloc(sizeof(*f_internal_data), GFP_KERNEL); + f_internal_data->recv_buf = kzalloc(NEURONSPI_BUFFER_MAX, GFP_KERNEL); + f_internal_data->send_buf = kzalloc(NEURONSPI_BUFFER_MAX, GFP_KERNEL); + f_internal_data->spi_device = neuronspi_s_dev; + mutex_init(&f_internal_data->lock); + file_p->private_data = f_internal_data; + return 0; +} + +int neuronspi_release (struct inode *inode_p, struct file *file_p) +{ + struct neuronspi_file_data *f_internal_data; + if (file_p == NULL) { + return -1; + } + 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); + file_p->private_data = NULL; + neuronspi_cdrv.open_counter -= 1; + return 0; +} + +ssize_t neuronspi_read (struct file *file_p, char *buffer, size_t len, loff_t *offset) +{ + + s32 result = 0; + u8 device_index = 0; + u32 frequency = NEURONSPI_COMMON_FREQ; + struct neuronspi_file_data* private_data; + struct spi_device* spi_driver_data; + struct neuronspi_driver_data* driver_data; + // Sanity checking + if (neuronspi_cdrv.open_counter == 0) { + neuronspi_cdrv.open_counter = 1; + } + if (buffer == NULL) return -7; // Invalid read buffer + if (len == 0) return result; // Empty read + if (len > 4095) return -EMSGSIZE; + if (file_p == NULL) { + printk(KERN_DEBUG "NEURONSPI: File Pointer is NULL\n"); + return -8; + } + if (file_p->private_data == NULL) { + printk(KERN_DEBUG "NEURONSPI: 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 + 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) return -3; // No device present + if (driver_data->slower_model) { + frequency = NEURONSPI_SLOWER_FREQ; + } + mutex_lock(&(private_data->lock)); + if (private_data->recv_buf == NULL) { + mutex_unlock(&(private_data->lock)); + return -10; + } +#if NEURONSPI_DETAILED_DEBUG > 0 + printk(KERN_INFO "NEURONSPI: 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; + } 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; + s32 delay = 25; + struct neuronspi_file_data* private_data; + struct spi_device* spi_driver_data; + struct neuronspi_driver_data* driver_data; + // Sanity checking + if (neuronspi_cdrv.open_counter == 0) { + neuronspi_cdrv.open_counter = 1; + } +#if NEURONSPI_DETAILED_DEBUG > 0 + printk(KERN_INFO "NEURONSPI: LENGTH:%d\n", len); +#endif + if (buffer == NULL) { + return 0; // Void write + } + if (len == 0) { + return result; // Empty write + } + if (len > 4095) return -EMSGSIZE; + if (file_p == NULL) { + return -12; + } + if (file_p->private_data == NULL) { + printk(KERN_DEBUG "NEURONSPI: No Private Data\n"); + return -1; // No private data + } + // Read packet header and initialise private data (dependent on each other) + device_index = buffer[0]; + 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) 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; + } +#else + } else if (device_index == (driver_data->reserved_device - 1)) { + return -5; // Device reserved + } + if (driver_data->slower_model) { + frequency = NEURONSPI_SLOWER_FREQ; + } +#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(neuronspi_spi_w_spinlock); + neuronspi_spi_w_flag = 1; + spin_unlock(neuronspi_spi_w_spinlock); + neuronspi_spi_send_message(spi_driver_data, &private_data->send_buf[NEURONSPI_HEADER_LENGTH], private_data->recv_buf, + transmit_len, frequency, delay, send_header); + mutex_unlock(&private_data->lock); + return len; +} + +s32 neuronspi_spi_uart_write(struct spi_device *spi, u8 *send_buf, u8 length, u8 uart_index) +{ + u8 *message_buf; + u8 *recv_buf; + s32 transmit_len, i; + 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 "NEURONSPI: UART SPI Write, dev:%d, len:%d\n", uart_index, length); +#endif + if (length == 0) { + return -1; + } + if (length == 1) { + transmit_len = 6; + message_buf = kzalloc(transmit_len, GFP_KERNEL); + 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); + } else { + transmit_len = 6 + length + 2; + message_buf = kzalloc(transmit_len, GFP_KERNEL); + 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); + } + recv_buf = kzalloc(transmit_len, GFP_KERNEL); + 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); + } + 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) +{ + s32 transmit_len; + 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; + } +#if NEURONSPI_DETAILED_DEBUG > 0 + printk(KERN_INFO "NEURONSPI: 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; + } 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 "NEURONSPI: UART Device Read len:%d %100ph\n", transmit_len, send_buf); +#endif + } + if (!d_data->reserved_device) { + neuronspi_spi_send_message(spi, send_buf, recv_buf, transmit_len, frequency, 65, 1); + } +} + +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 "NEURONSPI: 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_KERNEL); + recv_buf = kzalloc(NEURONSPI_SPI_IRQ_SET_MESSAGE_LEN, GFP_KERNEL); + 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); + } + kfree(message_buf); + kfree(recv_buf); +} + +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; + } +#if NEURONSPI_DETAILED_DEBUG > 0 + printk(KERN_INFO "NEURONSPI: 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_KERNEL); + recv_buf = kzalloc(NEURONSPI_SPI_UART_SET_CFLAG_MESSAGE_LEN, GFP_KERNEL); + 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); + 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); + } + kfree(message_buf); + kfree(recv_buf); +} + +void neuronspi_spi_uart_set_ldisc(struct spi_device* spi_dev, u8 port, u8 to) +{ + u8 *message_buf; + u8 *recv_buf; + 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 "NEURONSPI: 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); + } + kfree(message_buf); + kfree(recv_buf); +} + +u8 neuronspi_spi_uart_get_ldisc(struct spi_device* spi_dev, u8 port) +{ + u8 *message_buf; + u8 *recv_buf; + u8 outp; + 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); + } + outp = recv_buf[MODBUS_FIRST_DATA_BYTE + 1]; +#if NEURONSPI_DETAILED_DEBUG > 1 + printk(KERN_INFO "NEURONSPI: SPI TERMIOS GET, Dev-CS:%d, to:%x\n", spi_dev->chip_select, outp); +#endif + kfree(message_buf); + kfree(recv_buf); + return outp; +} + + +/* + * 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_sec_ai_data *ai_data = iio_priv(indio_dev); + struct spi_device *spi = ai_data->parent; + struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi); + 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 + (2 * ai_data->index), &sec_ai_val_h); + regmap_read(n_spi->reg_map, n_spi->regstart_table->sec_ai_val_reg + 1 + (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_sec_ai_data *ai_data = iio_priv(indio_dev); + struct spi_device *spi = ai_data->parent; + struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi); + 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 + (2 * ai_data->index), &sec_ai_val_h); + regmap_read(n_spi->reg_map, n_spi->regstart_table->sec_ai_val_reg + 1 + (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_sec_ai_data *ai_data = iio_priv(indio_dev); + struct spi_device *spi = ai_data->parent; + struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi); + 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 + (2 * ai_data->index), &sec_ai_val_h); + regmap_read(n_spi->reg_map, n_spi->regstart_table->sec_ai_val_reg + 1 + (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_sec_ao_data *ao_data = iio_priv(indio_dev); + struct spi_device *spi = ao_data->parent; + struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi); + u32 sec_true_val = (val * 2) / 5; + if (val > 10000) val = 10000; + regmap_write(n_spi->reg_map, n_spi->regstart_table->stm_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_stm_ai_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_stm_ai_data *ai_data = iio_priv(indio_dev); + struct spi_device *spi = ai_data->parent; + struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi); + 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; +} + +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_stm_ao_data *ao_data = iio_priv(indio_dev); + struct spi_device *spi = ao_data->parent; + struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi); + 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; +} + + +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_stm_ao_data *ao_data = iio_priv(indio_dev); + struct spi_device *spi = ao_data->parent; + struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi); + 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_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_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_stm_ao_data *ao_data = iio_priv(indio_dev); + struct spi_device *spi = ao_data->parent; + struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi); + 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->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); + stm_v_inp_ref = stm_v_inp_ref * 10000; + stm_true_val = (stm_true_val * 10000) - stm_i_off; + do_div(stm_true_ref, stm_v_inp_ref); + do_div(stm_true_ref, 4095); + stm_v_inp_ref = stm_true_ref; + do_div(stm_true_val, stm_v_inp_ref); + 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); +} + +/* +static s32 neuronspi_spi_watchdog(void *data) +{ + s32 *cycle = (s32 *) data; + while (!kthread_should_stop()) { + msleep(*cycle); + spin_lock(neuronspi_spi_w_spinlock); + if (neuronspi_spi_w_flag == 0) { + panic_timeout = -1; + panic("SPI Watchdog Failure\n"); + } else { + neuronspi_spi_w_flag = 0; + } + spin_unlock(neuronspi_spi_w_spinlock); + } + return 0; +} +*/ + + + +void neuronspi_spi_send_message(struct spi_device* spi_dev, u8 *send_buf, u8 *recv_buf, s32 len, s32 freq, s32 delay, s32 send_header) +{ + s32 i = 0; + 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; + struct neuronspi_driver_data *d_data; + struct spi_transfer* s_trans; + mutex_lock(&neuronspi_master_mutex); + s_trans = kzalloc(sizeof(struct spi_transfer) * trans_count, GFP_KERNEL); +#if NEURONSPI_DETAILED_DEBUG > 1 + printk(KERN_INFO "NEURONSPI: SPI Master Write, len:%d,\n %100ph\n", len, send_buf); +#endif + if (!send_header) { + trans_count -= 1; // one less transmission as the header is omitted + } + 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; + s_trans[i].bits_per_word = 8; + s_trans[i].speed_hz = freq; + if (i == 0) { + s_trans[i].delay_usecs = NEURONSPI_EDGE_DELAY; + } else if (i == 1) { + s_trans[i].tx_buf = send_buf; + s_trans[i].rx_buf = recv_buf; + if (send_header) { + s_trans[i].delay_usecs = delay; + s_trans[i].len = NEURONSPI_FIRST_MESSAGE_LENGTH; + } else { + // If len is more than NEURONSPI_MAX_TX * i, then chunk len is NEURONSPI_MAX_TX, otherwise it's the remainder + s_trans[i].len = (len - (NEURONSPI_MAX_TX * i)) > 0 ? NEURONSPI_MAX_TX : len; + } + } else if (i == trans_count - 1) { + 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))); + } 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)]); + s_trans[i].len = ((NEURONSPI_MAX_TX * i) - len) < 0 ? NEURONSPI_MAX_TX : (len - (NEURONSPI_MAX_TX * (i - 1))); + } + s_trans[i].delay_usecs = NEURONSPI_LAST_TRANSFER_DELAY; + // 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 + } else { + 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))); + } 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)]); + s_trans[i].len = ((NEURONSPI_MAX_TX * i) - len) < 0 ? NEURONSPI_MAX_TX : (len - (NEURONSPI_MAX_TX * (i - 1))); + } + // 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])); + } +#if NEURONSPI_DETAILED_DEBUG > 1 + printk(KERN_INFO "NEURONSPI: 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 + d_data = spi_get_drvdata(spi_dev); + 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 "NEURONSPI: SPI CRC1: %x\t COMPUTED CRC1:%x\n", packet_crc, recv_crc1); +#endif + if (recv_crc1 == packet_crc) { + // Signal the UART to issue character reads +#if NEURONSPI_DETAILED_DEBUG > 1 + printk(KERN_INFO "NEURONSPI: SPI CRC1 Correct"); +#endif + if (d_data && recv_buf[0] == 0x41) { + d_data->uart_buf[0] = recv_buf[3]; +#if NEURONSPI_DETAILED_DEBUG > 0 + printk(KERN_INFO "NEURONSPI: 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); + } + } + 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 "NEURONSPI: 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); + } + } + } + } + } +#if NEURONSPI_DETAILED_DEBUG > 0 + else { + printk(KERN_INFO "NEURONSPI: 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 "NEURONSPI: SPI CRC2: %x\t COMPUTED CRC2:%x\n", packet_crc, recv_crc2); +#endif + if (recv_crc2 != packet_crc) { +#if NEURONSPI_DETAILED_DEBUG > 0 + printk(KERN_INFO "NEURONSPI: SPI CRC2 Not Correct"); +#endif + recv_buf[0] = 0; + } + } + + mutex_unlock(&neuronspi_master_mutex); + kfree(s_trans); +} + + + +irqreturn_t neuronspi_spi_irq(s32 irq, void *dev_id) +{ + s32 i; + struct spi_device *spi; + struct neuronspi_driver_data *d_data; + 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 "NEURONSPI: SPI IRQ\n"); +#endif + if (d_data->uart_count) { + u_data = d_data->uart_data; + for (i = 0; i < u_data->p_count; i++) { + if (u_data->p[i].dev_index == d_data->neuron_index) { + kthread_queue_work(&u_data->kworker, &u_data->p[i].irq_work); + } + + } + } + return 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 "NEURONSPI: SPI LED Set, Dev-CS:%d, led id:%d\n", spi_dev->chip_select, id); +#endif + message_buf = kzalloc(NEURONSPI_SPI_LED_SET_MESSAGE_LEN, GFP_KERNEL); + recv_buf = kzalloc(NEURONSPI_SPI_LED_SET_MESSAGE_LEN, GFP_KERNEL); + memcpy(message_buf, NEURONSPI_SPI_LED_SET_MESSAGE, NEURONSPI_SPI_LED_SET_MESSAGE_LEN); + message_buf[2] += id; + if (brightness > 0) { + message_buf[1] = 0x01; + } else { + message_buf[1] = 0x00; + } + crc1 = neuronspi_spi_crc(message_buf, 4, 0); + memcpy(&message_buf[4], &crc1, 2); + if (!d_data->reserved_device) { + neuronspi_spi_send_message(spi_dev, message_buf, recv_buf, NEURONSPI_SPI_LED_SET_MESSAGE_LEN, frequency, 25, 0); + } + printk(KERN_INFO "NEURONSPI: Brightness set to %d on led %d\n", brightness, id); + kfree(message_buf); + kfree(recv_buf); +} + +int neuronspi_spi_gpio_di_get(struct spi_device* spi_dev, u32 id) +{ + u8 *recv_buf; + bool ret = 0; + u32 offset = id / 16; + struct neuronspi_driver_data *d_data = spi_get_drvdata(spi_dev); + recv_buf = kzalloc(4, GFP_KERNEL); + printk(KERN_INFO "NEURONSPI: REGMAP TEST: %d\n", regmap_read(d_data->reg_map, d_data->regstart_table->di_val_reg + offset, (void*)recv_buf)); + if (*recv_buf & (0x1 << offset)) { + ret = 1; + } + kfree(recv_buf); + printk(KERN_INFO "NEURONSPI: GPIO DI %d get %d\n", id, ret); + return ret; +} + +int neuronspi_spi_gpio_do_set(struct spi_device* spi_dev, u32 id, int value) +{ + u32 current_value = 0; + bool ret = 0; + u32 offset = id / 16; + u16 off_val = value << (id % 16); + u16 mask = ~(1 << (id % 16)); + struct neuronspi_driver_data *d_data = spi_get_drvdata(spi_dev); + regmap_read(d_data->reg_map, d_data->regstart_table->do_val_reg + offset, ¤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); + printk(KERN_INFO "NEURONSPI: GPIO DO %d set %d\n", id, value); + return ret; +} + +int neuronspi_spi_gpio_ro_set(struct spi_device* spi_dev, u32 id, int value) +{ + u32 current_value = 0; + bool ret = 0; + u32 offset = id / 16; + u16 off_val = value << (id % 16); + u16 mask = ~(1 << (id % 16)); + struct neuronspi_driver_data *d_data = spi_get_drvdata(spi_dev); + regmap_read(d_data->reg_map, d_data->regstart_table->ro_val_reg + offset, ¤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); + printk(KERN_INFO "NEURONSPI: GPIO RO %d set %d\n", id, value); + return ret; +} + + + +s32 neuronspi_spi_probe(struct spi_device *spi) +{ + const struct neuronspi_devtype *devtype; + struct sched_param sched_param = { .sched_priority = MAX_RT_PRIO / 2 }; + + struct neuronspi_driver_data *n_spi; + + s32 ret, i, no_irq = 0; + u8 uart_count = 0; + n_spi = kzalloc(sizeof *n_spi, GFP_KERNEL); + spin_lock(&neuronspi_probe_spinlock); + neuronspi_probe_count++; + spin_unlock(&neuronspi_probe_spinlock); + if (!n_spi) + return -ENOMEM; + printk(KERN_INFO "NEURONSPI: Neuronspi Probe Started\n"); + if (n_spi == NULL || spi == NULL) { + return -8; + } +#if NEURONSPI_DETAILED_DEBUG > 0 + printk(KERN_DEBUG "NEURONSPI: Chip Max Hz-%d\n",spi->master->max_speed_hz); +#endif + /* Setup SPI bus */ + spi->bits_per_word = 8; + spi->mode = spi->mode ? spi->mode : SPI_MODE_0; + spi->max_speed_hz = spi->max_speed_hz ? spi->max_speed_hz : 12000000; + ret = spi_setup(spi); + n_spi->neuron_index = spi->chip_select - 1; + n_spi->reserved_device = 0; + + if (neuron_plc_dev == NULL) { + neuron_plc_dev = platform_device_alloc("unipi_plc", -1); + neuron_plc_dev->dev.groups = neuron_plc_attr_groups; + platform_device_add(neuron_plc_dev); + } + + if (ret) + return ret; +#if NEURONSPI_DETAILED_DEBUG > 0 + printk(KERN_DEBUG "NEURONSPI: Chip Max Hz-%d %d\n", spi->master->max_speed_hz, spi->max_speed_hz); +#endif + if (spi->dev.of_node) { + const struct of_device_id *of_id = + of_match_device(neuronspi_id_match, &spi->dev); + if (!of_id) { + printk(KERN_DEBUG "NEURONSPI: Probe %s does not match a device!\n", *(&spi->dev.of_node->full_name)); + return -ENODEV; + } + of_property_read_u32_array(spi->dev.of_node, "neuron-board-index", &(n_spi->neuron_index), 1); + //print_device_tree_node(spi->dev.of_node->parent, 0); + devtype = (struct neuronspi_devtype *)of_id->data; +#if NEURONSPI_DETAILED_DEBUG > 0 + printk(KERN_INFO "DEVICE TREE NODE FOUND %d\n", n_spi->neuron_index); +#endif + } else { + const struct spi_device_id *id_entry = spi_get_device_id(spi); + devtype = (struct neuronspi_devtype *)id_entry->driver_data; + } + + + kthread_init_worker(&n_spi->primary_worker); + + n_spi->primary_worker_task = kthread_run(kthread_worker_fn, &n_spi->primary_worker, "neuronspi"); + if (IS_ERR(n_spi->primary_worker_task )) { + ret = PTR_ERR(n_spi->primary_worker_task); + return ret; + } + sched_setscheduler(n_spi->primary_worker_task, SCHED_FIFO, &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_KERNEL); + n_spi->send_buf = kzalloc(NEURONSPI_BUFFER_MAX, GFP_KERNEL); + n_spi->first_probe_reply = kzalloc(NEURONSPI_PROBE_MESSAGE_LEN, GFP_KERNEL); // allocate space for initial probe + n_spi->second_probe_reply = kzalloc(NEURONSPI_PROBE_MESSAGE_LEN, GFP_KERNEL); // allocate space for uart probe + n_spi->lower_board_id = 0xFF; + n_spi->upper_board_id = 0xFF; + 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); + + // Throw away the first message - the associated SPI Master is sometimes not properly initialised at this point + 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); + i++; + if (i > 1000) { // Sanity check to prevent looping if we get constant UART/0x41 messages + ret = -4; + kfree(n_spi); + printk(KERN_INFO "NEURONSPI: Probe did not detect a valid Neuron device on CS %d\n", spi->chip_select); + return ret; + } + } while (n_spi->first_probe_reply[0] == 0x41); // UART messages should be ignored + + 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; + for (i = 0; i < NEURONSPI_BOARDTABLE_LEN; i++) { + if (n_spi->first_probe_reply[19] == 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]; + } + if (n_spi->first_probe_reply[17] == NEURONSPI_BOARDTABLE[i].index) { + n_spi->combination_id = n_spi->first_probe_reply[17]; + n_spi->upper_board_id = NEURONSPI_BOARDTABLE[i].upper_board_id; + } + } + } + } else { + ret = -5; + kfree(n_spi); + printk(KERN_INFO "NEURONSPI: Probe did not detect a valid Neuron device on CS %d\n", spi->chip_select); + return ret; + } + + if (n_spi->lower_board_id != 0xFF && n_spi->combination_id != 0xFF) { + n_spi->features = kzalloc(sizeof(struct neuronspi_board_features), GFP_KERNEL); + n_spi->features = &(NEURONSPI_BOARDTABLE[n_spi->combination_id].definition->features); + } else { + n_spi->features = NULL; + } + + 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])) { + n_spi->slower_model = 1; + n_spi->ideal_frequency = NEURONSPI_SLOWER_FREQ; + } + } + if (n_spi->lower_board_id != 0xFF && n_spi->combination_id != 0xFF) { + printk(KERN_INFO "NEURONSPI: Probe detected Neuron Board %s (L:%x U:%x C:%x) Index: %d Fw: v%d.%d on CS %d, \ +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]); + } else if (n_spi->lower_board_id != 0xFF) { + printk(KERN_INFO "NEURONSPI: Probe detected Neuron 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]); + } else { + printk(KERN_INFO "NEURONSPI: Probe detected Neuron 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]); + } + printk(KERN_INFO "NEURONSPI: Neuron device %s on CS %d uses SPI communication freq. %d Hz\n", + NEURONSPI_BOARDTABLE[n_spi->combination_id].definition->combination_name, + spi->chip_select, n_spi->ideal_frequency); + + n_spi->reg_map = regmap_init(&(spi->dev), &neuronspi_regmap_bus, spi, &neuronspi_regmap_config_default); + spin_lock_init(&n_spi->sysfs_regmap_lock); + if (n_spi->features) { + n_spi->regstart_table = kzalloc(sizeof(struct neuronspi_board_regstart_table), 1); + neuronspi_create_reg_starts(n_spi->regstart_table, NEURONSPI_BOARDTABLE[n_spi->combination_id].definition); + } else { + n_spi->regstart_table = NULL; + } + + + // Check for user-configurable LED devices + if (n_spi->features && n_spi->features->led_count > 0) { + printk(KERN_INFO "NEURONSPI: LED model %s with %d LEDs detected at CS: %d\n", + NEURONSPI_BOARDTABLE[n_spi->combination_id].definition->combination_name, + n_spi->features->led_count, spi->chip_select); + n_spi->led_driver = kzalloc(sizeof(struct neuronspi_led_driver) * n_spi->features->led_count, GFP_KERNEL); + for (i = 0; i < n_spi->features->led_count; i++) { + kthread_init_work(&(n_spi->led_driver[i].led_work), neuronspi_led_proc); + } + } + + + if (uart_count && neuronspi_uart == NULL) { // Register UART if not registered + neuronspi_uart = kzalloc(sizeof(struct uart_driver), GFP_KERNEL); + neuronspi_uart->owner = THIS_MODULE; + neuronspi_uart->dev_name = "ttyNS"; + neuronspi_uart->driver_name = "ttyNS"; + neuronspi_uart->nr = NEURONSPI_MAX_UART; + ret = uart_register_driver(neuronspi_uart); + if (ret) { + printk(KERN_ERR "NEURONSPI:Failed to register the neuronspi uart driver, ERR:%d\n", ret); + } else { +#if NEURONSPI_DETAILED_DEBUG > 0 + printk(KERN_DEBUG "NEURONSPI: UART driver registered successfully!\n"); +#endif + } + if (neuronspi_uart_glob_data != NULL) { + printk(KERN_ERR "NEURONSPI:Uart data already allocated!\n"); + } else { + neuronspi_uart_glob_data = kzalloc(sizeof(struct neuronspi_uart_data), GFP_KERNEL); +#if NEURONSPI_DETAILED_DEBUG > 0 + printk(KERN_DEBUG "NEURONSPI: UART driver data allocated successfully!\n"); +#endif + } + + } + if (neuronspi_uart_glob_data != NULL) { + n_spi->uart_data = neuronspi_uart_glob_data; + } + n_spi->char_driver = &neuronspi_cdrv; + if (uart_count) { + n_spi->serial_driver = neuronspi_uart; + } else { + n_spi->serial_driver = NULL; + } + n_spi->uart_count = uart_count; + +#if NEURONSPI_DETAILED_DEBUG > 0 + printk(KERN_DEBUG "NEURONSPI: CHIP SELECT %d\n", spi->chip_select); +#endif + spin_lock(&neuronspi_probe_spinlock); + neuronspi_s_dev[n_spi->neuron_index] = spi; + spi_set_drvdata(neuronspi_s_dev[n_spi->neuron_index], n_spi); + if (neuronspi_probe_count == NEURONSPI_MAX_DEVS) { + printk(KERN_INFO "NEURONSPI: MAXPROBECOUNT\n"); + neuronspi_model_id = neuronspi_find_model_id(neuronspi_probe_count); + } + spin_unlock(&neuronspi_probe_spinlock); + if (neuronspi_model_id != -1) { + printk(KERN_INFO "NEURONSPI: Detected Neuron board combination corresponding to %s\n", NEURONSPI_MODELTABLE[neuronspi_model_id].model_name); + } +#if NEURONSPI_DETAILED_DEBUG > 0 + printk(KERN_DEBUG "NEURONSPI: SPI IRQ: %d", spi->irq); +#endif + 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); + n_spi->board_device->dev.parent = &(neuron_plc_dev->dev); + n_spi->board_device->dev.groups = neuron_board_attr_groups; + n_spi->board_device->dev.driver = &neuronspi_spi_driver.driver; + platform_device_add(n_spi->board_device); + platform_set_drvdata(n_spi->board_device, n_spi); + + if (!(neuronspi_cdrv.major_number)) { // Register character device if it doesn't exist + ret = char_register_driver(); + if (ret) { + printk(KERN_ERR "NEURONSPI: Failed to register the neuronspi character driver, ERR:%d\n", ret); + } + } + + if (n_spi->features) { + if (n_spi->features->led_count) { + for (i = 0; i < n_spi->features->led_count; i++) { + strcpy(n_spi->led_driver[i].name, "neuron:green:uled-x1"); + n_spi->led_driver[i].name[19] = i + '1'; + // Initialise the rest of the structure + n_spi->led_driver[i].id = i; + n_spi->led_driver[i].brightness = LED_OFF; + n_spi->led_driver[i].spi = spi; + spin_lock_init(&n_spi->led_driver[i].lock); + n_spi->led_driver[i].ldev.name = n_spi->led_driver[i].name; + n_spi->led_driver[i].ldev.brightness = n_spi->led_driver[i].brightness; + n_spi->led_driver[i].ldev.brightness_set = neuronspi_led_set_brightness; + led_classdev_register(&(n_spi->board_device->dev), &(n_spi->led_driver[i].ldev)); + } + } +#ifdef CONFIG_GPIOLIB + + if (n_spi->features->di_count) { + n_spi->di_driver = kzalloc(sizeof(struct neuronspi_di_driver*) * n_spi->features->di_count, GFP_KERNEL); + for (i = 0; i < n_spi->features->di_count; i++) { + n_spi->di_driver[i] = kzalloc(sizeof(struct neuronspi_di_driver), GFP_KERNEL); + strcpy(n_spi->di_driver[i]->name, "di_0_00"); + n_spi->di_driver[i]->name[3] = n_spi->neuron_index + '1'; + n_spi->di_driver[i]->name[5] = ((i + 1) / 10) + '0'; + n_spi->di_driver[i]->name[6] = ((i + 1) % 10) + '0'; + n_spi->di_driver[i]->di_index = i; + n_spi->di_driver[i]->spi = spi; + n_spi->di_driver[i]->plat_dev = platform_device_alloc(n_spi->di_driver[i]->name, -1); + n_spi->di_driver[i]->plat_dev->dev.parent = &(n_spi->board_device->dev); + n_spi->di_driver[i]->plat_dev->dev.groups = neuron_gpio_di_attr_groups; + n_spi->di_driver[i]->plat_dev->dev.driver = &neuronspi_spi_driver.driver; + platform_device_add(n_spi->di_driver[i]->plat_dev); + platform_set_drvdata(n_spi->di_driver[i]->plat_dev, n_spi->di_driver[i]); + n_spi->di_driver[i]->gpio_c.owner = THIS_MODULE; + n_spi->di_driver[i]->gpio_c.parent = &(n_spi->di_driver[i]->plat_dev->dev); + n_spi->di_driver[i]->gpio_c.label = "neuron_di"; + n_spi->di_driver[i]->gpio_c.can_sleep = 1; + n_spi->di_driver[i]->gpio_c.ngpio = 1; + n_spi->di_driver[i]->gpio_c.base = -1; + n_spi->di_driver[i]->gpio_c.direction_input = neuronspi_gpio_di_direction_input; + n_spi->di_driver[i]->gpio_c.get = neuronspi_gpio_di_get; + gpiochip_add_data(&n_spi->di_driver[i]->gpio_c, n_spi->di_driver[i]); + } + } + + if (n_spi->features->do_count) { + n_spi->do_driver = kzalloc(sizeof(struct neuronspi_do_driver*) * n_spi->features->do_count, GFP_KERNEL); + for (i = 0; i < n_spi->features->do_count; i++) { + n_spi->do_driver[i] = kzalloc(sizeof(struct neuronspi_do_driver), GFP_KERNEL); + strcpy(n_spi->do_driver[i]->name, "do_0_00"); + n_spi->do_driver[i]->name[3] = n_spi->neuron_index + '1'; + n_spi->do_driver[i]->name[5] = ((i + 1) / 10) + '0'; + n_spi->do_driver[i]->name[6] = ((i + 1) % 10) + '0'; + n_spi->do_driver[i]->do_index = i; + n_spi->do_driver[i]->spi = spi; + n_spi->do_driver[i]->plat_dev = platform_device_alloc(n_spi->do_driver[i]->name, -1); + n_spi->do_driver[i]->plat_dev->dev.parent = &(n_spi->board_device->dev); + n_spi->do_driver[i]->plat_dev->dev.groups = neuron_gpio_do_attr_groups; + n_spi->do_driver[i]->plat_dev->dev.driver = &neuronspi_spi_driver.driver; + platform_device_add(n_spi->do_driver[i]->plat_dev); + platform_set_drvdata(n_spi->do_driver[i]->plat_dev, n_spi->do_driver[i]); + n_spi->do_driver[i]->gpio_c.owner = THIS_MODULE; + n_spi->do_driver[i]->gpio_c.parent = &(n_spi->do_driver[i]->plat_dev->dev); + n_spi->do_driver[i]->gpio_c.label = "neuron_do"; + n_spi->do_driver[i]->gpio_c.can_sleep = 1; + n_spi->do_driver[i]->gpio_c.ngpio = n_spi->features->do_count; + n_spi->do_driver[i]->gpio_c.base = -1; + n_spi->do_driver[i]->gpio_c.direction_output = neuronspi_gpio_do_direction_output; + n_spi->do_driver[i]->gpio_c.set = neuronspi_gpio_do_set; + gpiochip_add_data(&n_spi->do_driver[i]->gpio_c, n_spi->do_driver[i]); + } + } + + if (n_spi->features->ro_count) { + n_spi->ro_driver = kzalloc(sizeof(struct neuronspi_ro_driver*) * n_spi->features->ro_count, GFP_KERNEL); + for (i = 0; i < n_spi->features->ro_count; i++) { + n_spi->ro_driver[i] = kzalloc(sizeof(struct neuronspi_ro_driver), GFP_KERNEL); + strcpy(n_spi->ro_driver[i]->name, "ro_0_00"); + n_spi->ro_driver[i]->name[3] = n_spi->neuron_index + '1'; + n_spi->ro_driver[i]->name[5] = ((i + 1) / 10) + '0'; + n_spi->ro_driver[i]->name[6] = ((i + 1) % 10) + '0'; + n_spi->ro_driver[i]->ro_index = i; + n_spi->ro_driver[i]->spi = spi; + n_spi->ro_driver[i]->plat_dev = platform_device_alloc(n_spi->ro_driver[i]->name, -1); + n_spi->ro_driver[i]->plat_dev->dev.parent = &(n_spi->board_device->dev); + n_spi->ro_driver[i]->plat_dev->dev.groups = neuron_gpio_ro_attr_groups; + n_spi->ro_driver[i]->plat_dev->dev.driver = &neuronspi_spi_driver.driver; + platform_device_add(n_spi->ro_driver[i]->plat_dev); + platform_set_drvdata(n_spi->ro_driver[i]->plat_dev, n_spi->ro_driver[i]); + n_spi->ro_driver[i]->gpio_c.owner = THIS_MODULE; + n_spi->ro_driver[i]->gpio_c.parent = &(n_spi->ro_driver[i]->plat_dev->dev); + n_spi->ro_driver[i]->gpio_c.label = "neuron_ro"; + n_spi->ro_driver[i]->gpio_c.can_sleep = 1; + n_spi->ro_driver[i]->gpio_c.ngpio = n_spi->features->ro_count; + n_spi->ro_driver[i]->gpio_c.base = -1; + n_spi->ro_driver[i]->gpio_c.direction_output = neuronspi_gpio_ro_direction_output; + n_spi->ro_driver[i]->gpio_c.set = neuronspi_gpio_ro_set; + gpiochip_add_data(&n_spi->ro_driver[i]->gpio_c, n_spi->ro_driver[i]); + } + } + +#endif + if (n_spi->features->stm_ai_count) { + n_spi->stm_ai_driver = devm_iio_device_alloc(&(spi->dev), sizeof(struct neuronspi_stm_ai_data)); + ((struct neuronspi_stm_ai_data*)iio_priv(n_spi->stm_ai_driver))->parent = spi; + n_spi->stm_ai_driver->modes = INDIO_DIRECT_MODE; + n_spi->stm_ai_driver->currentmode = INDIO_DIRECT_MODE; + n_spi->stm_ai_driver->name = "ai_type_a"; + n_spi->stm_ai_driver->dev.parent = &(n_spi->board_device->dev); + dev_set_name(&n_spi->stm_ai_driver->dev, "ai_%d_1", (int)n_spi->neuron_index + 1); + n_spi->stm_ai_driver->num_channels = 2; + n_spi->stm_ai_driver->channels = neuronspi_stm_ai_chan_spec; + n_spi->stm_ai_driver->info = &neuronspi_stm_ai_info; + iio_device_register(n_spi->stm_ai_driver); + } + if (n_spi->features->stm_ao_count) { + n_spi->stm_ao_driver = devm_iio_device_alloc(&(spi->dev), sizeof(struct neuronspi_stm_ai_data)); + ((struct neuronspi_stm_ao_data*)iio_priv(n_spi->stm_ao_driver))->parent = spi; + n_spi->stm_ao_driver->modes = INDIO_DIRECT_MODE; + n_spi->stm_ao_driver->currentmode = INDIO_DIRECT_MODE; + n_spi->stm_ao_driver->name = "ao_type_a"; + n_spi->stm_ao_driver->dev.parent = &(n_spi->board_device->dev); + dev_set_name(&n_spi->stm_ao_driver->dev, "ao_%d_1", (int)n_spi->neuron_index + 1); + n_spi->stm_ao_driver->num_channels = 3; + n_spi->stm_ao_driver->channels = neuronspi_stm_ao_chan_spec; + n_spi->stm_ao_driver->info = &neuronspi_stm_ao_info; + iio_device_register(n_spi->stm_ao_driver); + } + if (n_spi->features->sec_ai_count) { + n_spi->sec_ai_driver = kzalloc(sizeof(struct neuronspi_sec_ai_data*) * n_spi->features->sec_ai_count, GFP_KERNEL); + for (i = 0; i < n_spi->features->sec_ai_count; i++) { + n_spi->sec_ai_driver[i] = devm_iio_device_alloc(&(spi->dev), sizeof(struct neuronspi_sec_ai_data)); + ((struct neuronspi_sec_ai_data*)iio_priv(n_spi->sec_ai_driver[i]))->parent = spi; + n_spi->sec_ai_driver[i]->modes = INDIO_DIRECT_MODE; + n_spi->sec_ai_driver[i]->currentmode = INDIO_DIRECT_MODE; + n_spi->sec_ai_driver[i]->name = "ai_type_b"; + n_spi->sec_ai_driver[i]->dev.parent = &(n_spi->board_device->dev); + dev_set_name(&n_spi->sec_ai_driver[i]->dev, "ai_%d_%d", (int)n_spi->neuron_index + 1, (int)i + 1); + n_spi->sec_ai_driver[i]->num_channels = 3; + n_spi->sec_ai_driver[i]->channels = neuronspi_sec_ai_chan_spec; + n_spi->sec_ai_driver[i]->info = &neuronspi_sec_ai_info; + iio_device_register(n_spi->sec_ai_driver[i]); + } + } + if (n_spi->features->sec_ao_count) { + n_spi->sec_ao_driver = kzalloc(sizeof(struct neuronspi_sec_ao_data*) * n_spi->features->sec_ao_count, GFP_KERNEL); + for (i = 0; i < n_spi->features->sec_ao_count; i++) { + n_spi->sec_ao_driver[i] = devm_iio_device_alloc(&(spi->dev), sizeof(struct neuronspi_sec_ao_data)); + ((struct neuronspi_sec_ao_data*)iio_priv(n_spi->sec_ao_driver[i]))->parent = spi; + n_spi->sec_ao_driver[i]->modes = INDIO_DIRECT_MODE; + n_spi->sec_ao_driver[i]->currentmode = INDIO_DIRECT_MODE; + n_spi->sec_ao_driver[i]->name = "ao_type_b"; + n_spi->sec_ao_driver[i]->dev.parent = &(n_spi->board_device->dev); + dev_set_name(&n_spi->sec_ao_driver[i]->dev, "ao_%d_%d", (int)n_spi->neuron_index + 1, (int)i + 1); + n_spi->sec_ao_driver[i]->num_channels = 1; + n_spi->sec_ao_driver[i]->channels = neuronspi_sec_ao_chan_spec; + n_spi->sec_ao_driver[i]->info = &neuronspi_sec_ao_info; + iio_device_register(n_spi->sec_ao_driver[i]); + } + } + } + + if (uart_count) { +#if NEURONSPI_DETAILED_DEBUG > 0 + printk(KERN_DEBUG "NEURONSPI: UART registration 1\n"); +#endif + n_spi->uart_buf = kzalloc(NEURONSPI_FIFO_SIZE, GFP_KERNEL); + neuronspi_uart_probe(spi, n_spi->neuron_index); +#if NEURONSPI_DETAILED_DEBUG > 0 + printk(KERN_DEBUG "NEURONSPI: UART PROBE MCTRL:%d\n", neuronspi_spi_uart_get_cflag(spi, 0)); +#endif + } +#if NEURONSPI_DETAILED_DEBUG > 0 + printk(KERN_DEBUG "NEURONSPI: UART registration\n"); +#endif + 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])) { + no_irq = 1; + } + } + + n_spi->poll_thread = NULL; + 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 "NEURONSPI: IRQ registration, ret:%d\n", ret); +#endif + } else { + n_spi->no_irq = 1; +#if NEURONSPI_DETAILED_DEBUG > 0 + printk(KERN_DEBUG "NEURONSPI: NO IRQ ON THIS MODEL !!\n"); +#endif + } + + 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_KERNEL); + recv_buf = kzalloc(NEURONSPI_SPI_UART_GET_CFLAG_MESSAGE_LEN, GFP_KERNEL); + memcpy(message_buf, NEURONSPI_SPI_UART_GET_CFLAG_MESSAGE, NEURONSPI_SPI_UART_GET_CFLAG_MESSAGE_LEN); + crc1 = neuronspi_spi_crc(message_buf, 4, 0); + memcpy(&message_buf[4], &crc1, 2); + crc2 = neuronspi_spi_crc(&message_buf[6], NEURONSPI_SPI_UART_GET_CFLAG_MESSAGE_LEN - 8, crc1); + memcpy(&message_buf[NEURONSPI_SPI_UART_GET_CFLAG_MESSAGE_LEN - 2], &crc2, 2); + if (!d_data->reserved_device) { + neuronspi_spi_send_message(spi_dev, message_buf, recv_buf, NEURONSPI_SPI_UART_GET_CFLAG_MESSAGE_LEN, frequency, 65, 1); + } + ret = ((u32*)recv_buf)[5]; +#if NEURONSPI_DETAILED_DEBUG > 0 + printk(KERN_INFO "NEURONSPI: SPI TERMIOS Get, Dev-CS:%d, val:%x\n", spi_dev->chip_select, ret); +#endif + kfree(message_buf); + kfree(recv_buf); + return ret; +} + +s32 neuronspi_spi_remove(struct spi_device *spi) +{ + int i; + struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi); + if (n_spi) { + if (n_spi->led_driver) { + for (i = 0; i < n_spi->features->led_count; i++) { + led_classdev_unregister(&(n_spi->led_driver[i].ldev)); + } + kthread_flush_worker(&n_spi->primary_worker); + kfree(n_spi->led_driver); + n_spi->led_driver = NULL; + } + printk(KERN_INFO "NEURONSPI: LED DRIVER UNREGISTERED\n"); + if (n_spi->di_driver) { + for (i = 0; i < n_spi->features->di_count; i++) { + gpiochip_remove(&n_spi->di_driver[i]->gpio_c); + platform_set_drvdata(n_spi->di_driver[i]->plat_dev, 0); + platform_device_unregister(n_spi->di_driver[i]->plat_dev); + kfree(n_spi->di_driver[i]); + } + kfree(n_spi->di_driver); + } + if (n_spi->do_driver) { + for (i = 0; i < n_spi->features->do_count; i++) { + gpiochip_remove(&n_spi->do_driver[i]->gpio_c); + platform_set_drvdata(n_spi->do_driver[i]->plat_dev, 0); + platform_device_unregister(n_spi->do_driver[i]->plat_dev); + kfree(n_spi->do_driver[i]); + } + kfree(n_spi->do_driver); + } + if (n_spi->ro_driver) { + for (i = 0; i < n_spi->features->ro_count; i++) { + gpiochip_remove(&n_spi->ro_driver[i]->gpio_c); + platform_set_drvdata(n_spi->ro_driver[i]->plat_dev, 0); + platform_device_unregister(n_spi->ro_driver[i]->plat_dev); + kfree(n_spi->ro_driver[i]); + } + kfree(n_spi->ro_driver); + } + printk(KERN_INFO "NEURONSPI: GPIO DRIVER UNREGISTERED\n"); + if (n_spi->stm_ai_driver) { + iio_device_unregister(n_spi->stm_ai_driver); + } + if (n_spi->stm_ao_driver) { + iio_device_unregister(n_spi->stm_ao_driver); + } + if (n_spi->sec_ai_driver) { + for (i = 0; i < n_spi->features->sec_ai_count; i++) { + iio_device_unregister(n_spi->sec_ai_driver[i]); + } + kfree(n_spi->sec_ai_driver); + n_spi->sec_ai_driver = NULL; + } + if (n_spi->sec_ao_driver) { + for (i = 0; i < n_spi->features->sec_ao_count; i++) { + iio_device_unregister(n_spi->sec_ao_driver[i]); + } + kfree(n_spi->sec_ao_driver); + n_spi->sec_ao_driver = NULL; + } + printk(KERN_INFO "NEURONSPI: 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; + } + printk(KERN_INFO "NEURONSPI: SPI/UART DRIVER UNREGISTERED\n"); + if (n_spi->board_device) { + platform_set_drvdata(n_spi->board_device, 0); + platform_device_unregister(n_spi->board_device); + } + kfree(n_spi); + } + return 0; +} + +s32 char_register_driver(void) +{ + s32 ret = 0; + + // Character device registration +#if NEURONSPI_DETAILED_DEBUG > 0 + printk(KERN_DEBUG "NEURONSPI: Initialising Character Device\n"); +#endif + 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 "NEURONSPI: registered correctly with major number %d\n", neuronspi_cdrv.major_number); +#endif + + // Character class registration + neuronspi_cdrv.driver_class = class_create(THIS_MODULE, NEURON_DEVICE_CLASS); + if (IS_ERR(neuronspi_cdrv.driver_class)) { + unregister_chrdev(neuronspi_cdrv.major_number, NEURON_DEVICE_NAME); + 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 "NEURONSPI: device class registered correctly\n"); +#endif + + // 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); + if (IS_ERR(neuronspi_cdrv.dev)) { + class_destroy(neuronspi_cdrv.driver_class); + unregister_chrdev(neuronspi_cdrv.major_number, NEURON_DEVICE_NAME); + printk(KERN_ALERT "NEURONSPI: Failed to create the device\n"); + return PTR_ERR(neuronspi_cdrv.dev); + } +#if NEURONSPI_DETAILED_DEBUG > 0 + printk(KERN_DEBUG "NEURONSPI: device class created correctly\n"); +#endif + return ret; +} + +s32 char_unregister_driver(void) +{ + device_destroy(neuronspi_cdrv.driver_class, MKDEV(neuronspi_cdrv.major_number, 0)); // Destroy the device + class_unregister(neuronspi_cdrv.driver_class); // Unregister the class + class_destroy(neuronspi_cdrv.driver_class); // Destroy the class + unregister_chrdev(neuronspi_cdrv.major_number, NEURON_DEVICE_NAME); // Unregister the major number + printk(KERN_INFO "NEURONSPI: Device unloaded successfully\n"); + return 0; +} + +/********************* + * Final definitions * + *********************/ + +MODULE_ALIAS("spi:neuronspi"); + +static s32 __init neuronspi_init(void) +{ + s32 ret = 0; + neuronspi_spi_w_spinlock = kzalloc(sizeof(struct spinlock), GFP_KERNEL); + spin_lock_init(neuronspi_spi_w_spinlock); + mutex_init(&neuronspi_master_mutex); + memset(&neuronspi_s_dev, 0, sizeof(neuronspi_s_dev)); + ret = spi_register_driver(&neuronspi_spi_driver); + if (ret < 0) { + printk(KERN_ERR "NEURONSPI: Failed to init neuronspi spi --> %d\n", ret); + return ret; + } else { +#ifdef NEURONSPI_MAJOR_VERSIONSTRING + printk(KERN_INFO "NEURONSPI: SPI Driver Registered, Major Version: %s\n", NEURONSPI_MAJOR_VERSIONSTRING); +#else + printk(KERN_INFO "NEURONSPI: SPI Driver Registered\n"); +#endif + } + neuronspi_invalidate_thread = kthread_create(neuronspi_regmap_invalidate, NULL, "neuronspi_inv"); + if (neuronspi_invalidate_thread != NULL) { + wake_up_process(neuronspi_invalidate_thread); + } + return ret; +} +__attribute__((unused)) module_init(neuronspi_init); + +static void __exit neuronspi_exit(void) +{ +#if NEURONSPI_DETAILED_DEBUG > 0 + printk(KERN_INFO "NEURONSPI: Open Counter is %d\n", neuronspi_cdrv.open_counter); +#endif + if (neuronspi_invalidate_thread) { + kthread_stop(neuronspi_invalidate_thread); + } + char_unregister_driver(); + if (neuronspi_uart) { + neuronspi_uart_remove(neuronspi_uart_glob_data); + uart_unregister_driver(neuronspi_uart); + kfree(neuronspi_uart); + kfree(neuronspi_uart_glob_data); + } + spi_unregister_driver(&neuronspi_spi_driver); + if (neuron_plc_dev) { + platform_device_unregister(neuron_plc_dev); + } + kfree(neuronspi_spi_w_spinlock); + printk(KERN_INFO "NEURONSPI: SPI Driver Unregistered\n"); +} +__attribute__((unused)) module_exit(neuronspi_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Tomas Knot "); +MODULE_DESCRIPTION("UniPi Neuron driver"); diff --git a/modules/unipi/src/unipi_spi.h b/modules/unipi/src/unipi_spi.h new file mode 100644 index 0000000..75e795f --- /dev/null +++ b/modules/unipi/src/unipi_spi.h @@ -0,0 +1,512 @@ +/* + * UniPi Neuron tty serial driver - Copyright (C) 2017 UniPi Technologies + * Author: Tomas Knot + * + * Based on the SC16IS7xx driver by Jon Ringle , + * which was in turn based on max310x.c, by Alexander Shiyan + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +#ifndef MODULES_NEURON_SPI_SRC_UNIPI_SPI_H_ +#define MODULES_NEURON_SPI_SRC_UNIPI_SPI_H_ + +/************ + * Includes * + ************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "unipi_common.h" +#include "unipi_platform.h" +#include "unipi_sysfs.h" +#include "unipi_iio.h" + +/******************** + * Module Constants * + ********************/ + +#define NEURONSPI_SLOWER_MODELS_LEN 3 +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, + 0x04, 0x00, 0xe8, 0x03, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x12, 0x16 +}; + +#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 +}; + +#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 +}; + +#define NEURONSPI_SPI_UART_LONG_MESSAGE_LEN 8 +static const u8 NEURONSPI_SPI_UART_LONG_MESSAGE[NEURONSPI_SPI_UART_LONG_MESSAGE_LEN] = { + 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00 +}; + +#define NEURONSPI_SPI_UART_READ_MESSAGE_LEN 14 +static const u8 NEURONSPI_SPI_UART_READ_MESSAGE[NEURONSPI_SPI_UART_READ_MESSAGE_LEN] = { + 0x65, 0x06, 0x00, 0x00, 0x44, 0x69, + 0x65, 0x03, 0x00, 0x00, 0x00, 0x05, + 0x6a, 0x0c +}; + +#define NEURONSPI_SPI_IRQ_SET_MESSAGE_LEN 14 +static const u8 NEURONSPI_SPI_IRQ_SET_MESSAGE[NEURONSPI_SPI_UART_READ_MESSAGE_LEN] = { + 0x06, 0x06, 0xef, 0x03, 0x00, 0x00, + 0x06, 0x01, 0xef, 0x03, 0x05, 0x00, + 0x00, 0x00 +}; + +#define NEURONSPI_SPI_UART_GET_CFLAG_MESSAGE_LEN 16 +static const u8 NEURONSPI_SPI_UART_GET_CFLAG_MESSAGE[NEURONSPI_SPI_UART_GET_CFLAG_MESSAGE_LEN] = { + 0x04, 0x08, 0xf4, 0x01, 0x00, 0x00, + 0x04, 0x02, 0xf4, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 +}; + +#define NEURONSPI_SPI_UART_GET_LDISC_MESSAGE_LEN 16 +static const u8 NEURONSPI_SPI_UART_GET_LDISC_MESSAGE[NEURONSPI_SPI_UART_GET_LDISC_MESSAGE_LEN] = { + 0x04, 0x08, 0xf6, 0x01, 0x00, 0x00, + 0x04, 0x02, 0xf6, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 +}; + +#define NEURONSPI_SPI_UART_SET_CFLAG_MESSAGE_LEN 16 +static const u8 NEURONSPI_SPI_UART_SET_CFLAG_MESSAGE[NEURONSPI_SPI_UART_SET_CFLAG_MESSAGE_LEN] = { + 0x06, 0x08, 0xf4, 0x01, 0x00, 0x00, + 0x06, 0x02, 0xf4, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 +}; + +#define NEURONSPI_SPI_LED_SET_MESSAGE_LEN 6 +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] = { + 0, 1408, 3968, 2560, 7040, 7680, 5120, 4480, 13184, 13824, 15360, +14720, 10240, 11648, 10112, 8704, 25472, 26112, 27648, 27008, 30720, 32128, +30592, 29184, 20480, 21888, 24448, 23040, 19328, 19968, 17408, 16768, 50048, +50688, 52224, 51584, 55296, 56704, 55168, 53760, 61440, 62848, 65408, 64000, +60288, 60928, 58368, 57728, 40960, 42368, 44928, 43520, 48000, 48640, 46080, +45440, 37760, 38400, 39936, 39296, 34816, 36224, 34688, 33280, 33665, 34305, +35841, 35201, 38913, 40321, 38785, 37377, 45057, 46465, 49025, 47617, 43905, +44545, 41985, 41345, 57345, 58753, 61313, 59905, 64385, 65025, 62465, 61825, +54145, 54785, 56321, 55681, 51201, 52609, 51073, 49665, 16385, 17793, 20353, +18945, 23425, 24065, 21505, 20865, 29569, 30209, 31745, 31105, 26625, 28033, +26497, 25089, 9089, 9729, 11265, 10625, 14337, 15745, 14209, 12801, 4097, + 5505, 8065, 6657, 2945, 3585, 1025, 385, 899, 1539, 3075, 2435, + 6147, 7555, 6019, 4611, 12291, 13699, 16259, 14851, 11139, 11779, 9219, + 8579, 24579, 25987, 28547, 27139, 31619, 32259, 29699, 29059, 21379, 22019, +23555, 22915, 18435, 19843, 18307, 16899, 49155, 50563, 53123, 51715, 56195, +56835, 54275, 53635, 62339, 62979, 64515, 63875, 59395, 60803, 59267, 57859, +41859, 42499, 44035, 43395, 47107, 48515, 46979, 45571, 36867, 38275, 40835, +39427, 35715, 36355, 33795, 33155, 32770, 34178, 36738, 35330, 39810, 40450, +37890, 37250, 45954, 46594, 48130, 47490, 43010, 44418, 42882, 41474, 58242, +58882, 60418, 59778, 63490, 64898, 63362, 61954, 53250, 54658, 57218, 55810, +52098, 52738, 50178, 49538, 17282, 17922, 19458, 18818, 22530, 23938, 22402, +20994, 28674, 30082, 32642, 31234, 27522, 28162, 25602, 24962, 8194, 9602, +12162, 10754, 15234, 15874, 13314, 12674, 4994, 5634, 7170, 6530, 2050, + 3458, 1922, 514 +}; + +static const struct of_device_id neuronspi_id_match[] = { + {.compatible = "unipi,neuron"}, + {.compatible = NEURON_DEVICE_NAME}, + {} +}; + +/*************** + * Definitions * + ***************/ + +#define NEURON_INT_RX_NOT_EMPTY 0x1 +#define NEURON_INT_TX_FINISHED 0x2 +#define NEURON_INT_RX_MODBUS 0x4 +#define NEURON_INT_DI_CHANGED 0x8 +#define NEURON_INT_ID_MASK 0x0f +#define NEURON_INT_NO_INT_BIT 0x0f + +#define NEURONSPI_RECONF_MD (1 << 0) +#define NEURONSPI_RECONF_IER (1 << 1) +#define NEURONSPI_RECONF_RS485 (1 << 2) + +#define MODBUS_FIRST_DATA_BYTE 10 + +#define MODBUS_MAX_READ_BITS 2000 +#define MODBUS_MAX_WRITE_BITS 1968 +#define MODBUS_MAX_READ_REGISTERS 125 +#define MODBUS_MAX_WRITE_REGISTERS 123 +#define MODBUS_MAX_WR_WRITE_REGISTERS 121 +#define MODBUS_MAX_WR_READ_REGISTERS 125 + +/************************* + * Function Declarations * + *************************/ + +int neuronspi_open (struct inode *, struct file *); +int neuronspi_release (struct inode *, struct file *); +ssize_t neuronspi_read (struct file *, char *, size_t, loff_t *); +ssize_t neuronspi_write (struct file *, const char *, size_t, loff_t *); +s32 char_register_driver(void); +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); +void neuronspi_spi_send_message(struct spi_device *spi_dev, u8 *send_buf, u8 *recv_buf, s32 len, s32 freq, s32 delay, s32 send_header); +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); +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); +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); +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_iio_stm_ao_set_current(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int val, int val2, long mask); +void neuronspi_spi_iio_sec_ai_read_voltage(struct iio_dev *iio_dev, struct iio_chan_spec const *ch, int *val, int *val2, long mask); +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); +int neuronspi_spi_gpio_di_get(struct spi_device* spi_dev, u32 id); + +/*********************** + * Function structures * + ***********************/ + +// Host driver struct +extern struct spi_driver neuronspi_spi_driver; +extern struct file_operations file_ops; + +static const struct regmap_bus neuronspi_regmap_bus = +{ + .fast_io = 1, + .write = neuronspi_regmap_hw_write, + .gather_write = neuronspi_regmap_hw_gather_write, + .reg_write = neuronspi_regmap_hw_reg_write, + .read = neuronspi_regmap_hw_read, + .reg_read = neuronspi_regmap_hw_reg_read, + .reg_format_endian_default = REGMAP_ENDIAN_NATIVE, + .val_format_endian_default = REGMAP_ENDIAN_NATIVE, + .max_raw_read = 200, // CRC and other overhead not included + .max_raw_write = 200, // CRC and other overhead not included +}; + +static const struct regmap_config neuronspi_regmap_config_default = +{ + .name = "Neuronspi Regmap", + .reg_bits = 16, + .reg_stride = 0, + .pad_bits = 0, + .val_bits = 16, + .max_register = 65535, + .cache_type = REGCACHE_RBTREE, + .use_single_rw = 0, + .can_multi_write = 1, +}; + +static const struct iio_chan_spec neuronspi_stm_ai_chan_spec[] = { + { + .type = IIO_VOLTAGE, + .indexed = 1, + .channel = 0, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .output = 0 + }, + { + .type = IIO_CURRENT, + .indexed = 1, + .channel = 1, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .output = 0 + } +}; + +static const struct iio_chan_spec neuronspi_stm_ao_chan_spec[] = { + { + .type = IIO_VOLTAGE, + .indexed = 1, + .channel = 0, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .output = 1 + }, + { + .type = IIO_CURRENT, + .indexed = 1, + .channel = 1, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .output = 1 + }, + { + .type = IIO_RESISTANCE, + .indexed = 1, + .channel = 2, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .output = 0 + } +}; + +static const struct iio_chan_spec neuronspi_sec_ai_chan_spec[] = { + { + .type = IIO_VOLTAGE, + .indexed = 1, + .channel = 0, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .output = 0 + }, + { + .type = IIO_CURRENT, + .indexed = 1, + .channel = 1, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .output = 0 + }, + { + .type = IIO_RESISTANCE, + .indexed = 1, + .channel = 2, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .output = 0 + } +}; + +static const struct iio_chan_spec neuronspi_sec_ao_chan_spec[] = { + { + .type = IIO_VOLTAGE, + .indexed = 1, + .channel = 0, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .output = 1 + } +}; + +static const struct iio_info neuronspi_stm_ai_info = { + .read_raw = neuronspi_iio_stm_ai_read_raw, + .driver_module = THIS_MODULE, + .attrs = &neuron_stm_ai_group, +}; + +static const struct iio_info neuronspi_stm_ao_info = { + .read_raw = neuronspi_iio_stm_ao_read_raw, + .write_raw = neuronspi_iio_stm_ao_write_raw, + .driver_module = THIS_MODULE, + .attrs = &neuron_stm_ao_group, +}; + +static const struct iio_info neuronspi_sec_ai_info = { + .read_raw = neuronspi_iio_sec_ai_read_raw, + .driver_module = THIS_MODULE, + .attrs = &neuron_sec_ai_group, +}; + +static const struct iio_info neuronspi_sec_ao_info = { + .write_raw = neuronspi_iio_sec_ao_write_raw, + .driver_module = THIS_MODULE, + .attrs = &neuron_sec_ao_group, +}; + +// These defines need to be at the end +#define to_neuronspi_uart_data(p,e) ((container_of((p), struct neuronspi_uart_data, e))) +#define to_neuronspi_port(p,e) ((container_of((p), struct neuronspi_port, e))) +#define to_led_driver(p,e) ((container_of((p), struct neuronspi_led_driver, e))) +#define to_uart_port(p,e) ((container_of((p), struct uart_port, e))) + + +/********************* + * In-line Functions * + *********************/ + +static __always_inline u16 neuronspi_spi_crc(u8* inputstring, s32 length, u16 initval) +{ + s32 i; + u16 result = initval; + for (i=0; i> 8) ^ NEURONSPI_CRC16TABLE[(result ^ inputstring[i]) & 0xff]; + } + 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; + *buf_outp = kzalloc(6, GFP_KERNEL); + *buf_inp = kzalloc(6, GFP_KERNEL); + (*buf_inp)[0] = 0x05; + (*buf_inp)[1] = data; + (*buf_inp)[2] = start & 0xFF; + (*buf_inp)[3] = start >> 8; + crc1 = neuronspi_spi_crc(*buf_inp, 4, 0); + memcpy(&(*buf_inp)[4], &crc1, 2); + return 6; +} + +static __always_inline size_t neuronspi_spi_compose_single_coil_read(u16 start, u8 **buf_inp, u8 **buf_outp) +{ + u16 crc1, crc2; + *buf_outp = kzalloc(14, GFP_KERNEL); + *buf_inp = kzalloc(14, GFP_KERNEL); + (*buf_inp)[0] = 0x01; + (*buf_inp)[1] = 0x06; + (*buf_inp)[2] = start & 0xFF; + (*buf_inp)[3] = start >> 8; + crc1 = neuronspi_spi_crc(*buf_inp, 4, 0); + memcpy(&(*buf_inp)[4], &crc1, 2); + memcpy(&(*buf_inp)[6], *buf_inp, 4); + crc2 = neuronspi_spi_crc(&(*buf_inp)[6], 6, crc1); + memcpy(&(*buf_inp)[12], &crc2, 2); + return 14; +} + +static __always_inline size_t neuronspi_spi_compose_multiple_coil_write(u8 number, u16 start, u8 **buf_inp, u8 **buf_outp, u8 *data) +{ + u16 crc1, crc2; + *buf_outp = kzalloc(12 + NEURONSPI_GET_COIL_READ_PHASE2_BYTE_LENGTH(number), GFP_KERNEL); + *buf_inp = kzalloc(12 + NEURONSPI_GET_COIL_READ_PHASE2_BYTE_LENGTH(number), GFP_KERNEL); + (*buf_inp)[0] = 0x0F; + (*buf_inp)[1] = 4 + NEURONSPI_GET_COIL_READ_PHASE2_BYTE_LENGTH(number); + (*buf_inp)[2] = start & 0xFF; + (*buf_inp)[3] = start >> 8; + crc1 = neuronspi_spi_crc(*buf_inp, 4, 0); + memcpy(&(*buf_inp)[4], &crc1, 2); + memcpy(&(*buf_inp)[6], *buf_inp, 4); + (*buf_inp)[7] = number; + memcpy(&(*buf_inp)[10], data, NEURONSPI_GET_COIL_READ_PHASE2_BYTE_LENGTH(number)); + crc2 = neuronspi_spi_crc(&(*buf_inp)[6], 4 + NEURONSPI_GET_COIL_READ_PHASE2_BYTE_LENGTH(number), crc1); + memcpy(&(*buf_inp)[10 + NEURONSPI_GET_COIL_READ_PHASE2_BYTE_LENGTH(number)], &crc2, 2); + return 12 + NEURONSPI_GET_COIL_READ_PHASE2_BYTE_LENGTH(number); +} + +static __always_inline size_t neuronspi_spi_compose_multiple_coil_read(u8 number, u16 start, u8 **buf_inp, u8 **buf_outp) +{ + u16 crc1, crc2; + *buf_outp = kzalloc(12 + NEURONSPI_GET_COIL_READ_PHASE2_BYTE_LENGTH(number), GFP_KERNEL); + *buf_inp = kzalloc(12 + NEURONSPI_GET_COIL_READ_PHASE2_BYTE_LENGTH(number), GFP_KERNEL); + (*buf_inp)[0] = 0x01; + (*buf_inp)[1] = 4 + NEURONSPI_GET_COIL_READ_PHASE2_BYTE_LENGTH(number); + (*buf_inp)[2] = start & 0xFF; + (*buf_inp)[3] = start >> 8; + crc1 = neuronspi_spi_crc(*buf_inp, 4, 0); + memcpy(&(*buf_inp)[4], &crc1, 2); + memcpy(&(*buf_inp)[6], *buf_inp, 4); + crc2 = neuronspi_spi_crc(&(*buf_inp)[6], 4 + NEURONSPI_GET_COIL_READ_PHASE2_BYTE_LENGTH(number), crc1); + memcpy(&(*buf_inp)[10 + NEURONSPI_GET_COIL_READ_PHASE2_BYTE_LENGTH(number)], &crc2, 2); + return 12 + NEURONSPI_GET_COIL_READ_PHASE2_BYTE_LENGTH(number); +} + +static __always_inline size_t neuronspi_spi_compose_single_register_write(u16 start, u8 **buf_inp, u8 **buf_outp, u16 data) +{ + u16 crc1, crc2; + *buf_outp = kzalloc(14, GFP_KERNEL); + *buf_inp = kzalloc(14, GFP_KERNEL); + (*buf_inp)[0] = 0x06; + (*buf_inp)[1] = 0x06; + (*buf_inp)[2] = start & 0xFF; + (*buf_inp)[3] = start >> 8; + printk(KERN_INFO "NEURONSPI: COMPOSE SINGLE WRITE DATA: %x\n", data); + crc1 = neuronspi_spi_crc(*buf_inp, 4, 0); + memcpy(&(*buf_inp)[4], &crc1, 2); + memcpy(&(*buf_inp)[6], *buf_inp, 4); + (*buf_inp)[7] = 0x01; + memcpy(&(*buf_inp)[10], &data, 2); + crc2 = neuronspi_spi_crc(&(*buf_inp)[6], 6, crc1); + memcpy(&(*buf_inp)[12], &crc2, 2); + return 14; +} + +static __always_inline size_t neuronspi_spi_compose_single_register_read(u16 start, u8 **buf_inp, u8 **buf_outp) +{ + u16 crc1, crc2; + *buf_outp = kzalloc(14, GFP_KERNEL); + *buf_inp = kzalloc(14, GFP_KERNEL); + (*buf_inp)[0] = 0x03; + (*buf_inp)[1] = 0x06; + (*buf_inp)[2] = start & 0xFF; + (*buf_inp)[3] = start >> 8; + crc1 = neuronspi_spi_crc(*buf_inp, 4, 0); + memcpy(&(*buf_inp)[4], &crc1, 2); + memcpy(&(*buf_inp)[6], *buf_inp, 4); + (*buf_inp)[7] = 0x01; + crc2 = neuronspi_spi_crc(&(*buf_inp)[6], 6, crc1); + memcpy(&(*buf_inp)[12], &crc2, 2); + return 14; +} + +static __always_inline size_t neuronspi_spi_compose_multiple_register_write(u8 number, u16 start, u8 **buf_inp, u8 **buf_outp, u8 *data) +{ + u16 crc1, crc2; + *buf_outp = kzalloc(12 + (number * 2), GFP_KERNEL); + *buf_inp = kzalloc(12 + (number * 2), GFP_KERNEL); + (*buf_inp)[0] = 0x10; + (*buf_inp)[1] = 4 + (number * 2); + (*buf_inp)[2] = start & 0xFF; + (*buf_inp)[3] = start >> 8; + crc1 = neuronspi_spi_crc(*buf_inp, 4, 0); + memcpy(&(*buf_inp)[4], &crc1, 2); + memcpy(&(*buf_inp)[6], *buf_inp, 4); + (*buf_inp)[7] = number; + memcpy(&(*buf_inp)[10], data, number * 2); + crc2 = neuronspi_spi_crc(&(*buf_inp)[6], 4 + (number * 2), crc1); + memcpy(&(*buf_inp)[10 + (number * 2)], &crc2, 2); + return 12 + (number * 2); +} + +static __always_inline size_t neuronspi_spi_compose_multiple_register_read(u8 number, u16 start, u8 **buf_inp, u8 **buf_outp) +{ + u16 crc1, crc2; + *buf_outp = kzalloc(12 + (number * 2), GFP_KERNEL); + *buf_inp = kzalloc(12 + (number * 2), GFP_KERNEL); + (*buf_inp)[0] = 0x03; + (*buf_inp)[1] = 4 + (number * 2); + (*buf_inp)[2] = start & 0xFF; + (*buf_inp)[3] = start >> 8; + crc1 = neuronspi_spi_crc(*buf_inp, 4, 0); + memcpy(&(*buf_inp)[4], &crc1, 2); + memcpy(&(*buf_inp)[6], *buf_inp, 4); + (*buf_inp)[7] = number; + crc2 = neuronspi_spi_crc(&(*buf_inp)[6], 4 + (number * 2), crc1); + 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 new file mode 100644 index 0000000..e82f957 --- /dev/null +++ b/modules/unipi/src/unipi_sysfs.c @@ -0,0 +1,1098 @@ +/* + * UniPi Neuron tty serial driver - Copyright (C) 2018 UniPi Technologies + * Author: Tomas Knot + * + * Based on the SC16IS7xx driver by Jon Ringle , + * which was in turn based on max310x.c, by Alexander Shiyan + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +/************ + * Includes * + ************/ + +#include "unipi_sysfs.h" + +/************************ + * Static Functions * + ************************/ + +static ssize_t neuronspi_show_model(struct device *dev, struct device_attribute *attr, char *buf) +{ + ssize_t ret = 0; + if (neuronspi_model_id != -1) { + ret = scnprintf(buf, 255, "%s\n", NEURONSPI_MODELTABLE[neuronspi_model_id].model_name); + } + return ret; +} + +static ssize_t neuronspi_show_eeprom(struct device *dev, struct device_attribute *attr, char *buf) +{ + ssize_t ret = 0; + if (neuronspi_model_id != -1) { + ret = scnprintf(buf, 255, "%s\n", NEURONSPI_MODELTABLE[neuronspi_model_id].eeprom_name); + } + return ret; +} + +static ssize_t neuronspi_spi_show_serial(struct device *dev, struct device_attribute *attr, char *buf) +{ + ssize_t ret = 0; + u32 val[2] = {0, 0}; + struct neuronspi_driver_data *n_spi; + struct platform_device *plat = to_platform_device(dev); + n_spi = platform_get_drvdata(plat); + if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) { + regmap_read(n_spi->reg_map, n_spi->regstart_table->sys_serial_num, val); + regmap_read(n_spi->reg_map, n_spi->regstart_table->sys_serial_num + 1, &(val[1])); + ret = scnprintf(buf, 255, "%d\n", val[0]); + } + return ret; +} + +static ssize_t neuronspi_spi_show_hw_version(struct device *dev, struct device_attribute *attr, char *buf) +{ + ssize_t ret = 0; + u32 val = 0; + struct neuronspi_driver_data *n_spi; + struct platform_device *plat = to_platform_device(dev); + n_spi = platform_get_drvdata(plat); + if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) { + regmap_read(n_spi->reg_map, n_spi->regstart_table->sys_hw_ver, &val); + ret = scnprintf(buf, 255, "%x.%x\n", (val & 0xF0) >> 4, val & 0xF); + } + return ret; +} + +static ssize_t neuronspi_spi_show_hw_flash_version(struct device *dev, struct device_attribute *attr, char *buf) +{ + ssize_t ret = 0; + u32 val = 0; + struct neuronspi_driver_data *n_spi; + struct platform_device *plat = to_platform_device(dev); + n_spi = platform_get_drvdata(plat); + if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) { + regmap_read(n_spi->reg_map, n_spi->regstart_table->sys_hw_flash_ver, &val); + ret = scnprintf(buf, 255, "%x.%x\n", (val & 0xF0) >> 4, val & 0xF); + } + return ret; +} + +static ssize_t neuronspi_spi_show_fw_version(struct device *dev, struct device_attribute *attr, char *buf) +{ + ssize_t ret = 0; + u32 val = 0; + struct neuronspi_driver_data *n_spi; + struct platform_device *plat = to_platform_device(dev); + n_spi = platform_get_drvdata(plat); + if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) { + regmap_read(n_spi->reg_map, n_spi->regstart_table->sys_sw_ver, &val); + ret = scnprintf(buf, 255, "%x.%x%x\n", (val & 0xF00) >> 8, (val & 0xF0) >> 4, val & 0xF); + } + return ret; +} + +static ssize_t neuronspi_spi_show_uart_queue_length(struct device *dev, struct device_attribute *attr, char *buf) +{ + ssize_t ret = 0; + u32 val = 0; + struct neuronspi_driver_data *n_spi; + struct platform_device *plat = to_platform_device(dev); + n_spi = platform_get_drvdata(plat); + if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map && n_spi->regstart_table->uart_queue_reg) { + regmap_read(n_spi->reg_map, n_spi->regstart_table->uart_queue_reg, &val); + ret = scnprintf(buf, 255, "%d\n", val); + } + return ret; +} + +static ssize_t neuronspi_spi_show_uart_config(struct device *dev, struct device_attribute *attr, char *buf) +{ + ssize_t ret = 0; + u32 val = 0; + struct neuronspi_driver_data *n_spi; + struct platform_device *plat = to_platform_device(dev); + n_spi = platform_get_drvdata(plat); + if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map && n_spi->regstart_table->uart_conf_reg) { + regmap_read(n_spi->reg_map, n_spi->regstart_table->uart_conf_reg, &val); + ret = scnprintf(buf, 255, "%x\n", val); + } + return ret; +} + +static ssize_t neuronspi_spi_store_uart_config(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + ssize_t err = 0; + unsigned int val = 0; + struct neuronspi_driver_data *n_spi; + struct platform_device *plat = to_platform_device(dev); + n_spi = platform_get_drvdata(plat); + err = kstrtouint(buf, 0, &val); + if (err < 0) goto err_end; + if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map && n_spi->regstart_table->uart_conf_reg) { + regmap_write(n_spi->reg_map, n_spi->regstart_table->uart_conf_reg, val); + } +err_end: + return count; +} + +static ssize_t neuronspi_spi_show_watchdog_status(struct device *dev, struct device_attribute *attr, char *buf) +{ + ssize_t ret = 0; + u32 val = 0; + struct neuronspi_driver_data *n_spi; + struct platform_device *plat = to_platform_device(dev); + n_spi = platform_get_drvdata(plat); + if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) { + regmap_read(n_spi->reg_map, n_spi->regstart_table->wd_val_reg, &val); + ret = scnprintf(buf, 255, "%x\n", val); + } + return ret; +} + +static ssize_t neuronspi_spi_store_watchdog_status(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + ssize_t err = 0; + unsigned int val = 0; + struct neuronspi_driver_data *n_spi; + struct platform_device *plat = to_platform_device(dev); + n_spi = platform_get_drvdata(plat); + err = kstrtouint(buf, 0, &val); + if (err < 0) goto err_end; + if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) { + regmap_write(n_spi->reg_map, n_spi->regstart_table->wd_val_reg, val); + } +err_end: + return count; +} + +static ssize_t neuronspi_spi_show_watchdog_timeout(struct device *dev, struct device_attribute *attr, char *buf) +{ + ssize_t ret = 0; + u32 val = 0; + struct neuronspi_driver_data *n_spi; + struct platform_device *plat = to_platform_device(dev); + n_spi = platform_get_drvdata(plat); + if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) { + regmap_read(n_spi->reg_map, n_spi->regstart_table->wd_timeout_reg, &val); + ret = scnprintf(buf, 255, "%d\n", val); + } + return ret; +} + +static ssize_t neuronspi_spi_store_watchdog_timeout(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + ssize_t err = 0; + unsigned int val = 0; + struct neuronspi_driver_data *n_spi; + struct platform_device *plat = to_platform_device(dev); + n_spi = platform_get_drvdata(plat); + err = kstrtouint(buf, 0, &val); + if (err < 0) goto err_end; + if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) { + regmap_write(n_spi->reg_map, n_spi->regstart_table->wd_timeout_reg, val); + } +err_end: + return count; +} + +static ssize_t neuronspi_spi_gpio_show_pwm_presc(struct device *dev, struct device_attribute *attr, char *buf) +{ + ssize_t ret = 0; + u32 val = 0; + struct neuronspi_do_driver *n_do; + struct neuronspi_driver_data *n_spi; + struct platform_device *plat = to_platform_device(dev); + n_do = platform_get_drvdata(plat); + n_spi = spi_get_drvdata(n_do->spi); + if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) { + regmap_read(n_spi->reg_map, n_spi->regstart_table->do_pwm_ps_reg, &val); + ret = scnprintf(buf, 255, "%d\n", val); + } + return ret; +} + +static ssize_t neuronspi_spi_gpio_store_pwm_presc(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + ssize_t err = 0; + unsigned int val = 0; + struct neuronspi_do_driver *n_do; + struct neuronspi_driver_data *n_spi; + struct platform_device *plat = to_platform_device(dev); + n_do = platform_get_drvdata(plat); + n_spi = spi_get_drvdata(n_do->spi); + err = kstrtouint(buf, 0, &val); + if (err < 0) goto err_end; + if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) { + regmap_write(n_spi->reg_map, n_spi->regstart_table->do_pwm_ps_reg, val); + } +err_end: + return count; +} + +static ssize_t neuronspi_spi_gpio_show_pwm_freq(struct device *dev, struct device_attribute *attr, char *buf) +{ + ssize_t ret = 0; + u32 val = 0; + struct neuronspi_do_driver *n_do; + struct neuronspi_driver_data *n_spi; + struct platform_device *plat = to_platform_device(dev); + n_do = platform_get_drvdata(plat); + n_spi = spi_get_drvdata(n_do->spi); + if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) { + regmap_read(n_spi->reg_map, n_spi->regstart_table->do_pwm_c_reg, &val); + ret = scnprintf(buf, 255, "%d\n", val); + } + return ret; +} + +static ssize_t neuronspi_spi_gpio_store_pwm_freq(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + ssize_t err = 0; + unsigned int val = 0; + struct neuronspi_do_driver *n_do; + struct neuronspi_driver_data *n_spi; + struct platform_device *plat = to_platform_device(dev); + n_do = platform_get_drvdata(plat); + n_spi = spi_get_drvdata(n_do->spi); + err = kstrtouint(buf, 0, &val); + if (err < 0) goto err_end; + if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) { + regmap_write(n_spi->reg_map, n_spi->regstart_table->do_pwm_c_reg, val); + } +err_end: + return count; +} + +static ssize_t neuronspi_spi_gpio_show_pwm_cycle(struct device *dev, struct device_attribute *attr, char *buf) +{ + ssize_t ret = 0; + u32 val = 0; + struct neuronspi_do_driver *n_do; + struct neuronspi_driver_data *n_spi; + struct platform_device *plat = to_platform_device(dev); + n_do = platform_get_drvdata(plat); + n_spi = spi_get_drvdata(n_do->spi); + if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) { + regmap_read(n_spi->reg_map, n_spi->regstart_table->do_pwm_reg + n_do->do_index, &val); + ret = scnprintf(buf, 255, "%d\n", val); + } + return ret; +} + +static ssize_t neuronspi_spi_gpio_store_pwm_cycle(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + ssize_t err = 0; + unsigned int val = 0; + struct neuronspi_do_driver *n_do; + struct neuronspi_driver_data *n_spi; + struct platform_device *plat = to_platform_device(dev); + n_do = platform_get_drvdata(plat); + n_spi = spi_get_drvdata(n_do->spi); + err = kstrtouint(buf, 0, &val); + if (err < 0) goto err_end; + if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) { + regmap_write(n_spi->reg_map, n_spi->regstart_table->do_pwm_reg + n_do->do_index, val); + } +err_end: + return count; +} + +static ssize_t neuronspi_spi_gpio_di_show_counter(struct device *dev, struct device_attribute *attr, char *buf) +{ + ssize_t ret = 0; + u32 val = 0; + struct neuronspi_di_driver *n_di; + struct neuronspi_driver_data *n_spi; + struct platform_device *plat = to_platform_device(dev); + n_di = platform_get_drvdata(plat); + n_spi = spi_get_drvdata(n_di->spi); + if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) { + regmap_read(n_spi->reg_map, n_spi->regstart_table->di_counter_reg + (2 * n_di->di_index), &val); + ret = scnprintf(buf, 255, "%d\n", val); + } + return ret; +} + +static ssize_t neuronspi_spi_gpio_di_store_counter(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + ssize_t err = 0; + unsigned int val = 0; + struct neuronspi_di_driver *n_di; + struct neuronspi_driver_data *n_spi; + struct platform_device *plat = to_platform_device(dev); + n_di = platform_get_drvdata(plat); + n_spi = spi_get_drvdata(n_di->spi); + err = kstrtouint(buf, 0, &val); + if (err < 0) goto err_end; + if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) { + regmap_write(n_spi->reg_map, n_spi->regstart_table->di_counter_reg + (2 * n_di->di_index), val); + } +err_end: + return count; +} + +static ssize_t neuronspi_spi_gpio_di_show_debounce(struct device *dev, struct device_attribute *attr, char *buf) +{ + ssize_t ret = 0; + u32 val = 0; + struct neuronspi_di_driver *n_di; + struct neuronspi_driver_data *n_spi; + struct platform_device *plat = to_platform_device(dev); + n_di = platform_get_drvdata(plat); + n_spi = spi_get_drvdata(n_di->spi); + if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map && n_spi->features && n_spi->features->di_count > n_di->di_index) { + regmap_read(n_spi->reg_map, n_spi->regstart_table->di_deboun_reg + n_di->di_index, &val); + ret = scnprintf(buf, 255, "%d\n", val); + } + return ret; +} + +static ssize_t neuronspi_spi_gpio_di_store_debounce(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + ssize_t err = 0; + unsigned int val = 0; + struct neuronspi_di_driver *n_di; + struct neuronspi_driver_data *n_spi; + struct platform_device *plat = to_platform_device(dev); + n_di = platform_get_drvdata(plat); + n_spi = spi_get_drvdata(n_di->spi); + err = kstrtouint(buf, 0, &val); + if (err < 0) goto err_end; + if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map && n_spi->features && n_spi->features->di_count > n_di->di_index) { + regmap_write(n_spi->reg_map, n_spi->regstart_table->di_deboun_reg + n_di->di_index, val); + } +err_end: + return count; +} + +static ssize_t neuronspi_spi_gpio_di_show_value(struct device *dev, struct device_attribute *attr, char *buf) +{ + ssize_t ret = 0; + int val; + struct neuronspi_di_driver *n_di; + struct neuronspi_driver_data *n_spi; + struct platform_device *plat = to_platform_device(dev); + n_di = platform_get_drvdata(plat); + n_spi = spi_get_drvdata(n_di->spi); + if (n_spi && n_spi->combination_id != -1 && n_spi->features && n_spi->features->di_count > n_di->di_index) { + regmap_read(n_spi->reg_map, n_spi->regstart_table->di_val_reg + (n_di->di_index / 16), &val); + val &= 0x1 << (n_di->di_index % 15); + val = val >> (n_di->di_index % 15); + ret = scnprintf(buf, 255, "%d\n", val); + } + return ret; +} + +static ssize_t neuronspi_spi_gpio_do_show_value(struct device *dev, struct device_attribute *attr, char *buf) +{ + ssize_t ret = 0; + int val; + struct neuronspi_do_driver *n_do; + struct neuronspi_driver_data *n_spi; + struct platform_device *plat = to_platform_device(dev); + n_do = platform_get_drvdata(plat); + n_spi = spi_get_drvdata(n_do->spi); + if (n_spi && n_spi->combination_id != -1 && n_spi->features && n_spi->features->do_count > n_do->do_index) { + regmap_read(n_spi->reg_map, n_spi->regstart_table->do_val_reg + (n_do->do_index / 16), &val); + val &= 0x1 << (n_do->do_index % 15); + val = val >> (n_do->do_index % 15); + ret = scnprintf(buf, 255, "%d\n", val); + } + return ret; +} + +static ssize_t neuronspi_spi_gpio_do_store_value(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + ssize_t err = 0; + int inp = 0; + unsigned int val; + struct neuronspi_do_driver *n_do; + struct neuronspi_driver_data *n_spi; + struct platform_device *plat = to_platform_device(dev); + n_do = platform_get_drvdata(plat); + n_spi = spi_get_drvdata(n_do->spi); + err = kstrtoint(buf, 0, &inp); + if (err < 0) goto err_end; + if (inp > 1 || inp < 0) { + goto err_end; + } + if (n_spi && n_spi->combination_id != -1 && n_spi->features && n_spi->features->do_count > n_do->do_index) { + regmap_read(n_spi->reg_map, n_spi->regstart_table->do_val_reg + (n_do->do_index / 16), &val); + val &= ~(0x1 << (n_do->do_index % 15)); + val |= inp << (n_do->do_index % 15); + regmap_write(n_spi->reg_map, n_spi->regstart_table->do_val_reg + (n_do->do_index / 16), val); + } +err_end: + return count; +} + +static ssize_t neuronspi_spi_gpio_ro_show_value(struct device *dev, struct device_attribute *attr, char *buf) +{ + ssize_t ret = 0; + int val; + struct neuronspi_ro_driver *n_ro; + struct neuronspi_driver_data *n_spi; + struct platform_device *plat = to_platform_device(dev); + n_ro = platform_get_drvdata(plat); + n_spi = spi_get_drvdata(n_ro->spi); + if (n_spi && n_spi->combination_id != -1 && n_spi->features && n_spi->features->ro_count > n_ro->ro_index) { + regmap_read(n_spi->reg_map, n_spi->regstart_table->ro_val_reg + (n_ro->ro_index / 16), &val); + val &= 0x1 << (n_ro->ro_index % 15); + val = val >> (n_ro->ro_index % 15); + ret = scnprintf(buf, 255, "%d\n", val); + } + return ret; +} + +static ssize_t neuronspi_spi_gpio_ro_store_value(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + ssize_t err = 0; + int inp = 0; + unsigned int val; + struct neuronspi_ro_driver *n_ro; + struct neuronspi_driver_data *n_spi; + struct platform_device *plat = to_platform_device(dev); + n_ro = platform_get_drvdata(plat); + n_spi = spi_get_drvdata(n_ro->spi); + err = kstrtoint(buf, 0, &inp); + if (err < 0) goto err_end; + if (inp > 1 || inp < 0) { + goto err_end; + } + if (n_spi && n_spi->combination_id != -1 && n_spi->features && n_spi->features->ro_count > n_ro->ro_index) { + regmap_read(n_spi->reg_map, n_spi->regstart_table->ro_val_reg + (n_ro->ro_index / 16), &val); + val &= ~(0x1 << (n_ro->ro_index % 15)); + val |= inp << (n_ro->ro_index % 15); + regmap_write(n_spi->reg_map, n_spi->regstart_table->ro_val_reg + (n_ro->ro_index / 16), val); + } +err_end: + return count; +} + + +static ssize_t neuronspi_spi_gpio_show_ds_enable(struct device *dev, struct device_attribute *attr, char *buf) +{ + ssize_t ret = 0; + int val; + struct neuronspi_di_driver *n_di; + struct neuronspi_driver_data *n_spi; + struct platform_device *plat = to_platform_device(dev); + n_di = platform_get_drvdata(plat); + n_spi = spi_get_drvdata(n_di->spi); + if (n_spi && n_spi->combination_id != -1 && n_spi->features && n_spi->features->ds_count) { + regmap_read(n_spi->reg_map, n_spi->regstart_table->di_direct_reg + (n_di->di_index / 16), &val); + val &= 0x1 << (n_di->di_index % 15); + val = val >> (n_di->di_index % 15); + ret = scnprintf(buf, 255, "%d\n", val); + } + return ret; +} + +static ssize_t neuronspi_spi_gpio_show_ds_toggle(struct device *dev, struct device_attribute *attr, char *buf) +{ + ssize_t ret = 0; + int val; + struct neuronspi_di_driver *n_di; + struct neuronspi_driver_data *n_spi; + struct platform_device *plat = to_platform_device(dev); + n_di = platform_get_drvdata(plat); + n_spi = spi_get_drvdata(n_di->spi); + if (n_spi && n_spi->combination_id != -1 && n_spi->features && n_spi->features->ds_count) { + regmap_read(n_spi->reg_map, n_spi->regstart_table->di_toggle_reg + (n_di->di_index / 16), &val); + val &= 0x1 << (n_di->di_index % 15); + val = val >> (n_di->di_index % 15); + ret = scnprintf(buf, 255, "%d\n", val); + } + return ret; +} + +static ssize_t neuronspi_spi_gpio_show_ds_polarity(struct device *dev, struct device_attribute *attr, char *buf) +{ + ssize_t ret = 0; + int val; + struct neuronspi_di_driver *n_di; + struct neuronspi_driver_data *n_spi; + struct platform_device *plat = to_platform_device(dev); + n_di = platform_get_drvdata(plat); + n_spi = spi_get_drvdata(n_di->spi); + if (n_spi && n_spi->combination_id != -1 && n_spi->features && n_spi->features->ds_count) { + regmap_read(n_spi->reg_map, n_spi->regstart_table->di_polar_reg + (n_di->di_index / 16), &val); + val &= 0x1 << (n_di->di_index % 15); + val = val >> (n_di->di_index % 15); + ret = scnprintf(buf, 255, "%d\n", val); + } + return ret; +} + +static ssize_t neuronspi_spi_gpio_store_ds_enable(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + ssize_t err = 0; + int inp = 0; + unsigned int val; + struct neuronspi_di_driver *n_di; + struct neuronspi_driver_data *n_spi; + struct platform_device *plat = to_platform_device(dev); + n_di = platform_get_drvdata(plat); + n_spi = spi_get_drvdata(n_di->spi); + err = kstrtoint(buf, 0, &inp); + if (err < 0) goto err_end; + if (inp > 1 || inp < 0) { + goto err_end; + } + if (n_spi && n_spi->combination_id != -1 && n_spi->features && n_spi->features->ds_count) { + regmap_read(n_spi->reg_map, n_spi->regstart_table->di_direct_reg + (n_di->di_index / 16), &val); + val &= ~(0x1 << (n_di->di_index % 15)); + val |= inp << (n_di->di_index % 15); + regmap_write(n_spi->reg_map, n_spi->regstart_table->di_direct_reg + (n_di->di_index / 16), val); + } +err_end: + return count; +} + +static ssize_t neuronspi_spi_gpio_store_ds_toggle(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + ssize_t err = 0; + int inp = 0; + unsigned int val; + struct neuronspi_di_driver *n_di; + struct neuronspi_driver_data *n_spi; + struct platform_device *plat = to_platform_device(dev); + n_di = platform_get_drvdata(plat); + n_spi = spi_get_drvdata(n_di->spi); + err = kstrtoint(buf, 0, &inp); + if (err < 0) goto err_end; + if (inp > 1 || inp < 0) { + goto err_end; + } + if (n_spi && n_spi->combination_id != -1 && n_spi->features && n_spi->features->ds_count) { + regmap_read(n_spi->reg_map, n_spi->regstart_table->di_toggle_reg + (n_di->di_index / 16), &val); + val &= ~(0x1 << (n_di->di_index % 15)); + val |= inp << (n_di->di_index % 15); + regmap_write(n_spi->reg_map, n_spi->regstart_table->di_toggle_reg + (n_di->di_index / 16), val); + } +err_end: + return count; +} + +static ssize_t neuronspi_spi_gpio_store_ds_polarity(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + ssize_t err = 0; + int inp = 0; + unsigned int val; + struct neuronspi_di_driver *n_di; + struct neuronspi_driver_data *n_spi; + struct platform_device *plat = to_platform_device(dev); + n_di = platform_get_drvdata(plat); + n_spi = spi_get_drvdata(n_di->spi); + err = kstrtoint(buf, 0, &inp); + if (err < 0) goto err_end; + if (inp > 1 || inp < 0) { + goto err_end; + } + if (n_spi && n_spi->combination_id != -1 && n_spi->features && n_spi->features->ds_count) { + regmap_read(n_spi->reg_map, n_spi->regstart_table->di_polar_reg + (n_di->di_index / 16), &val); + val &= ~(0x1 << (n_di->di_index % 15)); + val |= inp << (n_di->di_index % 15); + regmap_write(n_spi->reg_map, n_spi->regstart_table->di_polar_reg + (n_di->di_index / 16), val); + } +err_end: + return count; +} + +static ssize_t neuronspi_show_regmap(struct device *dev, struct device_attribute *attr, char *buf) +{ + ssize_t ret = 0; + u32 val = 0; + struct neuronspi_driver_data *n_spi; + struct platform_device *plat = to_platform_device(dev); + n_spi = platform_get_drvdata(plat); + if (n_spi && n_spi->reg_map) { + spin_lock(&n_spi->sysfs_regmap_lock); + regmap_read(n_spi->reg_map, n_spi->sysfs_regmap_target, &val); + ret = scnprintf(buf, 255, "%x\n", val); + spin_unlock(&n_spi->sysfs_regmap_lock); + } + return ret; +} + +static ssize_t neuronspi_store_regmap(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + ssize_t err = 0; + unsigned int val = 0; + struct neuronspi_driver_data *n_spi; + struct platform_device *plat = to_platform_device(dev); + n_spi = platform_get_drvdata(plat); + err = kstrtouint(buf, 0, &val); + if (err < 0) goto err_end; + if (n_spi && n_spi->reg_map && val < 65536) { + spin_lock(&n_spi->sysfs_regmap_lock); + n_spi->sysfs_regmap_target = val; + spin_unlock(&n_spi->sysfs_regmap_lock); + } +err_end: + return count; +} + +static ssize_t neuronspi_spi_show_board(struct device *dev, struct device_attribute *attr, char *buf) +{ + ssize_t ret = 0; + struct neuronspi_driver_data *n_spi; + struct platform_device *plat = to_platform_device(dev); + n_spi = platform_get_drvdata(plat); + if (n_spi->combination_id != -1 && n_spi->combination_id < NEURONSPI_BOARDTABLE_LEN) { + ret = scnprintf(buf, 255, "%s\n", NEURONSPI_BOARDTABLE[n_spi->combination_id].definition->combination_name); + } + return ret; +} + +static ssize_t neuronspi_spi_show_lboard_id(struct device *dev, struct device_attribute *attr, char *buf) +{ + ssize_t ret = 0; + struct neuronspi_driver_data *n_spi; + struct platform_device *plat = to_platform_device(dev); + n_spi = platform_get_drvdata(plat); + if (n_spi->combination_id != -1 && n_spi->combination_id < NEURONSPI_BOARDTABLE_LEN) { + ret = scnprintf(buf, 255, "%d\n", NEURONSPI_BOARDTABLE[n_spi->combination_id].definition->lower_board_id); + } + return ret; +} + +static ssize_t neuronspi_spi_show_uboard_id(struct device *dev, struct device_attribute *attr, char *buf) +{ + ssize_t ret = 0; + struct neuronspi_driver_data *n_spi; + struct platform_device *plat = to_platform_device(dev); + n_spi = platform_get_drvdata(plat); + if (n_spi->combination_id != -1 && n_spi->combination_id < NEURONSPI_BOARDTABLE_LEN) { + ret = scnprintf(buf, 255, "%d\n", NEURONSPI_BOARDTABLE[n_spi->combination_id].definition->upper_board_id); + } + return ret; +} + +static ssize_t neuronspi_spi_gpio_show_do_prefix(struct device *dev, struct device_attribute *attr, char *buf) +{ + ssize_t ret = 0; + struct neuronspi_do_driver *n_do; + struct neuronspi_driver_data *n_spi; + struct platform_device *plat = to_platform_device(dev); + n_do = platform_get_drvdata(plat); + n_spi = spi_get_drvdata(n_do->spi); + if (n_spi->features && n_spi->features->do_count > 0 && n_spi->do_driver) { + ret = scnprintf(buf, 255, "%s_%d\n", n_spi->do_driver[n_do->do_index]->gpio_c.label, n_spi->neuron_index + 1); + } + return ret; +} + +static ssize_t neuronspi_spi_gpio_show_di_prefix(struct device *dev, struct device_attribute *attr, char *buf) +{ + ssize_t ret = 0; + struct neuronspi_di_driver *n_di; + struct neuronspi_driver_data *n_spi; + struct platform_device *plat = to_platform_device(dev); + n_di = platform_get_drvdata(plat); + n_spi = spi_get_drvdata(n_di->spi); + if (n_spi->features && n_spi->features->di_count > 0 && n_spi->di_driver) { + ret = scnprintf(buf, 255, "%s_%d\n", n_spi->di_driver[n_di->di_index]->gpio_c.label, n_spi->neuron_index + 1); + } + return ret; +} + +static ssize_t neuronspi_spi_gpio_show_ro_prefix(struct device *dev, struct device_attribute *attr, char *buf) +{ + ssize_t ret = 0; + struct neuronspi_ro_driver *n_ro; + struct neuronspi_driver_data *n_spi; + struct platform_device *plat = to_platform_device(dev); + n_ro = platform_get_drvdata(plat); + n_spi = spi_get_drvdata(n_ro->spi); + if (n_spi->features && n_spi->features->ro_count > 0 && n_spi->ro_driver) { + ret = scnprintf(buf, 255, "%s_%d\n", n_spi->ro_driver[n_ro->ro_index]->gpio_c.label, n_spi->neuron_index + 1); + } + return ret; +} + +static ssize_t neuronspi_spi_gpio_show_do_base(struct device *dev, struct device_attribute *attr, char *buf) +{ + ssize_t ret = 0; + struct neuronspi_do_driver *n_do; + struct neuronspi_driver_data *n_spi; + struct platform_device *plat = to_platform_device(dev); + n_do = platform_get_drvdata(plat); + n_spi = spi_get_drvdata(n_do->spi); + if (n_spi->features && n_spi->features->do_count > 0 && n_spi->do_driver) { + ret = scnprintf(buf, 255, "%d\n", n_spi->do_driver[n_do->do_index]->gpio_c.base); + } + return ret; +} + +static ssize_t neuronspi_spi_gpio_show_di_base(struct device *dev, struct device_attribute *attr, char *buf) +{ + ssize_t ret = 0; + struct neuronspi_di_driver *n_di; + struct neuronspi_driver_data *n_spi; + struct platform_device *plat = to_platform_device(dev); + n_di = platform_get_drvdata(plat); + n_spi = spi_get_drvdata(n_di->spi); + if (n_spi->features && n_spi->features->di_count > 0 && n_spi->di_driver) { + ret = scnprintf(buf, 255, "%d\n", n_spi->di_driver[n_di->di_index]->gpio_c.base); + } + return ret; +} + +static ssize_t neuronspi_spi_gpio_show_ro_base(struct device *dev, struct device_attribute *attr, char *buf) +{ + ssize_t ret = 0; + struct neuronspi_ro_driver *n_ro; + struct neuronspi_driver_data *n_spi; + struct platform_device *plat = to_platform_device(dev); + n_ro = platform_get_drvdata(plat); + n_spi = spi_get_drvdata(n_ro->spi); + if (n_spi->features && n_spi->features->ro_count > 0 && n_spi->ro_driver) { + ret = scnprintf(buf, 255, "%d\n", n_spi->ro_driver[n_ro->ro_index]->gpio_c.base); + } + return ret; +} + +static ssize_t neuronspi_spi_gpio_show_do_count(struct device *dev, struct device_attribute *attr, char *buf) +{ + ssize_t ret = 0; + struct neuronspi_do_driver *n_do; + struct neuronspi_driver_data *n_spi; + struct platform_device *plat = to_platform_device(dev); + n_do = platform_get_drvdata(plat); + n_spi = spi_get_drvdata(n_do->spi); + if (n_spi->features && n_spi->features->do_count > 0 && n_spi->do_driver) { + ret = scnprintf(buf, 255, "%d\n", n_spi->do_driver[n_do->do_index]->gpio_c.ngpio); + } + return ret; +} + +static ssize_t neuronspi_spi_gpio_show_di_count(struct device *dev, struct device_attribute *attr, char *buf) +{ + ssize_t ret = 0; + struct neuronspi_di_driver *n_di; + struct neuronspi_driver_data *n_spi; + struct platform_device *plat = to_platform_device(dev); + n_di = platform_get_drvdata(plat); + n_spi = spi_get_drvdata(n_di->spi); + if (n_spi->features && n_spi->features->di_count > 0 && n_spi->di_driver) { + ret = scnprintf(buf, 255, "%d\n", n_spi->di_driver[n_di->di_index]->gpio_c.ngpio); + } + return ret; +} + +static ssize_t neuronspi_spi_gpio_show_ro_count(struct device *dev, struct device_attribute *attr, char *buf) +{ + ssize_t ret = 0; + struct neuronspi_ro_driver *n_ro; + struct neuronspi_driver_data *n_spi; + struct platform_device *plat = to_platform_device(dev); + n_ro = platform_get_drvdata(plat); + n_spi = spi_get_drvdata(n_ro->spi); + if (n_spi->features && n_spi->features->ro_count > 0 && n_spi->ro_driver) { + ret = scnprintf(buf, 255, "%d\n", n_spi->ro_driver[n_ro->ro_index]->gpio_c.ngpio); + } + return ret; +} + + +static ssize_t neuronspi_iio_show_primary_ai_mode(struct device *dev, struct device_attribute *attr, char *buf) +{ + int ret = 0; + unsigned int val = 0; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct neuronspi_stm_ai_data *ai_data = iio_priv(indio_dev); + struct spi_device *spi = ai_data->parent; + struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi); + regmap_read(n_spi->reg_map, n_spi->regstart_table->stm_ai_mode_reg, &val); + ret = scnprintf(buf, 255, "%d\n", val); + return ret; +} + +static ssize_t neuronspi_iio_store_primary_ai_mode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + ssize_t err = 0; + unsigned int val = 0; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct neuronspi_stm_ai_data *ai_data = iio_priv(indio_dev); + struct spi_device *spi = ai_data->parent; + struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi); + err = kstrtouint(buf, 0, &val); + if (err < 0) goto err_end; + if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) { + regmap_write(n_spi->reg_map, n_spi->regstart_table->stm_ai_mode_reg, val); + } +err_end: + return count; +} + +static ssize_t neuronspi_iio_show_primary_ao_mode(struct device *dev, struct device_attribute *attr, char *buf) +{ + int ret = 0; + unsigned int val = 0; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct neuronspi_stm_ao_data *ao_data = iio_priv(indio_dev); + struct spi_device *spi = ao_data->parent; + struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi); + regmap_read(n_spi->reg_map, n_spi->regstart_table->stm_ao_mode_reg, &val); + ret = scnprintf(buf, 255, "%d\n", val); + return ret; +} + +static ssize_t neuronspi_iio_store_primary_ao_mode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + ssize_t err = 0; + unsigned int val = 0; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct neuronspi_stm_ao_data *ao_data = iio_priv(indio_dev); + struct spi_device *spi = ao_data->parent; + struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi); + err = kstrtouint(buf, 0, &val); + if (err < 0) goto err_end; + if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) { + regmap_write(n_spi->reg_map, n_spi->regstart_table->stm_ao_mode_reg, val); + } +err_end: + return count; +} + +static ssize_t neuronspi_iio_show_secondary_ai_mode(struct device *dev, struct device_attribute *attr, char *buf) +{ + int ret = 0; + unsigned int val = 0; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct neuronspi_sec_ai_data *ai_data = iio_priv(indio_dev); + struct spi_device *spi = ai_data->parent; + struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi); + regmap_read(n_spi->reg_map, n_spi->regstart_table->sec_ai_mode_reg + ai_data->index, &val); + ret = scnprintf(buf, 255, "%d\n", val); + return ret; +} +static ssize_t neuronspi_iio_store_secondary_ai_mode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + ssize_t err = 0; + unsigned int val = 0; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct neuronspi_sec_ai_data *ai_data = iio_priv(indio_dev); + struct spi_device *spi = ai_data->parent; + struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi); + err = kstrtouint(buf, 0, &val); + if (err < 0) goto err_end; + if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) { + regmap_write(n_spi->reg_map, n_spi->regstart_table->sec_ai_mode_reg + ai_data->index, val); + } +err_end: + return count; +} +static ssize_t neuronspi_iio_show_secondary_ao_mode(struct device *dev, struct device_attribute *attr, char *buf) +{ + int ret = 0; + unsigned int val = 0; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct neuronspi_sec_ao_data *ao_data = iio_priv(indio_dev); + struct spi_device *spi = ao_data->parent; + struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi); + regmap_read(n_spi->reg_map, n_spi->regstart_table->sec_ao_mode_reg + ao_data->index, &val); + ret = scnprintf(buf, 255, "%d\n", val); + return ret; +} +static ssize_t neuronspi_iio_store_secondary_ao_mode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + ssize_t err = 0; + unsigned int val = 0; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct neuronspi_sec_ao_data *ao_data = iio_priv(indio_dev); + struct spi_device *spi = ao_data->parent; + struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi); + err = kstrtouint(buf, 0, &val); + if (err < 0) goto err_end; + if (n_spi && n_spi->combination_id != -1 && n_spi->reg_map) { + regmap_write(n_spi->reg_map, n_spi->regstart_table->sec_ao_mode_reg + ao_data->index, val); + } +err_end: + return count; +} + +/********************************** + * Function Structure Definitions * + **********************************/ + +static DEVICE_ATTR(model_name, 0440, neuronspi_show_model, NULL); +static DEVICE_ATTR(sys_eeprom_name, 0440, neuronspi_show_eeprom, NULL); +static DEVICE_ATTR(register_read, 0660, neuronspi_show_regmap, neuronspi_store_regmap); +static DEVICE_ATTR(sys_board_serial, 0440, neuronspi_spi_show_serial, NULL); +static DEVICE_ATTR(sys_board_name, 0440, neuronspi_spi_show_board, NULL); +static DEVICE_ATTR(sys_primary_major_id, 0440, neuronspi_spi_show_lboard_id, NULL); +static DEVICE_ATTR(sys_secondary_major_id, 0440, neuronspi_spi_show_uboard_id, NULL); +static DEVICE_ATTR(sys_primary_minor_id, 0440, neuronspi_spi_show_hw_version, NULL); +static DEVICE_ATTR(sys_secondary_minor_id, 0440, neuronspi_spi_show_hw_flash_version, NULL); +static DEVICE_ATTR(firmware_version, 0440, neuronspi_spi_show_fw_version, NULL); +static DEVICE_ATTR(watchdog_status, 0660, neuronspi_spi_show_watchdog_status, neuronspi_spi_store_watchdog_status); +static DEVICE_ATTR(watchdog_timeout, 0660, neuronspi_spi_show_watchdog_timeout, neuronspi_spi_store_watchdog_timeout); +static DEVICE_ATTR(sys_gpio_do_count, 0440, neuronspi_spi_gpio_show_do_count, NULL); +static DEVICE_ATTR(sys_gpio_do_prefix, 0440, neuronspi_spi_gpio_show_do_prefix, NULL); +static DEVICE_ATTR(sys_gpio_do_base, 0440, neuronspi_spi_gpio_show_do_base, NULL); +static DEVICE_ATTR(sys_gpio_di_count, 0440, neuronspi_spi_gpio_show_di_count, NULL); +static DEVICE_ATTR(sys_gpio_di_prefix, 0440, neuronspi_spi_gpio_show_di_prefix, NULL); +static DEVICE_ATTR(ro_value, 0660, neuronspi_spi_gpio_ro_show_value, neuronspi_spi_gpio_ro_store_value); +static DEVICE_ATTR(do_value, 0660, neuronspi_spi_gpio_do_show_value, neuronspi_spi_gpio_do_store_value); +static DEVICE_ATTR(counter, 0660, neuronspi_spi_gpio_di_show_counter, neuronspi_spi_gpio_di_store_counter); +static DEVICE_ATTR(debounce, 0660, neuronspi_spi_gpio_di_show_debounce, neuronspi_spi_gpio_di_store_debounce); +static DEVICE_ATTR(di_value, 0440, neuronspi_spi_gpio_di_show_value, NULL); +static DEVICE_ATTR(direct_switch_enable, 0660, neuronspi_spi_gpio_show_ds_enable, neuronspi_spi_gpio_store_ds_enable); +static DEVICE_ATTR(direct_switch_toggle, 0660, neuronspi_spi_gpio_show_ds_toggle, neuronspi_spi_gpio_store_ds_toggle); +static DEVICE_ATTR(direct_switch_polarity, 0660, neuronspi_spi_gpio_show_ds_polarity, neuronspi_spi_gpio_store_ds_polarity); +static DEVICE_ATTR(pwm_frequency_cycle, 0660, neuronspi_spi_gpio_show_pwm_freq, neuronspi_spi_gpio_store_pwm_freq); +static DEVICE_ATTR(pwm_prescale, 0660, neuronspi_spi_gpio_show_pwm_presc, neuronspi_spi_gpio_store_pwm_presc); +static DEVICE_ATTR(pwm_duty_cycle, 0660, neuronspi_spi_gpio_show_pwm_cycle, neuronspi_spi_gpio_store_pwm_cycle); +static DEVICE_ATTR(uart_queue_length, 0440, neuronspi_spi_show_uart_queue_length, NULL); +static DEVICE_ATTR(uart_config, 0660, neuronspi_spi_show_uart_config, neuronspi_spi_store_uart_config); +static DEVICE_ATTR(sys_gpio_di_base, 0440, neuronspi_spi_gpio_show_di_base, NULL); +static DEVICE_ATTR(sys_gpio_ro_count, 0440, neuronspi_spi_gpio_show_ro_count, NULL); +static DEVICE_ATTR(sys_gpio_ro_prefix, 0440, neuronspi_spi_gpio_show_ro_prefix, NULL); +static DEVICE_ATTR(sys_gpio_ro_base, 0440, neuronspi_spi_gpio_show_ro_base, NULL); +static DEVICE_ATTR(mode_ai_type_a, 0660, neuronspi_iio_show_primary_ai_mode, neuronspi_iio_store_primary_ai_mode); +static DEVICE_ATTR(mode_ao_type_a, 0660, neuronspi_iio_show_primary_ao_mode, neuronspi_iio_store_primary_ao_mode); +static DEVICE_ATTR(mode_ai_type_b, 0660, neuronspi_iio_show_secondary_ai_mode, neuronspi_iio_store_secondary_ai_mode); +static DEVICE_ATTR(mode_ao_type_b, 0660, neuronspi_iio_show_secondary_ao_mode, neuronspi_iio_store_secondary_ao_mode); + +static struct attribute *neuron_plc_attrs[] = { + &dev_attr_model_name.attr, + &dev_attr_sys_eeprom_name.attr, + NULL, +}; + +static struct attribute *neuron_board_attrs[] = { + &dev_attr_sys_board_name.attr, + &dev_attr_sys_primary_major_id.attr, + &dev_attr_sys_secondary_major_id.attr, + &dev_attr_sys_primary_minor_id.attr, + &dev_attr_sys_secondary_minor_id.attr, + &dev_attr_firmware_version.attr, + &dev_attr_watchdog_status.attr, + &dev_attr_watchdog_timeout.attr, + &dev_attr_sys_board_serial.attr, + &dev_attr_uart_queue_length.attr, + &dev_attr_uart_config.attr, + &dev_attr_register_read.attr, + NULL, +}; + +static struct attribute *neuron_gpio_di_attrs[] = { + &dev_attr_sys_gpio_di_count.attr, + &dev_attr_sys_gpio_di_prefix.attr, + &dev_attr_sys_gpio_di_base.attr, + &dev_attr_direct_switch_enable.attr, + &dev_attr_direct_switch_toggle.attr, + &dev_attr_direct_switch_polarity.attr, + &dev_attr_di_value.attr, + &dev_attr_counter.attr, + &dev_attr_debounce.attr, + NULL, +}; + +static struct attribute *neuron_gpio_do_attrs[] = { + &dev_attr_sys_gpio_do_count.attr, + &dev_attr_sys_gpio_do_prefix.attr, + &dev_attr_sys_gpio_do_base.attr, + &dev_attr_pwm_frequency_cycle.attr, + &dev_attr_pwm_prescale.attr, + &dev_attr_pwm_duty_cycle.attr, + &dev_attr_do_value.attr, + NULL, +}; + +static struct attribute *neuron_gpio_ro_attrs[] = { + &dev_attr_sys_gpio_ro_count.attr, + &dev_attr_sys_gpio_ro_prefix.attr, + &dev_attr_sys_gpio_ro_base.attr, + &dev_attr_ro_value.attr, + NULL, +}; + +static struct attribute *neuron_stm_ai_attrs[] = { + &dev_attr_mode_ai_type_a.attr, + NULL, +}; + +static struct attribute *neuron_stm_ao_attrs[] = { + &dev_attr_mode_ao_type_a.attr, + NULL, +}; + +static struct attribute *neuron_sec_ai_attrs[] = { + &dev_attr_mode_ai_type_b.attr, + NULL, +}; + +static struct attribute *neuron_sec_ao_attrs[] = { + &dev_attr_mode_ao_type_b.attr, + NULL, +}; + +static struct attribute_group neuron_plc_attr_group = { + .attrs = neuron_plc_attrs, +}; + +static struct attribute_group neuron_board_attr_group = { + .attrs = neuron_board_attrs, +}; + +static struct attribute_group neuron_gpio_di_attr_group = { + .attrs = neuron_gpio_di_attrs, +}; + +static struct attribute_group neuron_gpio_do_attr_group = { + .attrs = neuron_gpio_do_attrs, +}; + +static struct attribute_group neuron_gpio_ro_attr_group = { + .attrs = neuron_gpio_ro_attrs, +}; + +const struct attribute_group neuron_stm_ai_group = { + .attrs = neuron_stm_ai_attrs, +}; + +const struct attribute_group neuron_stm_ao_group = { + .attrs = neuron_stm_ao_attrs, +}; + +const struct attribute_group neuron_sec_ai_group = { + .attrs = neuron_sec_ai_attrs, +}; + +const struct attribute_group neuron_sec_ao_group = { + .attrs = neuron_sec_ao_attrs, +}; + +const struct attribute_group *neuron_plc_attr_groups[] = { + &neuron_plc_attr_group, + NULL, +}; + +const struct attribute_group *neuron_board_attr_groups[] = { + &neuron_board_attr_group, + NULL, +}; + +const struct attribute_group *neuron_gpio_di_attr_groups[] = { + &neuron_gpio_di_attr_group, + NULL, +}; + +const struct attribute_group *neuron_gpio_do_attr_groups[] = { + &neuron_gpio_do_attr_group, + NULL, +}; + +const struct attribute_group *neuron_gpio_ro_attr_groups[] = { + &neuron_gpio_ro_attr_group, + NULL, +}; diff --git a/modules/unipi/src/unipi_sysfs.h b/modules/unipi/src/unipi_sysfs.h new file mode 100644 index 0000000..72ae365 --- /dev/null +++ b/modules/unipi/src/unipi_sysfs.h @@ -0,0 +1,60 @@ +/* + * UniPi Neuron tty serial driver - Copyright (C) 2018 UniPi Technologies + * Author: Tomas Knot + * + * Based on the SC16IS7xx driver by Jon Ringle , + * which was in turn based on max310x.c, by Alexander Shiyan + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +#ifndef MODULES_NEURON_SPI_SRC_UNIPI_SYSFS_H_ +#define MODULES_NEURON_SPI_SRC_UNIPI_SYSFS_H_ + +/************ + * Includes * + ************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "unipi_common.h" +#include "unipi_platform.h" + +extern const struct attribute_group neuron_stm_ai_group; +extern const struct attribute_group neuron_stm_ao_group; +extern const struct attribute_group neuron_sec_ai_group; +extern const struct attribute_group neuron_sec_ao_group; + +extern const struct attribute_group *neuron_plc_attr_groups[]; +extern const struct attribute_group *neuron_board_attr_groups[]; +extern const struct attribute_group *neuron_gpio_di_attr_groups[]; +extern const struct attribute_group *neuron_gpio_do_attr_groups[]; +extern const struct attribute_group *neuron_gpio_ro_attr_groups[]; + +#endif /* MODULES_NEURON_SPI_SRC_UNIPI_SYSFS_H_ */ diff --git a/modules/unipi/src/unipi_uart.c b/modules/unipi/src/unipi_uart.c new file mode 100644 index 0000000..ed549f0 --- /dev/null +++ b/modules/unipi/src/unipi_uart.c @@ -0,0 +1,565 @@ +/* + * UniPi Neuron tty serial driver - Copyright (C) 2018 UniPi Technologies + * Author: Tomas Knot + * + * Based on the SC16IS7xx driver by Jon Ringle , + * which was in turn based on max310x.c, by Alexander Shiyan + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +/************ + * Includes * + ************/ + +#include "unipi_uart.h" +#include "unipi_spi.h" + +/******************** + * Data Definitions * + ********************/ + +struct neuronspi_uart_data* neuronspi_uart_glob_data; +unsigned long neuronspi_lines; +struct uart_driver* neuronspi_uart; + +/************************ + * Non-static Functions * + ************************/ + +void neuronspi_uart_tx_proc(struct kthread_work *ws) +{ + struct neuronspi_port *port = to_neuronspi_port(ws, tx_work); + + if ((port->port.rs485.flags & SER_RS485_ENABLED) && + (port->port.rs485.delay_rts_before_send > 0)) { + msleep(port->port.rs485.delay_rts_before_send); + } + + neuronspi_uart_handle_tx(port); +} + +u32 neuronspi_uart_tx_empty(struct uart_port *port) +{ +#if NEURONSPI_DETAILED_DEBUG > 0 + printk(KERN_INFO "NEURONSPI: UART TX Empty\n"); +#endif + return TIOCSER_TEMT; +} + +u32 neuronspi_uart_get_mctrl(struct uart_port *port) +{ +#if NEURONSPI_DETAILED_DEBUG > 0 + printk(KERN_DEBUG "NEURONSPI: UART MCTRL Get\n"); +#endif + 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; + 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); + switch (ioctl_code) { + case TIOCSETD: { + printk(KERN_INFO "NEURONSPI: IOCTL TIOCSETD (processed via set_termios)\n"); + return 1; + } + case 0x5480: { + printk(KERN_INFO "NEURONSPI: IOCTL 0x5480\n"); + write_length = neuronspi_spi_compose_single_register_write(NEURONSPI_UART_TIMEOUT_REGISTER, &inp_buf, &outp_buf, (ioctl_arg * 1000000) / n_port->baud); + neuronspi_spi_send_message(spi, inp_buf, outp_buf, write_length, n_spi->ideal_frequency, 25, 1); + return 1; + } + case 0x5481: { + printk(KERN_INFO "NEURONSPI: IOCTL 0x5481\n"); + write_length = neuronspi_spi_compose_single_register_write(NEURONSPI_UART_TIMEOUT_REGISTER, &inp_buf, &outp_buf, ioctl_arg); + neuronspi_spi_send_message(spi, inp_buf, outp_buf, write_length, n_spi->ideal_frequency, 25, 1); + return 1; + } + default: { + return 0; + } + } +} + +void neuronspi_uart_set_parmrk(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); + printk(KERN_INFO "NEURONSPI: SET PARMRK to %d\n", 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); +} + +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); + printk(KERN_INFO "NEURONSPI: PROFIBUS discipline set\n"); + 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); +} + +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 (old && old->c_iflag && old->c_iflag != termios->c_iflag) { + printk(KERN_INFO "NEURONSPI: c_iflag termios:%d\n", termios->c_iflag); + } +#if NEURONSPI_DETAILED_DEBUG > 0 + printk(KERN_DEBUG "NEURONSPI: TERMIOS Set, p:%d, c_cflag:%x\n", port->line, termios->c_cflag); +#endif + neuronspi_spi_uart_set_cflag(neuronspi_s_dev[n_port->dev_index], n_port->dev_port, termios->c_cflag); + if (old && termios && (old->c_iflag & PARMRK) != (termios->c_iflag & PARMRK)) { + if (termios->c_iflag & PARMRK) { + neuronspi_uart_set_parmrk(port, 1); + } else { + neuronspi_uart_set_parmrk(port, 0); + } + } + if (old && termios && old->c_line != termios->c_line) { + if (termios->c_line == N_PROFIBUS_FDL) { + printk(KERN_INFO "NEURONSPI: Line Discipline change/n"); + neuronspi_uart_set_ldisc(port, termios); + } + } + n_port->baud = uart_get_baud_rate(port, termios, old, 2400, 115200); + uart_update_timeout(port, termios->c_cflag, n_port->baud); +} + +s32 neuronspi_uart_config_rs485(struct uart_port *port, struct serial_rs485 *rs485) +{ + port->rs485 = *rs485; + return 0; +} + +const char* neuronspi_uart_type(struct uart_port *port) +{ + return port->type == PORT_NEURONSPI ? "NEURONSPI_NAME" : NULL; +} + +s32 neuronspi_uart_request_port(struct uart_port *port) +{ +#if NEURONSPI_DETAILED_DEBUG > 0 + printk(KERN_DEBUG "NEURONSPI: Requested port %d\n", port->line); +#endif + return 0; +} + +void neuronspi_uart_fifo_read(struct uart_port *port, u32 rxlen) +{ + struct neuronspi_port *s = to_neuronspi_port(port,port); + struct neuronspi_driver_data *d_data = spi_get_drvdata(neuronspi_s_dev[s->dev_index]); +#if NEURONSPI_DETAILED_DEBUG > 0 + printk(KERN_INFO "NEURONSPI: FIFO Read len:%d\n", rxlen); +#endif + memcpy(s->buf, d_data->uart_buf, rxlen); +} + +void neuronspi_uart_fifo_write(struct neuronspi_port *port, u8 to_send) +{ + s32 i; +#if NEURONSPI_DETAILED_DEBUG > 0 + printk(KERN_INFO "NEURONSPI: FIFO Write to_send:%d\n", to_send); +#endif + for (i = 0; i < to_send; i++) { +#if NEURONSPI_DETAILED_DEBUG > 0 + printk(KERN_INFO "NEURONSPI: UART Char Send: %x\n", port->buf[i]); +#endif + } + neuronspi_spi_uart_write(neuronspi_s_dev[port->dev_index], port->buf, to_send, port->dev_port); +} + +s32 neuronspi_uart_alloc_line(void) +{ + s32 i; + BUILD_BUG_ON(NEURONSPI_MAX_DEVS > BITS_PER_LONG); + + for (i = 0; i < NEURONSPI_MAX_DEVS; i++) + if (!test_and_set_bit(i, &neuronspi_lines)) + break; + + return i; +} + +void neuronspi_uart_handle_rx(struct neuronspi_port *port, u32 rxlen, u32 iir) +{ + u32 ch, flag, bytes_read, i; + while (rxlen) { + + neuronspi_uart_fifo_read(&port->port, rxlen); + bytes_read = rxlen; + + port->port.icount.rx++; + flag = TTY_NORMAL; + + for (i = 0; i < bytes_read; ++i) { +#if NEURONSPI_DETAILED_DEBUG > 0 + printk(KERN_INFO "NEURONSPI: UART Insert Char:%x\n", port->buf[i]); +#endif + ch = port->buf[i]; + if (uart_handle_sysrq_char(port, ch)) + continue; + + uart_insert_char(&port->port, 0, 0, ch, flag); + } + rxlen -= bytes_read; + } + + tty_flip_buffer_push(&port->port.state->port); +} + +void neuronspi_uart_handle_tx(struct neuronspi_port *port) +{ + u32 txlen, to_send, i; + struct spi_device *spi; + struct neuronspi_driver_data *d_data; + struct circ_buf *xmit; + + spi = neuronspi_s_dev[port->dev_index]; + d_data = spi_get_drvdata(spi); + xmit = &port->port.state->xmit; + + if (unlikely(port->port.x_char)) { + neuronspi_spi_uart_write(spi, &port->port.x_char, 1, port->dev_port); + port->port.icount.tx++; + port->port.x_char = 0; + return; + } + + if (uart_circ_empty(xmit) || uart_tx_stopped(&port->port)) { + return; + } + + /* Get length of data pending in circular buffer */ + to_send = uart_circ_chars_pending(xmit); + if (likely(to_send)) { + /* Limit to size of TX FIFO */ + txlen = NEURONSPI_FIFO_SIZE; + to_send = (to_send > txlen) ? txlen : to_send; + + /* Add data to send */ + port->port.icount.tx += to_send; + + /* Convert to linear buffer */ + for (i = 0; i < to_send; ++i) { + port->buf[i] = xmit->buf[xmit->tail]; + xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); + } + + neuronspi_uart_fifo_write(port, to_send); + } + + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) { + uart_write_wakeup(&port->port); + } +} + +void neuronspi_uart_handle_irq(struct neuronspi_uart_data *uart_data, u32 portno) +{ + struct neuronspi_port *n_port = &uart_data->p[portno]; + struct spi_device *spi = neuronspi_s_dev[n_port->dev_index]; + u8 *send_buf = kzalloc(NEURONSPI_UART_PROBE_MESSAGE_LEN, GFP_KERNEL); + u8 *recv_buf = kzalloc(NEURONSPI_UART_PROBE_MESSAGE_LEN, GFP_KERNEL); + memcpy(send_buf, NEURONSPI_UART_PROBE_MESSAGE, NEURONSPI_UART_PROBE_MESSAGE_LEN); + neuronspi_spi_send_message(spi, send_buf, recv_buf, NEURONSPI_UART_PROBE_MESSAGE_LEN, NEURONSPI_DEFAULT_FREQ, 25, 1); + kfree(send_buf); + kfree(recv_buf); +} + +void neuronspi_uart_ist(struct kthread_work *ws) +{ + struct neuronspi_port *p = to_neuronspi_port(ws, irq_work); + neuronspi_uart_handle_irq(p->parent, p->line); +} + +void neuronspi_uart_config_port(struct uart_port *port, int flags) +{ + if (flags & UART_CONFIG_TYPE) { + port->type = PORT_NEURONSPI; + } +} + +s32 neuronspi_uart_verify_port(struct uart_port *port, + struct serial_struct *s) +{ + if ((s->type != PORT_UNKNOWN) && (s->type != PORT_NEURONSPI)) + return -EINVAL; + if (s->irq != port->irq) + return -EINVAL; + + return 0; +} + +void neuronspi_uart_pm(struct uart_port *port, u32 state, u32 oldstate) +{ + neuronspi_uart_power(port, (state == UART_PM_STATE_ON) ? 1 : 0); +} + +s32 neuronspi_uart_probe(struct spi_device* dev, u8 device_index) +{ + struct neuronspi_driver_data* driver_data = spi_get_drvdata(dev); + struct sched_param sched_param = { .sched_priority = MAX_RT_PRIO / 2 }; + s32 i, j, ret, new_uart_count; + struct neuronspi_uart_data *uart_data = driver_data->uart_data; + + if (uart_data->p == NULL) { + uart_data->p = kzalloc(sizeof(struct neuronspi_port[NEURONSPI_MAX_UART]), GFP_KERNEL); + for (i = 0; i < NEURONSPI_MAX_UART; i++) { + uart_data->p[i].parent = uart_data; + } +#if NEURONSPI_DETAILED_DEBUG > 0 + printk(KERN_DEBUG "NEURONSPI: Allocated port structure for %d potential UART devices\n", NEURONSPI_MAX_UART); +#endif + } + + new_uart_count = driver_data->uart_count + uart_data->p_count; + + // Initialise port data + for (i = uart_data->p_count; i < new_uart_count; i++) { + uart_data->p[i].dev_index = device_index; + uart_data->p[i].dev_port = i - uart_data->p_count; + uart_data->p[i].line = i; + uart_data->p[i].port.dev = &(dev->dev); + uart_data->p[i].port.irq = dev->irq; + uart_data->p[i].port.type = PORT_NEURONSPI; + uart_data->p[i].port.fifosize = NEURONSPI_FIFO_SIZE; + uart_data->p[i].port.flags = UPF_FIXED_TYPE | UPF_LOW_LATENCY; + uart_data->p[i].port.iotype = UPIO_PORT; + uart_data->p[i].port.uartclk = 9600; + uart_data->p[i].port.rs485_config = neuronspi_uart_config_rs485; + uart_data->p[i].port.ops = &neuronspi_uart_ops; + uart_data->p[i].port.line = neuronspi_uart_alloc_line(); + spin_lock_init(&uart_data->p[i].port.lock); + if (uart_data->p[i].port.line >= NEURONSPI_MAX_DEVS) { + ret = -ENOMEM; + } + kthread_init_work(&(uart_data->p[i].tx_work), neuronspi_uart_tx_proc); + kthread_init_work(&(uart_data->p[i].rx_work), neuronspi_uart_rx_proc); + kthread_init_work(&(uart_data->p[i].irq_work), neuronspi_uart_ist); + uart_add_one_port(driver_data->serial_driver, &uart_data->p[i].port); + printk(KERN_INFO "NEURONSPI: Added UART port %d\n", i); + } + + // For ports on multiple SPI devices renumber the ports to correspond to SPI chip-select numbering + if (uart_data->p_count) { + // First remove all existing ports + for (i = 0; i < new_uart_count; i++) { + uart_remove_one_port(driver_data->serial_driver, &uart_data->p[i].port); + clear_bit(uart_data->p[i].port.line, &neuronspi_lines); + kthread_flush_worker(&uart_data->kworker); + } + // Now add the ports in the correct order + for (i = 0; i < NEURONSPI_MAX_DEVS; i++) { + if (neuronspi_s_dev[i] != NULL) { + driver_data = spi_get_drvdata(neuronspi_s_dev[i]); +#if NEURONSPI_DETAILED_DEBUG > 0 + printk(KERN_DEBUG "NEURONSPI: Renumber not NULL %d UC:%d\n", i, driver_data->uart_count); +#endif + if (driver_data->uart_count) { + for (j = 0; j < new_uart_count; j++) { + if (uart_data->p[j].dev_index == i) { + uart_data->p[j].port.dev = &(neuronspi_s_dev[i]->dev); + uart_data->p[j].port.irq = neuronspi_s_dev[i]->irq; + uart_data->p[j].port.type = PORT_NEURONSPI; + uart_data->p[j].port.fifosize = NEURONSPI_FIFO_SIZE; + uart_data->p[j].port.flags = UPF_FIXED_TYPE | UPF_LOW_LATENCY; + uart_data->p[j].port.iotype = UPIO_PORT; + uart_data->p[j].port.uartclk = 9800; + uart_data->p[j].port.rs485_config = neuronspi_uart_config_rs485; + uart_data->p[j].port.ops = &neuronspi_uart_ops; + uart_data->p[j].port.line = neuronspi_uart_alloc_line(); + uart_add_one_port(driver_data->serial_driver, &uart_data->p[j].port); +#if NEURONSPI_DETAILED_DEBUG > 0 + printk(KERN_DEBUG "NEURONSPI: Added UART port %d\n", j); +#endif + } + } + } + } + } + } + + uart_data->p_count = new_uart_count; + if (uart_data->kworker_task == NULL) { +#if NEURONSPI_DETAILED_DEBUG > 0 + printk(KERN_DEBUG "NEURONSPI: KWorker Task is NULL\n"); +#endif + + kthread_init_worker(&uart_data->kworker); + + uart_data->kworker_task = kthread_run(kthread_worker_fn, &uart_data->kworker, + "neuronspi"); + if (IS_ERR(uart_data->kworker_task)) { + ret = PTR_ERR(uart_data->kworker_task); + } + sched_setscheduler(uart_data->kworker_task, SCHED_FIFO, &sched_param); + } + return ret; +} + +s32 neuronspi_uart_remove(struct neuronspi_uart_data *u_data) +{ + struct neuronspi_driver_data *d_data; + struct spi_device *spi; + s32 i; + + for (i = 0; i < NEURONSPI_MAX_DEVS; i++) { + if (!(neuronspi_s_dev[i] == NULL)) { + spi = neuronspi_s_dev[i]; + d_data = spi_get_drvdata(spi); + if (d_data->poll_thread != NULL) { + kthread_stop(d_data->poll_thread); + } + } + } + for (i = 0; i < u_data->p_count; i++) { + uart_remove_one_port(neuronspi_uart, &u_data->p[i].port); + clear_bit(u_data->p[i].port.line, &neuronspi_lines); + neuronspi_uart_power(&u_data->p[i].port, 0); + } + + kthread_flush_worker(&u_data->kworker); + return 0; +} + +void neuronspi_uart_rx_proc(struct kthread_work *ws) +{ + s32 end_flag = 0; + s32 read_count = 0; + struct neuronspi_port *n_port = to_neuronspi_port(ws, rx_work); + struct spi_device *spi = neuronspi_s_dev[n_port->dev_index]; + struct neuronspi_driver_data *d_data = spi_get_drvdata(spi); + + u8 *send_buf = kzalloc(NEURONSPI_BUFFER_MAX, GFP_KERNEL); + u8 *recv_buf = kzalloc(NEURONSPI_BUFFER_MAX, GFP_KERNEL); + + mutex_lock(&neuronspi_master_mutex); + read_count = d_data->uart_read; + mutex_unlock(&neuronspi_master_mutex); + + while (!end_flag) { + memset(recv_buf, 0, NEURONSPI_BUFFER_MAX); + neuronspi_spi_uart_read(spi, send_buf, recv_buf, read_count, n_port->dev_port); + if (recv_buf[6] == 0x65 && recv_buf[7] > 0) { + mutex_lock(&neuronspi_master_mutex); + memcpy(&d_data->uart_buf[0], &recv_buf[10], recv_buf[7]); + neuronspi_uart_handle_rx(n_port, recv_buf[7], 1); + read_count = recv_buf[9]; + mutex_unlock(&neuronspi_master_mutex); + } else if (recv_buf[0] != 0x41) { + mutex_lock(&neuronspi_master_mutex); + d_data->uart_read = 0; + end_flag = 1; + mutex_unlock(&neuronspi_master_mutex); + } + } + kfree(recv_buf); + kfree(send_buf); +} + +void neuronspi_uart_start_tx(struct uart_port *port) +{ + struct neuronspi_port *n_port = to_neuronspi_port(port,port); +#if NEURONSPI_DETAILED_DEBUG > 0 + printk(KERN_INFO "NEURONSPI: Start TX\n"); +#endif + kthread_queue_work(&n_port->parent->kworker, &n_port->tx_work); +} + +s32 neuronspi_uart_poll(void *data) +{ + struct neuronspi_driver_data *d_data = (struct neuronspi_driver_data*) data; + struct neuronspi_uart_data *u_data; + s32 i; + while (!kthread_should_stop()) { + usleep_range(2000,8000); + if (d_data->uart_count) { + u_data = d_data->uart_data; + for (i = 0; i < u_data->p_count; i++) { + if (u_data->p[i].dev_index == d_data->neuron_index) { + kthread_queue_work(&u_data->kworker, &u_data->p[i].irq_work); + } + } + } + } + return 0; +} + +// Initialise the driver +s32 neuronspi_uart_startup(struct uart_port *port) +{ + struct neuronspi_port *n_port = to_neuronspi_port(port, port); + struct spi_device *spi = neuronspi_s_dev[n_port->dev_index]; + struct neuronspi_driver_data *d_data = spi_get_drvdata(spi); + neuronspi_spi_set_irqs(spi, 0x5); + if (d_data->poll_thread != NULL) { + wake_up_process(d_data->poll_thread); + } else if (d_data->no_irq) { + d_data->poll_thread = kthread_create(neuronspi_uart_poll, (void *)d_data, "UART_poll_thread"); + } + neuronspi_uart_power(port, 1); + // TODO: /* Reset FIFOs*/ +#if NEURONSPI_DETAILED_DEBUG > 0 + printk(KERN_DEBUG "NEURONSPI: UART Startup\n"); +#endif + return 0; +} + +void neuronspi_uart_shutdown(struct uart_port *port) +{ + neuronspi_uart_power(port, 0); +} + +/******************* + * Empty functions * + *******************/ + +void neuronspi_uart_stop_tx(struct uart_port *port) +{ + /* Do Nothing */ +} + +void neuronspi_uart_stop_rx(struct uart_port *port) +{ + /* Do Nothing */ +} +void neuronspi_uart_set_mctrl(struct uart_port *port, u32 mctrl) +{ + /* Do Nothing */ +} +void neuronspi_uart_break_ctl(struct uart_port *port, int break_state) +{ + /* Do Nothing */ +} +void neuronspi_uart_power(struct uart_port *port, s32 on) +{ + /* Do nothing */ +} +void neuronspi_uart_null_void(struct uart_port *port) +{ + /* Do nothing */ +} diff --git a/modules/unipi/src/unipi_uart.h b/modules/unipi/src/unipi_uart.h new file mode 100644 index 0000000..81a702d --- /dev/null +++ b/modules/unipi/src/unipi_uart.h @@ -0,0 +1,126 @@ +/* + * UniPi Neuron tty serial driver - Copyright (C) 2018 UniPi Technologies + * Author: Tomas Knot + * + * Based on the SC16IS7xx driver by Jon Ringle , + * which was in turn based on max310x.c, by Alexander Shiyan + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +#ifndef MODULES_NEURON_SPI_SRC_UNIPI_UART_H_ +#define MODULES_NEURON_SPI_SRC_UNIPI_UART_H_ + +/************ + * Includes * + ************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "unipi_common.h" +#include "unipi_platform.h" + +/*************** + * Definitions * + ***************/ + +#define NEURONSPI_UART_IFLAGS_REGISTER 502 +#define NEURONSPI_UART_LDISC_REGISTER 503 +#define NEURONSPI_UART_TIMEOUT_REGISTER 504 + +/************************* + * Function Declarations * + *************************/ + +void neuronspi_uart_start_tx(struct uart_port *port); +void neuronspi_uart_stop_tx(struct uart_port *port); +void neuronspi_uart_stop_rx(struct uart_port *port); +void neuronspi_uart_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old); +u32 neuronspi_uart_tx_empty(struct uart_port *port); +void neuronspi_uart_break_ctl(struct uart_port *port, int break_state); +void neuronspi_uart_shutdown(struct uart_port *port); +s32 neuronspi_uart_startup(struct uart_port *port); +s32 neuronspi_uart_request_port(struct uart_port *port); +s32 neuronspi_uart_alloc_line(void); +void neuronspi_uart_set_mctrl(struct uart_port *port, u32 mctrl); +int neuronspi_uart_ioctl (struct uart_port *port, unsigned int ioctl_code, unsigned long ioctl_arg); +void neuronspi_uart_set_ldisc(struct uart_port *port, struct ktermios *kterm); +u32 neuronspi_uart_get_mctrl(struct uart_port *port); +const char *neuronspi_uart_type(struct uart_port *port); +void neuronspi_uart_null_void(struct uart_port *port); +void neuronspi_uart_config_port(struct uart_port *port, int flags); +s32 neuronspi_uart_verify_port(struct uart_port *port, struct serial_struct *s); +void neuronspi_uart_pm(struct uart_port *port, u32 state, u32 oldstate); +s32 neuronspi_uart_poll(void *data); +s32 neuronspi_uart_probe(struct spi_device* dev, u8 device_index); +s32 neuronspi_uart_remove(struct neuronspi_uart_data *u_data); +void neuronspi_uart_power(struct uart_port *port, s32 on); +s32 neuronspi_uart_config_rs485(struct uart_port *port, struct serial_rs485 *rs485); +void neuronspi_spi_uart_set_cflag(struct spi_device* spi_dev, u8 port, u32 to); +u32 neuronspi_spi_uart_get_cflag(struct spi_device* spi_dev, u8 port); +void neuronspi_uart_fifo_write(struct neuronspi_port *port, u8 to_send); +void neuronspi_uart_fifo_read(struct uart_port *port, u32 rxlen); +void neuronspi_uart_rx_proc(struct kthread_work *ws); +void neuronspi_uart_tx_proc(struct kthread_work *ws); +void neuronspi_uart_ist(struct kthread_work *ws); +void neuronspi_uart_handle_tx(struct neuronspi_port *port); +void neuronspi_uart_handle_rx(struct neuronspi_port *port, u32 rxlen, u32 iir); +void neuronspi_uart_handle_irq(struct neuronspi_uart_data *uart_data, u32 portno); + +/********************* + * Data Declarations * + *********************/ + +extern struct neuronspi_uart_data* neuronspi_uart_glob_data; +extern unsigned long neuronspi_lines; +extern struct uart_driver* neuronspi_uart; + +static const struct uart_ops neuronspi_uart_ops = +{ + .tx_empty = neuronspi_uart_tx_empty, + .set_mctrl = neuronspi_uart_set_mctrl, + .get_mctrl = neuronspi_uart_get_mctrl, + .stop_tx = neuronspi_uart_stop_tx, + .start_tx = neuronspi_uart_start_tx, + .stop_rx = neuronspi_uart_stop_rx, + .break_ctl = neuronspi_uart_break_ctl, + .startup = neuronspi_uart_startup, + .shutdown = neuronspi_uart_shutdown, + .set_termios = neuronspi_uart_set_termios, + .set_ldisc = neuronspi_uart_set_ldisc, + .type = neuronspi_uart_type, + .request_port = neuronspi_uart_request_port, + .release_port = neuronspi_uart_null_void, + .config_port = neuronspi_uart_config_port, + .verify_port = neuronspi_uart_verify_port, + .pm = neuronspi_uart_pm, + .ioctl = neuronspi_uart_ioctl, +}; + +#endif /* MODULES_NEURON_SPI_SRC_UNIPI_UART_H_ */