if (n_spi && n_spi->combination_id != 0xFF && n_spi->reg_map && n_spi->regstart_table->uart_conf_reg) {
read_length = neuronspi_spi_compose_single_register_read(504, &inp_buf, &outp_buf);
neuronspi_spi_send_message(spi, inp_buf, outp_buf, read_length, n_spi->ideal_frequency, 25, 1, 0);
- val = outp_buf[10 + 1];
+ val = outp_buf[11];
memcpy(&val, &outp_buf[NEURONSPI_HEADER_LENGTH], sizeof(u16));
kfree(inp_buf);
kfree(outp_buf);
return count;
}
+
+static ssize_t neuronspi_spi_show_register(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ u8 *inp_buf, *outp_buf;
+ int read_length;
+ ssize_t ret = 0;
+ u16 val = 0;
+ struct neuronspi_driver_data *n_spi;
+ struct spi_device *spi;
+ struct platform_device *plat = to_platform_device(dev);
+ n_spi = platform_get_drvdata(plat);
+ spi = neuronspi_s_dev[n_spi->neuron_index];
+ if (n_spi && n_spi->reg_map) {
+ spin_lock(&n_spi->sysfs_regmap_lock);
+ read_length = neuronspi_spi_compose_single_register_read(n_spi->sysfs_register_target, &inp_buf, &outp_buf);
+ spin_unlock(&n_spi->sysfs_regmap_lock);
+ neuronspi_spi_send_message(spi, inp_buf, outp_buf, read_length, n_spi->ideal_frequency, 125, 1, 0);
+ memcpy(&val, &outp_buf[NEURONSPI_HEADER_LENGTH], sizeof(u16));
+ ret = scnprintf(buf, 255, "%x\n", (u32)val);
+ }
+ return ret;
+}
+
+static ssize_t neuronspi_spi_store_register(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_register_target = val;
+ spin_unlock(&n_spi->sysfs_regmap_lock);
+ }
+err_end:
+ return count;
+}
+
+static ssize_t neuronspi_spi_store_register_value(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+ u8 *inp_buf, *outp_buf;
+ int write_length;
+ ssize_t err = 0;
+ unsigned int val = 0;
+ struct neuronspi_driver_data *n_spi;
+ struct spi_device *spi;
+ struct platform_device *plat = to_platform_device(dev);
+ n_spi = platform_get_drvdata(plat);
+ spi = neuronspi_s_dev[n_spi->neuron_index];
+ err = kstrtouint(buf, 0, &val);
+ if (err < 0) goto err_end;
+ if (n_spi && n_spi->reg_map && val < 65536) {
+ spin_lock(&n_spi->sysfs_regmap_lock);
+ write_length = neuronspi_spi_compose_single_register_read(n_spi->sysfs_register_target, &inp_buf, &outp_buf);
+ spin_unlock(&n_spi->sysfs_regmap_lock);
+ neuronspi_spi_send_message(spi, inp_buf, outp_buf, write_length, n_spi->ideal_frequency, 125, 1, 0);
+ }
+err_end:
+ return count;
+}
+
+
+
static ssize_t neuronspi_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 spi_device *spi;
struct platform_device *plat = to_platform_device(dev);
n_spi = platform_get_drvdata(plat);
+ spi = neuronspi_s_dev[n_spi->neuron_index];
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);
return count;
}
+static ssize_t neuronspi_store_regmap_value(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);
+ regmap_write(n_spi->reg_map, 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;
static DEVICE_ATTR(sys_reading_freq, 0660, neuronspi_show_sysfs_speed, neuronspi_store_sysfs_speed);
static DEVICE_ATTR(sys_eeprom_name, 0440, neuronspi_show_eeprom, NULL);
static DEVICE_ATTR(driver_version, 0440, neuronspi_show_driver_version, NULL);
-static DEVICE_ATTR(register_read, 0660, neuronspi_show_regmap, neuronspi_store_regmap);
+static DEVICE_ATTR(register_read, 0660, neuronspi_spi_show_register, neuronspi_spi_store_register);
+static DEVICE_ATTR(register_set, 0220, NULL, neuronspi_spi_store_register_value);
+static DEVICE_ATTR(regmap_read, 0660, neuronspi_show_regmap, neuronspi_store_regmap);
+static DEVICE_ATTR(regmap_set, 0220, NULL, neuronspi_store_regmap_value);
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);
&dev_attr_uart_config.attr,
&dev_attr_uart_timeout.attr,
&dev_attr_register_read.attr,
+ &dev_attr_register_set.attr,
+ &dev_attr_regmap_read.attr,
+ &dev_attr_regmap_set.attr,
NULL,
};
(port->port.rs485.delay_rts_before_send > 0)) {
msleep(port->port.rs485.delay_rts_before_send);
}
-
neuronspi_uart_handle_tx(port);
}
}
}
+int static neuronspi_uart_get_charcount(struct neuronspi_port *port) {
+ u8 *inp_buf, *outp_buf;
+ int read_length;
+ struct spi_device *spi;
+ struct neuronspi_driver_data *n_spi;
+ int ret = 0;
+ spi = neuronspi_s_dev[port->dev_index];
+ n_spi = spi_get_drvdata(spi);
+ if (n_spi && n_spi->combination_id != 0xFF && n_spi->reg_map && n_spi->regstart_table->uart_queue_reg) {
+ read_length = neuronspi_spi_compose_single_register_read(n_spi->regstart_table->uart_queue_reg, &inp_buf, &outp_buf);
+ neuronspi_spi_send_message(spi, inp_buf, outp_buf, read_length, n_spi->ideal_frequency, 35, 1, 0);
+ ret = outp_buf[MODBUS_FIRST_DATA_BYTE + 1];
+ kfree(inp_buf);
+ kfree(outp_buf);
+ }
+ return ret;
+}
+
void neuronspi_uart_fifo_write(struct neuronspi_port *port, u8 to_send)
{
s32 i;
printk(KERN_INFO "NEURONSPI: UART Char Send: %x\n", port->buf[i]);
#endif
}
+ while(neuronspi_uart_get_charcount(port) > 50) {
+ msleep(1);
+ }
neuronspi_spi_uart_write(neuronspi_s_dev[port->dev_index], port->buf, to_send, port->dev_port);
}
void neuronspi_uart_handle_tx(struct neuronspi_port *port)
{
- u32 txlen, to_send, i;
+ u32 max_txlen, to_send, i;
struct spi_device *spi;
struct neuronspi_driver_data *d_data;
struct circ_buf *xmit;
neuronspi_spi_uart_write(spi, &port->port.x_char, 1, port->dev_port);
port->port.icount.tx++;
port->port.x_char = 0;
+ spin_lock(&port->tx_lock);
+ port->tx_work_count--;
+ spin_unlock(&port->tx_lock);
return;
}
if (uart_circ_empty(xmit) || uart_tx_stopped(&port->port)) {
+ spin_lock(&port->tx_lock);
+ port->tx_work_count--;
+ spin_unlock(&port->tx_lock);
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;
+ /* Limit to size of (TX FIFO / 2) */
+ max_txlen = NEURONSPI_FIFO_SIZE >> 1;
+ while (to_send > max_txlen) {
+ to_send = (to_send > max_txlen) ? max_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);
+ }
+ to_send = (to_send > NEURONSPI_FIFO_SIZE - NEURONSPI_FIFO_MIN_CONTINUOUS) ? NEURONSPI_FIFO_SIZE - NEURONSPI_FIFO_MIN_CONTINUOUS : to_send;
/* Add data to send */
port->port.icount.tx += to_send;
}
neuronspi_uart_fifo_write(port, to_send);
+
}
+ spin_lock(&port->tx_lock);
+ port->tx_work_count--;
+ spin_unlock(&port->tx_lock);
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) {
uart_write_wakeup(&port->port);
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].tx_lock);
spin_lock_init(&uart_data->p[i].port.lock);
if (uart_data->p[i].port.line >= NEURONSPI_MAX_DEVS) {
ret = -ENOMEM;
#if NEURONSPI_DETAILED_DEBUG > 0
printk(KERN_INFO "NEURONSPI: Start TX\n");
#endif
+ spin_lock(&n_port->tx_lock);
+ if (n_port->tx_work_count > NEURONSPI_MAX_TX_WORK) {
+ spin_unlock(&n_port->tx_lock);
+ return;
+ } else {
+ n_port->tx_work_count++;
+ }
+ spin_unlock(&n_port->tx_lock);
kthread_queue_work(&n_port->parent->kworker, &n_port->tx_work);
}