// read queue length
port->rx_remain = recv_buf->first_message[2];
unipi_spi_trace(KERN_INFO "UNIPISPI: UART Buffer:%d, ttyNS%d(%d:%d)\n", port->rx_remain, port->port.line, port->dev_index, port->dev_port);
- kthread_queue_work(&neuronspi_uart_data_global->kworker, &port->rx_work);
+ //kthread_queue_work(&neuronspi_uart_data_global->kworker, &port->rx_work);
+ kthread_queue_work(d_data->primary_worker, &port->rx_work);
}
}
}
struct neuronspi_driver_data* n_spi = ((container_of((timer), struct neuronspi_driver_data, poll_timer)));
unipi_spi_trace_1(KERN_INFO "UNIPISPI: nspi%d POLL IRQ\n", n_spi->neuron_index);
- kthread_queue_work(&n_spi->primary_worker, &n_spi->irq_work);
+ kthread_queue_work(n_spi->primary_worker, &n_spi->irq_work);
return HRTIMER_NORESTART;
}
-/*
-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 < neuronspi_uart_data_global->p_count; i++) {
- if (neuronspi_uart_data_global->p[i].dev_index == d_data->neuron_index) {
- kthread_queue_work(&neuronspi_uart_data_global->kworker, &neuronspi_uart_data_global->p[i].irq_work);
- }
- }
- }
- }
- return 0;
-}
-*/
irqreturn_t neuronspi_spi_irq(s32 irq, void *dev_id)
{
struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi);
unipi_spi_trace(KERN_INFO "UNIPISPI: nspi%d SPI IRQ\n", n_spi->neuron_index);
- kthread_queue_work(&n_spi->primary_worker, &n_spi->irq_work);
+ kthread_queue_work(n_spi->primary_worker, &n_spi->irq_work);
return IRQ_HANDLED;
}
// start polling
n_spi->poll_enabled = 1;
// invoke first probe -> which invokes hrtimer
- kthread_queue_work(&n_spi->primary_worker, &n_spi->irq_work);
+ kthread_queue_work(n_spi->primary_worker, &n_spi->irq_work);
}
}
const char *board_name = name_unknown;
u32 probe_always_succeeds;
u32 always_create_uart;
+ struct kthread_worker *worker;
unsigned long flags;
break;
}
}
- n_spi->ideal_frequency = neuronspi_is_noirq_model(lower_board) ? NEURONSPI_SLOWER_FREQ : NEURONSPI_COMMON_FREQ;
+ n_spi->ideal_frequency = neuronspi_is_slower_model(lower_board) ? NEURONSPI_SLOWER_FREQ : NEURONSPI_COMMON_FREQ;
no_irq = neuronspi_is_noirq_model(lower_board);
- printk(KERN_INFO "UNIPISPI: Detected UniPi Board %s (L:%x U:%x C:%x) at CS%d (nspi%d)\n\t\t\tFw: v%d.%d Uarts:%d, reg1001-4: %04x %04x %04x %04x\n",
+ printk(KERN_INFO "UNIPISPI: UniPi Board %s (L:%x U:%x C:%x) at CS%d (nspi%d) detected.\n\t\t\tFw: v%d.%d Uarts:%d, reg1001-4: %04x %04x %04x %04x\n",
board_name, hi(lower_board), upper_board, hardware_model, spi->chip_select, n_spi->neuron_index,
hi(n_spi->firmware_version), lo(n_spi->firmware_version), uart_count,
REG1000(first_probe,1001), REG1000(first_probe,1002), REG1000(first_probe,1003), REG1000(first_probe,1004));
if (always_create_uart) uart_count = 1;
n_spi->ideal_frequency = NEURONSPI_SLOWER_FREQ;
no_irq = 1;
- printk(KERN_INFO "UNIPISPI: Probe assigned DUMMY UniPi Board at CS%d (nspi%d) Uarts:%d, uses freq. %d Hz\n",
+ printk(KERN_INFO "UNIPISPI: DUMMY UniPi Board at CS%d (nspi%d) assigned. Uarts:%d, uses freq. %d Hz\n",
spi->chip_select, n_spi->neuron_index, uart_count, n_spi->ideal_frequency);
} else {
return ret;
}
- // Prepare worker for interrupt, LEDs,
- kthread_init_worker(&n_spi->primary_worker);
-
- n_spi->primary_worker_task = kthread_run(kthread_worker_fn, &n_spi->primary_worker, "unipispi%d", n_spi->neuron_index);
- if (IS_ERR(n_spi->primary_worker_task )) {
- ret = PTR_ERR(n_spi->primary_worker_task);
+ // Prepare worker for interrupt, LEDs, UARTs
+ worker = kthread_create_worker(0, "unipispi%d", n_spi->neuron_index);
+ if (IS_ERR(worker)) {
kfree(n_spi);
- return ret;
- }
- sched_setscheduler(n_spi->primary_worker_task, SCHED_FIFO, &neuronspi_sched_param);
-
+ return PTR_ERR(worker);
+ }
+ sched_setscheduler(worker->task, SCHED_FIFO, &neuronspi_sched_param);
+ n_spi->primary_worker = worker;
+
+/*
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) {
} else {
n_spi->regstart_table = NULL;
}
-
- //n_spi->char_driver = &neuronspi_cdrv;
+*/
+ // save device into global array
spin_lock_irqsave(neuronspi_probe_spinlock, flags);
-
- neuronspi_s_dev[n_spi->neuron_index] = spi;
spi_set_drvdata(spi, n_spi);
+ neuronspi_s_dev[n_spi->neuron_index] = spi;
if (neuronspi_probe_count == NEURONSPI_MAX_DEVS) {
neuronspi_model_id = neuronspi_find_model_id(neuronspi_probe_count);
}
spin_unlock_irqrestore(neuronspi_probe_spinlock, flags);
+
if (neuronspi_model_id != -1) {
printk(KERN_INFO "UNIPISPI: Detected UniPi board combination corresponding to %s\n", NEURONSPI_MODELTABLE[neuronspi_model_id].model_name);
}
neuron_plc_dev->dev.groups = neuron_plc_attr_groups;
platform_device_add(neuron_plc_dev);
}
-
+/*
n_spi->board_device = neuronspi_board_device_probe(n_spi);
if (n_spi->features) {
n_spi->sec_ao_driver = neuronspi_sec_ao_probe(n_spi->features->sec_ao_count, n_spi->neuron_index, n_spi->board_device);
}
}
-
+*/
n_spi->uart_count_to_probe = uart_count;
if (uart_count) {
if (neuronspi_uart_driver_global != NULL) {
s32 neuronspi_spi_remove(struct spi_device *spi)
{
int i;
+ int neuron_index;
struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi);
if (n_spi) {
-
+ neuron_index = n_spi->neuron_index;
if (n_spi->no_irq) {
hrtimer_cancel(&n_spi->poll_timer);
} else {
devm_free_irq(&(spi->dev), spi->irq, spi);
}
- kthread_flush_worker(&n_spi->primary_worker);
-
+ neuronspi_uart_remove(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_work(&(n_spi->led_driver[i].led_work));
}
kfree(n_spi->led_driver);
n_spi->led_driver = NULL;
+ unipi_spi_trace(KERN_INFO "UNIPISPI: LED Driver unregistered\n");
}
- printk(KERN_INFO "UNIPISPI: LED Driver unregistered\n");
if (n_spi->di_driver) { neuronspi_gpio_remove(n_spi->di_driver); }
if (n_spi->do_driver) { neuronspi_gpio_remove(n_spi->do_driver); }
if (n_spi->ro_driver) { neuronspi_gpio_remove(n_spi->ro_driver); }
- printk(KERN_INFO "UNIPISPI: GPIO Driver unregistered\n");
+ unipi_spi_trace(KERN_INFO "UNIPISPI: 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); }
kfree(n_spi->sec_ao_driver);
n_spi->sec_ao_driver = NULL;
}
- printk(KERN_INFO "UNIPISPI: IIO Driver unregistered\n");
- printk(KERN_INFO "UNIPISPI: SPI/UART Driver unregistered\n");
+ unipi_spi_trace(KERN_INFO "UNIPISPI: IIO Driver unregistered\n");
+*/
if (n_spi->board_device) {
platform_set_drvdata(n_spi->board_device, 0);
platform_device_unregister(n_spi->board_device);
}
+ /*if (n_spi->reg_map)
+ regmap_exit(n_spi->reg_map); */
+
+ kthread_destroy_worker(n_spi->primary_worker);
+ neuronspi_s_dev[neuron_index] = NULL;
kfree(n_spi);
+ printk(KERN_INFO "UNIPISPI: UniPi Board nspi%d removed\n", neuron_index);
}
return 0;
}
printk(KERN_ALERT "NEURONSPI: CDEV Failed to create the device\n");
return PTR_ERR(neuronspi_cdrv.dev);
}
- printk(KERN_DEBUG "UNIPISPI: Device /dev/%s (%d:0) created.\n", NEURON_DEVICE_NAME, major);
+ printk(KERN_DEBUG "UNIPISPI: ModBus/SPI interface /dev/%s (%d:0) created.\n", NEURON_DEVICE_NAME, major);
neuronspi_cdrv.major_number = major;
return 0;
}
printk(KERN_INFO "UNIPISPI: SPI Driver Registered, Major Version: %s\n", NEURONSPI_MAJOR_VERSIONSTRING);
- neuronspi_invalidate_thread = kthread_create(neuronspi_regmap_invalidate, NULL, "unipispi_inv");
- if (neuronspi_invalidate_thread != NULL) {
- wake_up_process(neuronspi_invalidate_thread);
- }
+ neuronspi_invalidate_thread = kthread_run(neuronspi_regmap_invalidate, NULL, "unipispi_inv");
+ if (IS_ERR(neuronspi_invalidate_thread)) {
+ neuronspi_invalidate_thread = NULL;
+ }
char_register_driver();
{
unipi_spi_trace(KERN_INFO "UNIPISPI: Open Counter is %d\n", neuronspi_cdrv.open_counter);
- if (neuronspi_invalidate_thread) {
+ if (neuronspi_invalidate_thread) {
kthread_stop(neuronspi_invalidate_thread);
+ neuronspi_invalidate_thread = NULL;
}
char_unregister_driver();
neuronspi_uart_driver_exit();
struct uart_driver* neuronspi_uart_driver_global = NULL;
//unsigned long neuronspi_lines;
-static struct sched_param neuronspi_sched_param = { .sched_priority = MAX_RT_PRIO / 2 };
+//static struct sched_param neuronspi_sched_param = { .sched_priority = MAX_RT_PRIO / 2 };
void neuronspi_uart_update_timeout(struct neuronspi_port *n_port, unsigned int cflag, unsigned int baud);
struct neuronspi_port *n_port = to_neuronspi_port(port,port);
unipi_uart_trace("Start TX\n");
- if (!kthread_queue_work(&neuronspi_uart_data_global->kworker, &n_port->tx_work)) {
+ if (!kthread_queue_work(n_port->n_spi->primary_worker, &n_port->tx_work)) {
+ //if (!kthread_queue_work(&neuronspi_uart_data_global->kworker, &n_port->tx_work)) {
//unipi_uart_trace("TX WORK OVERFLOW\n");
}
}
port->port.icount.tx++;
spin_unlock_irqrestore(&port->port.lock, flags);
port->port.x_char = 0;
- kthread_queue_work(&neuronspi_uart_data_global->kworker, &port->tx_work);
+ kthread_queue_work(port->n_spi->primary_worker, &port->tx_work);
+ //kthread_queue_work(&neuronspi_uart_data_global->kworker, &port->tx_work);
return;
}
spin_unlock_irqrestore(&port->port.lock, flags);
if (to_send) {
// reschedule work
- kthread_queue_work(&neuronspi_uart_data_global->kworker, &port->tx_work);
+ kthread_queue_work(port->n_spi->primary_worker, &port->tx_work);
+ //kthread_queue_work(&neuronspi_uart_data_global->kworker, &port->tx_work);
} else {
// set timer to check tx_empty
unipi_uart_trace_1("ttyNS%d Handle TX. Start timer=%llu", port->port.line, to_send_packet * port->one_char_nsec);
{
struct neuronspi_port* n_port = ((container_of((timer), struct neuronspi_port, tx_timer)));
- kthread_queue_work(&neuronspi_uart_data_global->kworker, &n_port->tx_work);
+ kthread_queue_work(n_port->n_spi->primary_worker, &n_port->tx_work);
+ //kthread_queue_work(&neuronspi_uart_data_global->kworker, &n_port->tx_work);
return HRTIMER_NORESTART;
}
}
if (n_port->rx_remain > 0) {
- kthread_queue_work(&neuronspi_uart_data_global->kworker, &n_port->rx_work);
+ kthread_queue_work(n_port->n_spi->primary_worker, &n_port->rx_work);
+ //kthread_queue_work(&neuronspi_uart_data_global->kworker, &n_port->rx_work);
}
kfree(recv_buf);
}
}
-s32 neuronspi_uart_remove(void)
+void neuronspi_uart_remove(struct spi_device* spi)
{
- struct neuronspi_driver_data *d_data;
- struct spi_device *spi;
+ struct neuronspi_driver_data *n_spi = spi_get_drvdata(spi);
struct neuronspi_port *port;
- int i;
+ int i, uart_count;
+
+ uart_count = n_spi->uart_count;
+ n_spi->uart_count = 0;
- 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);
- d_data->uart_count = 0;
- }
- }
- if (neuronspi_uart_data_global->kworker_task) {
- kthread_destroy_worker(&neuronspi_uart_data_global->kworker);
- }
- for (i = 0; i < neuronspi_uart_data_global->p_count; i++) {
- port = neuronspi_uart_data_global->p + i;
+ for (i = 0; i < uart_count; i++) {
+ port = neuronspi_uart_data_global->p + i + n_spi->uart_pindex;
hrtimer_cancel(&port->tx_timer);
uart_remove_one_port(neuronspi_uart_driver_global, &port->port);
+ kthread_flush_work(&(port->rx_work));
+ kthread_flush_work(&(port->tx_work));
+
neuronspi_uart_power(&port->port, 0);
kfree(port->rx_queue_primary);
kfree(port->rx_queue_secondary);
+ printk(KERN_INFO "UNIPIUART: Serial port ttyNS%d removed\n", i + n_spi->uart_pindex);
}
- return 0;
}
port->port.dev = &(spi->dev);
port->dev_index = n_spi->neuron_index;
- port->dev_port = i; //neuronspi_uart_data_global->p_count;
+ port->dev_port = i;
+ port->n_spi = n_spi; // shorthand to n_spi
port->port.line = neuronspi_uart_data_global->p_count;
port->port.irq = spi->irq;
unipi_uart_trace("Allocated port structure for %d ttyNS devices", NEURONSPI_MAX_UART);
}
+ /*
if (neuronspi_uart_data_global->kworker_task == NULL) {
kthread_init_worker(&neuronspi_uart_data_global->kworker);
sched_setscheduler(neuronspi_uart_data_global->kworker_task, SCHED_FIFO, &neuronspi_sched_param);
unipi_uart_trace("KWorker unipiuart started\n");
}
-
+ */
ret = neuronspi_uart_probe(spi, n_spi);
if (ret) break; // max number of uarts reached
}
int neuronspi_uart_driver_exit(void)
{
+ int i;
if (neuronspi_uart_driver_global) {
- neuronspi_uart_remove();
+ for (i = 0; i < NEURONSPI_MAX_DEVS; i++) {
+ if (neuronspi_s_dev[i] != NULL) {
+ neuronspi_uart_remove(neuronspi_s_dev[i]);
+ }
+ }
uart_unregister_driver(neuronspi_uart_driver_global);
if (neuronspi_uart_data_global->p)
kfree(neuronspi_uart_data_global->p);