diff options
author | Russell King <rmk+kernel@arm.linux.org.uk> | 2009-09-22 19:54:53 (GMT) |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2009-09-22 20:01:40 (GMT) |
commit | ae19ffbadc1b2100285a5b5b3d0a4e0a11390904 (patch) | |
tree | 3c2086ab67398a019089a47ca3f362a4bc6db74f /drivers/staging/meilhaus/me4600_ai.c | |
parent | 34e84f39a27d059a3e6ec6e8b94aafa702e6f220 (diff) | |
parent | 9173a8ef24a6b1b8031507b35b8ffe5f85a87692 (diff) | |
download | linux-fsl-qoriq-ae19ffbadc1b2100285a5b5b3d0a4e0a11390904.tar.xz |
Merge branch 'master' into for-linus
Diffstat (limited to 'drivers/staging/meilhaus/me4600_ai.c')
-rw-r--r-- | drivers/staging/meilhaus/me4600_ai.c | 3405 |
1 files changed, 0 insertions, 3405 deletions
diff --git a/drivers/staging/meilhaus/me4600_ai.c b/drivers/staging/meilhaus/me4600_ai.c deleted file mode 100644 index e496d0c..0000000 --- a/drivers/staging/meilhaus/me4600_ai.c +++ /dev/null @@ -1,3405 +0,0 @@ -/** - * @file me4600_ai.c - * - * @brief ME-4000 analog input subdevice instance. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) - */ - -/* - * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * - * This file 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef __KERNEL__ -# define __KERNEL__ -#endif - -/* - * Includes - */ -#include <linux/module.h> - -#include <linux/slab.h> -#include <linux/spinlock.h> -#include <linux/io.h> -#include <linux/uaccess.h> -#include <linux/types.h> -#include <linux/interrupt.h> -#include <linux/delay.h> - -#include "medefines.h" -#include "meinternal.h" -#include "meerror.h" -#include "medebug.h" -#include "meids.h" - -#include "me4600_reg.h" -#include "me4600_ai_reg.h" -#include "me4600_ai.h" - -/* - * Declarations (local) - */ - -static void me4600_ai_destructor(struct me_subdevice *subdevice); -static int me4600_ai_io_reset_subdevice(me_subdevice_t *subdevice, - struct file *filep, int flags); - -static int me4600_ai_io_single_config(me_subdevice_t *subdevice, - struct file *filep, - int channel, - int single_config, - int ref, - int trig_chan, - int trig_type, int trig_edge, int flags); - -static int me4600_ai_io_single_read(me_subdevice_t *subdevice, - struct file *filep, - int channel, - int *value, int time_out, int flags); - -static int me4600_ai_io_stream_config(me_subdevice_t *subdevice, - struct file *filep, - meIOStreamConfig_t *config_list, - int count, - meIOStreamTrigger_t *trigger, - int fifo_irq_threshold, int flags); -static int me4600_ai_io_stream_read(me_subdevice_t *subdevice, - struct file *filep, - int read_mode, - int *values, int *count, int flags); -static int me4600_ai_io_stream_new_values(me_subdevice_t *subdevice, - struct file *filep, - int time_out, int *count, int flags); -static inline int me4600_ai_io_stream_read_get_value(me4600_ai_subdevice_t * - instance, int *values, - const int count, - const int flags); - -static int me4600_ai_io_stream_start(me_subdevice_t *subdevice, - struct file *filep, - int start_mode, int time_out, int flags); -static int me4600_ai_io_stream_stop(me_subdevice_t *subdevice, - struct file *filep, - int stop_mode, int flags); -static int me4600_ai_io_stream_status(me_subdevice_t *subdevice, - struct file *filep, - int wait, - int *status, int *values, int flags); - -static int me4600_ai_query_range_by_min_max(me_subdevice_t *subdevice, - int unit, - int *min, - int *max, int *maxdata, int *range); -static int me4600_ai_query_number_ranges(me_subdevice_t *subdevice, - int unit, int *count); -static int me4600_ai_query_range_info(me_subdevice_t *subdevice, - int range, - int *unit, - int *min, int *max, int *maxdata); -static int me4600_ai_query_timer(me_subdevice_t *subdevice, - int timer, - int *base_frequency, - long long *min_ticks, long long *max_ticks); -static int me4600_ai_query_number_channels(me_subdevice_t *subdevice, - int *number); -static int me4600_ai_query_subdevice_type(me_subdevice_t *subdevice, - int *type, int *subtype); -static int me4600_ai_query_subdevice_caps(me_subdevice_t *subdevice, - int *caps); -static int me4600_ai_query_subdevice_caps_args(struct me_subdevice *subdevice, - int cap, int *args, int count); - -static irqreturn_t me4600_ai_isr(int irq, void *dev_id); - -static int ai_mux_toggler(me4600_ai_subdevice_t *subdevice); - -/** Immidiate stop. -* Reset all IRQ's sources. (block laches) -* Preserve FIFO -*/ -static int ai_stop_immediately(me4600_ai_subdevice_t *instance); - -/** Immidiate stop. -* Reset all IRQ's sources. (block laches) -* Reset data FIFO -*/ -inline void ai_stop_isr(me4600_ai_subdevice_t *instance); - -/** Interrupt logics. -* Read datas -* Reset latches -*/ -void ai_limited_isr(me4600_ai_subdevice_t *instance, const uint32_t irq_status, - const uint32_t ctrl_status); -void ai_infinite_isr(me4600_ai_subdevice_t *instance, - const uint32_t irq_status, const uint32_t ctrl_status); - -/** Last chunck of datas. We must reschedule sample counter. -* Leaving SC_RELOAD doesn't do any harm, but in some bad case can make extra interrupts. -* When threshold is wrongly set some IRQ are lost.(!!!) -*/ -inline void ai_reschedule_SC(me4600_ai_subdevice_t *instance); - -/** Read datas from FIFO and copy them to buffer */ -static inline int ai_read_data(me4600_ai_subdevice_t *instance, - const int count); - -/** Copy rest of data from fifo to circular buffer.*/ -static inline int ai_read_data_pooling(me4600_ai_subdevice_t *instance); - -/** Set ISM to next state for infinite data aqusation mode*/ -inline void ai_infinite_ISM(me4600_ai_subdevice_t *instance); - -/** Set ISM to next state for define amount of data aqusation mode*/ -inline void ai_limited_ISM(me4600_ai_subdevice_t *instance, - uint32_t irq_status); - -/** Set ISM to next stage for limited mode */ -inline void ai_data_acquisition_logic(me4600_ai_subdevice_t *instance); - -static void me4600_ai_work_control_task(struct work_struct *work); - -/* Definitions - */ - -me4600_ai_subdevice_t *me4600_ai_constructor(uint32_t reg_base, - unsigned int channels, - unsigned int ranges, - int isolated, - int sh, - int irq, - spinlock_t *ctrl_reg_lock, - struct workqueue_struct *me4600_wq) -{ - me4600_ai_subdevice_t *subdevice; - int err; - unsigned int i; - - PDEBUG("executed. idx=0\n"); - - // Allocate memory for subdevice instance. - subdevice = kmalloc(sizeof(me4600_ai_subdevice_t), GFP_KERNEL); - - if (!subdevice) { - PERROR("Cannot get memory for subdevice instance.\n"); - return NULL; - } - - memset(subdevice, 0, sizeof(me4600_ai_subdevice_t)); - - // Initialize subdevice base class. - err = me_subdevice_init(&subdevice->base); - - if (err) { - PERROR("Cannot initialize subdevice base class instance.\n"); - kfree(subdevice); - return NULL; - } - // Initialize spin locks. - spin_lock_init(&subdevice->subdevice_lock); - - subdevice->ctrl_reg_lock = ctrl_reg_lock; - - // Initialize circular buffer. - subdevice->circ_buf.mask = ME4600_AI_CIRC_BUF_COUNT - 1; - - subdevice->circ_buf.buf = - (void *)__get_free_pages(GFP_KERNEL, ME4600_AI_CIRC_BUF_SIZE_ORDER); - PDEBUG("circ_buf = %p size=%ld\n", subdevice->circ_buf.buf, - ME4600_AI_CIRC_BUF_SIZE); - - if (!subdevice->circ_buf.buf) { - PERROR("Cannot get circular buffer.\n"); - me_subdevice_deinit((me_subdevice_t *) subdevice); - kfree(subdevice); - return NULL; - } - - memset(subdevice->circ_buf.buf, 0, ME4600_AI_CIRC_BUF_SIZE); - subdevice->circ_buf.head = 0; - subdevice->circ_buf.tail = 0; - subdevice->status = ai_status_none; - - // Initialize wait queue. - init_waitqueue_head(&subdevice->wait_queue); - - // Save the number of channels. - subdevice->channels = channels; - - /* Initialize the single config entries to reset values */ - for (i = 0; i < channels; i++) { - subdevice->single_config[i].status = ME_SINGLE_CHANNEL_NOT_CONFIGURED; //not configured - } - - // Save if isolated device. - subdevice->isolated = isolated; - - // Save if sample and hold is available. - subdevice->sh = sh; - - // Set stream config to not configured state. - subdevice->fifo_irq_threshold = 0; - subdevice->data_required = 0; - subdevice->chan_list_len = 0; - - // Initialize registers addresses. - subdevice->ctrl_reg = reg_base + ME4600_AI_CTRL_REG; - subdevice->status_reg = reg_base + ME4600_AI_STATUS_REG; - subdevice->channel_list_reg = reg_base + ME4600_AI_CHANNEL_LIST_REG; - subdevice->data_reg = reg_base + ME4600_AI_DATA_REG; - subdevice->chan_timer_reg = reg_base + ME4600_AI_CHAN_TIMER_REG; - subdevice->chan_pre_timer_reg = reg_base + ME4600_AI_CHAN_PRE_TIMER_REG; - subdevice->scan_timer_low_reg = reg_base + ME4600_AI_SCAN_TIMER_LOW_REG; - subdevice->scan_timer_high_reg = - reg_base + ME4600_AI_SCAN_TIMER_HIGH_REG; - subdevice->scan_pre_timer_low_reg = - reg_base + ME4600_AI_SCAN_PRE_TIMER_LOW_REG; - subdevice->scan_pre_timer_high_reg = - reg_base + ME4600_AI_SCAN_PRE_TIMER_HIGH_REG; - subdevice->start_reg = reg_base + ME4600_AI_START_REG; - subdevice->irq_status_reg = reg_base + ME4600_IRQ_STATUS_REG; - subdevice->sample_counter_reg = reg_base + ME4600_AI_SAMPLE_COUNTER_REG; -#ifdef MEDEBUG_DEBUG_REG - subdevice->reg_base = reg_base; -#endif - - // Initialize ranges. - subdevice->ranges_len = ranges; - subdevice->ranges[0].min = -10E6; - subdevice->ranges[0].max = 9999694; - - subdevice->ranges[1].min = 0; - subdevice->ranges[1].max = 9999847; - - subdevice->ranges[2].min = -25E5; - subdevice->ranges[2].max = 2499923; - - subdevice->ranges[3].min = 0; - subdevice->ranges[3].max = 2499961; - - // We have to switch the mux in order to get it work correctly. - ai_mux_toggler(subdevice); - - // Register interrupt service routine. - subdevice->irq = irq; - if (request_irq(subdevice->irq, me4600_ai_isr, - IRQF_DISABLED | IRQF_SHARED, - ME4600_NAME, subdevice)) { - PERROR("Cannot register interrupt service routine.\n"); - me_subdevice_deinit((me_subdevice_t *) subdevice); - free_pages((unsigned long)subdevice->circ_buf.buf, - ME4600_AI_CIRC_BUF_SIZE_ORDER); - subdevice->circ_buf.buf = NULL; - kfree(subdevice); - return NULL; - } - PINFO("Registered irq=%d.\n", subdevice->irq); - - // Override base class methods. - subdevice->base.me_subdevice_destructor = me4600_ai_destructor; - subdevice->base.me_subdevice_io_reset_subdevice = - me4600_ai_io_reset_subdevice; - subdevice->base.me_subdevice_io_single_config = - me4600_ai_io_single_config; - subdevice->base.me_subdevice_io_single_read = me4600_ai_io_single_read; - subdevice->base.me_subdevice_io_stream_config = - me4600_ai_io_stream_config; - subdevice->base.me_subdevice_io_stream_new_values = - me4600_ai_io_stream_new_values; - subdevice->base.me_subdevice_io_stream_read = me4600_ai_io_stream_read; - subdevice->base.me_subdevice_io_stream_start = - me4600_ai_io_stream_start; - subdevice->base.me_subdevice_io_stream_status = - me4600_ai_io_stream_status; - subdevice->base.me_subdevice_io_stream_stop = me4600_ai_io_stream_stop; - subdevice->base.me_subdevice_query_number_channels = - me4600_ai_query_number_channels; - subdevice->base.me_subdevice_query_subdevice_type = - me4600_ai_query_subdevice_type; - subdevice->base.me_subdevice_query_subdevice_caps = - me4600_ai_query_subdevice_caps; - subdevice->base.me_subdevice_query_subdevice_caps_args = - me4600_ai_query_subdevice_caps_args; - subdevice->base.me_subdevice_query_range_by_min_max = - me4600_ai_query_range_by_min_max; - subdevice->base.me_subdevice_query_number_ranges = - me4600_ai_query_number_ranges; - subdevice->base.me_subdevice_query_range_info = - me4600_ai_query_range_info; - subdevice->base.me_subdevice_query_timer = me4600_ai_query_timer; - - // Prepare work queue. - subdevice->me4600_workqueue = me4600_wq; - -/* workqueue API changed in kernel 2.6.20 */ - INIT_DELAYED_WORK(&subdevice->ai_control_task, - me4600_ai_work_control_task); - - return subdevice; -} - -static void me4600_ai_destructor(struct me_subdevice *subdevice) -{ - me4600_ai_subdevice_t *instance; - - instance = (me4600_ai_subdevice_t *) subdevice; - - PDEBUG("executed. idx=0\n"); - - instance->ai_control_task_flag = 0; - // Reset subdevice to asure clean exit. - me4600_ai_io_reset_subdevice(subdevice, NULL, - ME_IO_RESET_SUBDEVICE_NO_FLAGS); - - // Remove any tasks from work queue. This is paranoic because it was done allready in reset(). - if (!cancel_delayed_work(&instance->ai_control_task)) { //Wait 2 ticks to be sure that control task is removed from queue. - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(2); - } - - free_irq(instance->irq, instance); - free_pages((unsigned long)instance->circ_buf.buf, - ME4600_AI_CIRC_BUF_SIZE_ORDER); - me_subdevice_deinit(&instance->base); - kfree(instance); -} - -static int me4600_ai_io_reset_subdevice(me_subdevice_t *subdevice, - struct file *filep, int flags) -{ - me4600_ai_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - volatile uint32_t ctrl; - unsigned long status; - const int timeout = HZ / 10; //100ms - int i; - - PDEBUG("executed. idx=0\n"); - - if (flags) { - PERROR("Invalid flag specified.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - instance = (me4600_ai_subdevice_t *) subdevice; - - ME_SUBDEVICE_ENTER; - - instance->ai_control_task_flag = 0; - instance->status = ai_status_none; - - for (i = 0; i <= timeout; i++) { - spin_lock_irqsave(instance->ctrl_reg_lock, status); - ctrl = inl(instance->ctrl_reg); - //Stop DMA - ctrl &= ~ME4600_AI_CTRL_RPCI_FIFO; - // Stop all actions. No conditions! - ctrl &= ~ME4600_AI_CTRL_BIT_STOP; - ctrl |= ME4600_AI_CTRL_BIT_IMMEDIATE_STOP; - - outl(ctrl, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ctrl_reg - instance->reg_base, ctrl); - spin_unlock_irqrestore(instance->ctrl_reg_lock, status); - - if (!(inl(instance->status_reg) & ME4600_AI_STATUS_BIT_FSM)) - break; - - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1); - } - - if (i > timeout) { - PERROR("FSM is still busy.\n"); - ME_SUBDEVICE_EXIT; - return ME_ERRNO_INTERNAL; - } - - spin_lock_irqsave(instance->ctrl_reg_lock, status); - ctrl = inl(instance->ctrl_reg); - // Clear all features. Dissable interrupts. - ctrl &= ~(ME4600_AI_CTRL_BIT_STOP - | ME4600_AI_CTRL_BIT_LE_IRQ - | ME4600_AI_CTRL_BIT_HF_IRQ | ME4600_AI_CTRL_BIT_SC_IRQ); - ctrl |= (ME4600_AI_CTRL_BIT_IMMEDIATE_STOP - | ME4600_AI_CTRL_BIT_LE_IRQ_RESET - | ME4600_AI_CTRL_BIT_HF_IRQ_RESET - | ME4600_AI_CTRL_BIT_SC_IRQ_RESET); - - outl(ctrl, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->ctrl_reg - instance->reg_base, ctrl); - spin_unlock_irqrestore(instance->ctrl_reg_lock, status); - - outl(ME4600_AI_MIN_CHAN_TICKS - 1, instance->chan_timer_reg); - PDEBUG_REG("chan_timer_reg outl(0x%lX+0x%lX)=0x%llx\n", - instance->reg_base, - instance->chan_timer_reg - instance->reg_base, - ME4600_AI_MIN_CHAN_TICKS); - outl(ME4600_AI_MIN_ACQ_TICKS - 1, instance->chan_pre_timer_reg); - PDEBUG_REG("chan_pre_timer_reg outl(0x%lX+0x%lX)=0x%llx\n", - instance->reg_base, - instance->chan_pre_timer_reg - instance->reg_base, - ME4600_AI_MIN_ACQ_TICKS); - outl(0, instance->scan_timer_low_reg); - PDEBUG_REG("scan_timer_low_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->scan_timer_low_reg - instance->reg_base, 0); - outl(0, instance->scan_timer_high_reg); - PDEBUG_REG("scan_timer_high_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->scan_timer_high_reg - instance->reg_base, 0); - outl(0, instance->scan_pre_timer_low_reg); - PDEBUG_REG("scan_pre_timer_low_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->scan_pre_timer_low_reg - instance->reg_base, 0); - outl(0, instance->scan_pre_timer_high_reg); - PDEBUG_REG("scan_pre_timer_high_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->scan_pre_timer_high_reg - instance->reg_base, 0); - outl(0xEFFFFFFF, instance->sample_counter_reg); - PDEBUG_REG("sample_counter_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->sample_counter_reg - instance->reg_base, - 0xEFFFFFFF); - - instance->circ_buf.head = 0; - instance->circ_buf.tail = 0; - - instance->fifo_irq_threshold = 0; - instance->data_required = 0; - instance->chan_list_len = 0; - - // Initialize the single config entries to reset values. - for (i = 0; i < instance->channels; i++) { - instance->single_config[i].status = - ME_SINGLE_CHANNEL_NOT_CONFIGURED; - } - instance->status = ai_status_none; - - //Signal reset if user is on wait. - wake_up_interruptible_all(&instance->wait_queue); - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me4600_ai_io_single_config(me_subdevice_t *subdevice, - struct file *filep, - int channel, - int single_config, - int ref, - int trig_chan, - int trig_type, int trig_edge, int flags) -{ - me4600_ai_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - unsigned long cpu_flags; - int i; - - instance = (me4600_ai_subdevice_t *) subdevice; - - PDEBUG("executed. idx=0\n"); - - if (flags & ~ME_IO_SINGLE_CONFIG_CONTINUE) { - PERROR("Invalid flag specified.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - switch (trig_type) { - case ME_TRIG_TYPE_SW: - if (trig_edge != ME_TRIG_EDGE_NONE) { - PERROR - ("Invalid trigger edge. Software trigger has not edge.\n"); - return ME_ERRNO_INVALID_TRIG_EDGE; - } - break; - - case ME_TRIG_TYPE_EXT_ANALOG: - if (instance->channels <= 16) //Only versions with 32 channels have analog trigger (4670 and 4680) - { - PERROR("Invalid trigger type specified.\n"); - return ME_ERRNO_INVALID_TRIG_TYPE; - } - - case ME_TRIG_TYPE_EXT_DIGITAL: - if ((trig_edge != ME_TRIG_EDGE_ANY) - && (trig_edge != ME_TRIG_EDGE_RISING) - && (trig_edge != ME_TRIG_EDGE_FALLING)) { - PERROR("Invalid trigger edge specified.\n"); - return ME_ERRNO_INVALID_TRIG_EDGE; - } - break; - - default: - PERROR("Invalid trigger type specified.\n"); - return ME_ERRNO_INVALID_TRIG_TYPE; - } - - if (trig_chan != ME_TRIG_CHAN_DEFAULT) { - PERROR("Invalid trigger channel specified.\n"); - return ME_ERRNO_INVALID_TRIG_CHAN; - } - - if ((single_config < 0) || (single_config >= instance->ranges_len)) { - PERROR("Invalid single config specified.\n"); - return ME_ERRNO_INVALID_SINGLE_CONFIG; - } - - if ((ref != ME_REF_AI_GROUND) && (ref != ME_REF_AI_DIFFERENTIAL)) { - PERROR("Invalid analog reference specified.\n"); - return ME_ERRNO_INVALID_REF; - } - - if ((single_config % 2) && (ref != ME_REF_AI_GROUND)) { - PERROR("Invalid analog reference specified.\n"); - return ME_ERRNO_INVALID_REF; - } - - if ((ref == ME_REF_AI_DIFFERENTIAL) - && ((instance->channels == 16) || (channel >= 16))) { - PERROR("Invalid analog reference specified.\n"); - return ME_ERRNO_INVALID_REF; - } - - if (channel < 0) { - PERROR("Invalid channel number specified.\n"); - return ME_ERRNO_INVALID_CHANNEL; - } - - if (channel >= instance->channels) { - PERROR("Invalid channel number specified.\n"); - return ME_ERRNO_INVALID_CHANNEL; - } - - ME_SUBDEVICE_ENTER; - - spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); - //Prepare data entry. - // Common for all modes. - instance->single_config[channel].entry = - channel | ME4600_AI_LIST_LAST_ENTRY; - - if (ref == ME_REF_AI_DIFFERENTIAL) { // ME_REF_AI_DIFFERENTIAL - instance->single_config[channel].entry |= - ME4600_AI_LIST_INPUT_DIFFERENTIAL; - } -/* - // ME4600_AI_LIST_INPUT_SINGLE_ENDED = 0x0000 - // 'entry |= ME4600_AI_LIST_INPUT_SINGLE_ENDED' <== Do nothing. Removed. - else - {// ME_REF_AI_GROUND - instance->single_config[channel].entry |= ME4600_AI_LIST_INPUT_SINGLE_ENDED; - } -*/ - switch (single_config) { - case 0: //-10V..10V -/* - // ME4600_AI_LIST_RANGE_BIPOLAR_10 = 0x0000 - // 'entry |= ME4600_AI_LIST_RANGE_BIPOLAR_10' <== Do nothing. Removed. - instance->single_config[channel].entry |= ME4600_AI_LIST_RANGE_BIPOLAR_10; -*/ break; - - case 1: //0V..10V - instance->single_config[channel].entry |= - ME4600_AI_LIST_RANGE_UNIPOLAR_10; - break; - - case 2: //-2.5V..2.5V - instance->single_config[channel].entry |= - ME4600_AI_LIST_RANGE_BIPOLAR_2_5; - break; - - case 3: //0V..2.5V - instance->single_config[channel].entry |= - ME4600_AI_LIST_RANGE_UNIPOLAR_2_5; - break; - } - - // Prepare control register. - // Common for all modes. - instance->single_config[channel].ctrl = - ME4600_AI_CTRL_BIT_CHANNEL_FIFO | ME4600_AI_CTRL_BIT_DATA_FIFO; - - switch (trig_type) { - case ME_TRIG_TYPE_SW: - // Nothing to set. - break; - - case ME_TRIG_TYPE_EXT_ANALOG: - instance->single_config[channel].ctrl |= - ME4600_AI_CTRL_BIT_EX_TRIG_ANALOG; - - case ME_TRIG_TYPE_EXT_DIGITAL: - instance->single_config[channel].ctrl |= - ME4600_AI_CTRL_BIT_EX_TRIG; - break; - } - - switch (trig_edge) { - case ME_TRIG_EDGE_RISING: - // Nothing to set. - break; - - case ME_TRIG_EDGE_ANY: - instance->single_config[channel].ctrl |= - ME4600_AI_CTRL_BIT_EX_TRIG_BOTH; - - case ME_TRIG_EDGE_FALLING: - instance->single_config[channel].ctrl |= - ME4600_AI_CTRL_BIT_EX_TRIG_FALLING; - break; - } - - // Enable this channel - instance->single_config[channel].status = ME_SINGLE_CHANNEL_CONFIGURED; - - // Copy this settings to other outputs. - if (flags == ME_IO_SINGLE_CONFIG_CONTINUE) { - for (i = channel + 1; i < instance->channels; i++) { - instance->single_config[i].ctrl = - instance->single_config[channel].ctrl; - instance->single_config[i].entry = - instance->single_config[channel].entry; - instance->single_config[i].status = - ME_SINGLE_CHANNEL_CONFIGURED; - } - } - - instance->status = ai_status_single_configured; - spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me4600_ai_io_single_read(me_subdevice_t *subdevice, - struct file *filep, - int channel, - int *value, int time_out, int flags) -{ - me4600_ai_subdevice_t *instance; - volatile uint32_t tmp; - volatile uint32_t val; - unsigned long cpu_flags; - int err = ME_ERRNO_SUCCESS; - - unsigned long j; - unsigned long delay = 0; - - PDEBUG("executed. idx=0\n"); - - instance = (me4600_ai_subdevice_t *) subdevice; - - if (flags) { - PERROR("Invalid flag specified.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - if (instance->status != ai_status_single_configured) { - PERROR("Subdevice not configured to work in single mode!\n"); - return ME_ERRNO_PREVIOUS_CONFIG; - } - - if ((channel > instance->channels) || (channel < 0)) { - PERROR("Invalid channel specified.\n"); - return ME_ERRNO_INVALID_CHANNEL; - } - - if (time_out < 0) { - PERROR("Invalid timeout specified.\n"); - return ME_ERRNO_INVALID_TIMEOUT; - } - - if (instance->single_config[channel].status != - ME_SINGLE_CHANNEL_CONFIGURED) { - PERROR("Channel is not configured to work in single mode!\n"); - return ME_ERRNO_PREVIOUS_CONFIG; - } - - if (inl(instance->status_reg) & ME4600_AI_STATUS_BIT_FSM) { - PERROR("Subdevice is busy.\n"); - return ME_ERRNO_SUBDEVICE_BUSY; - } - - ME_SUBDEVICE_ENTER; - - // Cancel control task - PDEBUG("Cancel control task.\n"); - instance->ai_control_task_flag = 0; - cancel_delayed_work(&instance->ai_control_task); - - if (time_out) { - delay = (time_out * HZ) / 1000; - - if (delay == 0) - delay = 1; - } - - spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); - - // Mark that StreamConfig is removed. - instance->chan_list_len = 0; - - spin_lock_irqsave(instance->ctrl_reg_lock, cpu_flags); - /// @note Imprtant: Preserve EXT IRQ settings. - tmp = inl(instance->ctrl_reg); - // Clear FIFOs and dissable interrupts - tmp &= - ~(ME4600_AI_CTRL_BIT_CHANNEL_FIFO | ME4600_AI_CTRL_BIT_DATA_FIFO); - - tmp &= - ~(ME4600_AI_CTRL_BIT_SC_IRQ | ME4600_AI_CTRL_BIT_HF_IRQ | - ME4600_AI_CTRL_BIT_LE_IRQ); - tmp |= - ME4600_AI_CTRL_BIT_SC_IRQ_RESET | ME4600_AI_CTRL_BIT_HF_IRQ_RESET | - ME4600_AI_CTRL_BIT_LE_IRQ_RESET; - - tmp |= ME4600_AI_CTRL_BIT_IMMEDIATE_STOP; - outl(tmp, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->ctrl_reg - instance->reg_base, tmp); - - outl(0, instance->scan_pre_timer_low_reg); - PDEBUG_REG("scan_pre_timer_low_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->scan_pre_timer_low_reg - instance->reg_base, 0); - outl(0, instance->scan_pre_timer_high_reg); - PDEBUG_REG("scan_pre_timer_high_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->scan_pre_timer_high_reg - instance->reg_base, 0); - outl(0, instance->scan_timer_low_reg); - PDEBUG_REG("scan_timer_low_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->scan_timer_low_reg - instance->reg_base, 0); - outl(0, instance->scan_timer_high_reg); - PDEBUG_REG("scan_timer_high_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->scan_timer_high_reg - instance->reg_base, 0); - outl(65, instance->chan_timer_reg); - PDEBUG_REG("chan_timer_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->chan_timer_reg - instance->reg_base, 65); - outl(65, instance->chan_pre_timer_reg); - PDEBUG_REG("chan_pre_timer_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->chan_pre_timer_reg - instance->reg_base, 65); - - //Reactive FIFOs. Enable work. - tmp |= ME4600_AI_CTRL_BIT_CHANNEL_FIFO | ME4600_AI_CTRL_BIT_DATA_FIFO; - outl(tmp, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->ctrl_reg - instance->reg_base, tmp); - - outl(instance->single_config[channel].entry, - instance->channel_list_reg); - PDEBUG_REG("channel_list_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->channel_list_reg - instance->reg_base, - instance->single_config[channel].entry); - - // Preserve EXT IRQ settings. - tmp &= (ME4600_AI_CTRL_BIT_EX_IRQ | ME4600_AI_CTRL_BIT_EX_IRQ_RESET); - outl(instance->single_config[channel].ctrl | tmp, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->ctrl_reg - instance->reg_base, - instance->single_config[channel].ctrl | tmp); - - spin_unlock_irqrestore(instance->ctrl_reg_lock, cpu_flags); - - if (!(instance->single_config[channel].ctrl & ME4600_AI_CTRL_BIT_EX_TRIG)) { // Software start - inl(instance->start_reg); - PDEBUG_REG("start_reg inl(0x%lX+0x%lX)\n", instance->reg_base, - instance->start_reg - instance->reg_base); - - delay = 2; - } - - j = jiffies; - - while (!(inl(instance->status_reg) & ME4600_AI_STATUS_BIT_EF_DATA)) { - if (delay && ((jiffies - j) >= delay)) { - if (!(instance->single_config[channel].ctrl & ME4600_AI_CTRL_BIT_EX_TRIG)) { // Software start. - PERROR("Value not available after wait.\n"); - err = ME_ERRNO_INTERNAL; - } else { // External start. - PERROR("Timeout reached.\n"); - err = ME_ERRNO_TIMEOUT; - } - break; - } - // Wait - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1); - - if (signal_pending(current)) { - PERROR - ("Wait on external trigger interrupted by signal.\n"); - err = ME_ERRNO_SIGNAL; - break; - } - - if (instance->status != ai_status_single_configured) { - PERROR("Wait interrupted by reset.\n"); - err = ME_ERRNO_CANCELLED; - break; - } - } - - // Read value. - if (!err) { - val = inl(instance->data_reg) ^ 0x8000; - PDEBUG_REG("data_reg inl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->data_reg - instance->reg_base, val); - *value = val & ME4600_AI_MAX_DATA; - } else { - *value = 0xFFFFFFFF; - } - - // Restore settings. - spin_lock_irqsave(instance->ctrl_reg_lock, cpu_flags); - tmp = inl(instance->ctrl_reg); - // Clear FIFOs and dissable interrupts. - tmp &= - ~(ME4600_AI_CTRL_BIT_CHANNEL_FIFO | ME4600_AI_CTRL_BIT_DATA_FIFO); - tmp |= ME4600_AI_CTRL_BIT_SC_IRQ | ME4600_AI_CTRL_BIT_HF_IRQ; - tmp |= - ME4600_AI_CTRL_BIT_SC_IRQ_RESET | ME4600_AI_CTRL_BIT_HF_IRQ_RESET | - ME4600_AI_CTRL_BIT_LE_IRQ_RESET | ME4600_AI_CTRL_BIT_IMMEDIATE_STOP; - outl(tmp, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->ctrl_reg - instance->reg_base, tmp); - spin_unlock_irqrestore(instance->ctrl_reg_lock, cpu_flags); - - spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me4600_ai_io_stream_config(me_subdevice_t *subdevice, - struct file *filep, - meIOStreamConfig_t *config_list, - int count, - meIOStreamTrigger_t *trigger, - int fifo_irq_threshold, int flags) -{ - me4600_ai_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - int i; // internal multipurpose variable - unsigned long long data_required; - - volatile uint32_t entry; - volatile uint32_t ctrl = ME4600_AI_CTRL_BIT_IMMEDIATE_STOP; - volatile uint32_t tmp; // use when current copy of register's value needed - unsigned long cpu_flags; - - uint64_t acq_ticks; - uint64_t scan_ticks; - uint64_t conv_ticks; - unsigned int acq_start_ticks_low = trigger->iAcqStartTicksLow; - unsigned int acq_start_ticks_high = trigger->iAcqStartTicksHigh; - unsigned int scan_start_ticks_low = trigger->iScanStartTicksLow; - unsigned int scan_start_ticks_high = trigger->iScanStartTicksHigh; - unsigned int conv_start_ticks_low = trigger->iConvStartTicksLow; - unsigned int conv_start_ticks_high = trigger->iConvStartTicksHigh; - - PDEBUG("executed. idx=0\n"); - - instance = (me4600_ai_subdevice_t *) subdevice; - - if (flags) { - PERROR("Invalid flag specified.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - ME_SUBDEVICE_ENTER - // Convert ticks to 64 bit long values - acq_ticks = - (uint64_t) acq_start_ticks_low + - ((uint64_t) acq_start_ticks_high << 32); - scan_ticks = - (uint64_t) scan_start_ticks_low + - ((uint64_t) scan_start_ticks_high << 32); - conv_ticks = - (uint64_t) conv_start_ticks_low + - ((uint64_t) conv_start_ticks_high << 32); - - // Check settings - begin - switch (trigger->iAcqStartTrigType) { - case ME_TRIG_TYPE_SW: - case ME_TRIG_TYPE_EXT_DIGITAL: - case ME_TRIG_TYPE_EXT_ANALOG: - break; - - default: - PERROR("Invalid acquisition start trigger type specified.\n"); - err = ME_ERRNO_INVALID_ACQ_START_TRIG_TYPE; - goto ERROR; - break; - } - - if ((trigger->iAcqStartTrigType == ME_TRIG_TYPE_SW) - && (trigger->iAcqStartTrigEdge != ME_TRIG_EDGE_NONE)) { - PERROR("Invalid acquisition start trigger edge specified.\n"); - err = ME_ERRNO_INVALID_ACQ_START_TRIG_EDGE; - goto ERROR; - } - - if (trigger->iAcqStartTrigType != ME_TRIG_TYPE_SW) { - switch (trigger->iAcqStartTrigEdge) { - case ME_TRIG_EDGE_RISING: - case ME_TRIG_EDGE_FALLING: - case ME_TRIG_EDGE_ANY: - break; - - default: - PERROR - ("Invalid acquisition start trigger edge specified.\n"); - err = ME_ERRNO_INVALID_ACQ_START_TRIG_EDGE; - goto ERROR; - break; - } - } - - if (trigger->iAcqStartTrigChan != ME_TRIG_CHAN_DEFAULT) { - PERROR - ("Invalid acquisition start trigger channel specified.\n"); - err = ME_ERRNO_INVALID_ACQ_START_TRIG_CHAN; - goto ERROR; - } - - if ((acq_ticks < ME4600_AI_MIN_ACQ_TICKS) - || (acq_ticks > ME4600_AI_MAX_ACQ_TICKS)) { - PERROR - ("Invalid acquisition start trigger argument specified.\n"); - err = ME_ERRNO_INVALID_ACQ_START_ARG; - goto ERROR; - } - - switch (trigger->iScanStartTrigType) { - - case ME_TRIG_TYPE_TIMER: - if ((scan_ticks < ME4600_AI_MIN_SCAN_TICKS) - || (scan_ticks > ME4600_AI_MAX_SCAN_TICKS) - || (scan_ticks < count * conv_ticks) - ) { - PERROR("Invalid scan start argument specified.\n"); - err = ME_ERRNO_INVALID_SCAN_START_ARG; - goto ERROR; - } - break; - - case ME_TRIG_TYPE_EXT_DIGITAL: - if (trigger->iAcqStartTrigType != ME_TRIG_TYPE_EXT_DIGITAL) { - PERROR - ("Invalid scan start trigger type specified (Acq is HW digital)\n"); - err = ME_ERRNO_INVALID_SCAN_START_TRIG_TYPE; - goto ERROR; - } - break; - - case ME_TRIG_TYPE_EXT_ANALOG: - if (trigger->iAcqStartTrigType != ME_TRIG_TYPE_EXT_ANALOG) { - PERROR - ("Invalid scan start trigger type specified (Acq is HW analog)\n"); - err = ME_ERRNO_INVALID_SCAN_START_TRIG_TYPE; - goto ERROR; - } - break; - - case ME_TRIG_TYPE_FOLLOW: - break; - - default: - PERROR("Invalid scan start trigger type specified.\n"); - err = ME_ERRNO_INVALID_SCAN_START_TRIG_TYPE; - goto ERROR; - break; - } - - switch (trigger->iConvStartTrigType) { - - case ME_TRIG_TYPE_TIMER: - if ((conv_ticks < ME4600_AI_MIN_CHAN_TICKS) - || (conv_ticks > ME4600_AI_MAX_CHAN_TICKS)) { - PERROR - ("Invalid conv start trigger argument specified.\n"); - err = ME_ERRNO_INVALID_CONV_START_ARG; - goto ERROR; - } - break; - - case ME_TRIG_TYPE_EXT_DIGITAL: - if ((trigger->iScanStartTrigType != ME_TRIG_TYPE_FOLLOW) - || (trigger->iAcqStartTrigType != - ME_TRIG_TYPE_EXT_DIGITAL)) { - PERROR("Invalid conv start trigger type specified.\n"); - err = ME_ERRNO_INVALID_CONV_START_TRIG_TYPE; - goto ERROR; - } - break; - - case ME_TRIG_TYPE_EXT_ANALOG: - if ((trigger->iScanStartTrigType != ME_TRIG_TYPE_FOLLOW) - || (trigger->iAcqStartTrigType != - ME_TRIG_TYPE_EXT_ANALOG)) { - PERROR("Invalid conv start trigger type specified.\n"); - err = ME_ERRNO_INVALID_CONV_START_TRIG_TYPE; - goto ERROR; - } - break; - - default: - PERROR("Invalid conv start trigger type specified.\n"); - err = ME_ERRNO_INVALID_CONV_START_TRIG_TYPE; - goto ERROR; - - break; - } -/** -* Aceptable settings: -* iScanStopTrigType : iAcqStopTrigType -* -* ME_TRIG_TYPE_NONE : ME_TRIG_TYPE_NONE -> infinite count with manual stop -* ME_TRIG_TYPE_NONE : ME_TRIG_TYPE_COUNT -> stop after getting iScanStopCount list of values (iScanStopCount * count) -* ME_TRIG_TYPE_COUNT : ME_TRIG_TYPE_FOLLOW -> stop after getting iAcqStopCount values (it can stops in midle of the list) -*/ - switch (trigger->iScanStopTrigType) { - - case ME_TRIG_TYPE_NONE: - break; - - case ME_TRIG_TYPE_COUNT: - if (trigger->iScanStopCount <= 0) { - PERROR("Invalid scan stop argument specified.\n"); - err = ME_ERRNO_INVALID_SCAN_STOP_ARG; - goto ERROR; - } - break; - - default: - PERROR("Invalid scan stop trigger type specified.\n"); - err = ME_ERRNO_INVALID_SCAN_STOP_TRIG_TYPE; - goto ERROR; - break; - } - - switch (trigger->iAcqStopTrigType) { - - case ME_TRIG_TYPE_NONE: - if (trigger->iScanStopTrigType != ME_TRIG_TYPE_NONE) { - PERROR("Invalid acq stop trigger type specified.\n"); - err = ME_ERRNO_INVALID_ACQ_STOP_TRIG_TYPE; - goto ERROR; - } - break; - - case ME_TRIG_TYPE_FOLLOW: - if (trigger->iScanStopTrigType != ME_TRIG_TYPE_COUNT) { - PERROR("Invalid acq stop trigger type specified.\n"); - err = ME_ERRNO_INVALID_ACQ_STOP_TRIG_TYPE; - goto ERROR; - } - break; - - case ME_TRIG_TYPE_COUNT: - if (trigger->iScanStopTrigType != ME_TRIG_TYPE_NONE) { - PERROR("Invalid acq stop trigger type specified.\n"); - err = ME_ERRNO_INVALID_ACQ_STOP_TRIG_TYPE; - goto ERROR; - } - - if (trigger->iAcqStopCount <= 0) { - PERROR - ("Invalid acquisition or scan stop argument specified.\n"); - err = ME_ERRNO_INVALID_ACQ_STOP_ARG; - goto ERROR; - } - break; - - default: - PERROR("Invalid acq stop trigger type specified.\n"); - err = ME_ERRNO_INVALID_ACQ_STOP_TRIG_TYPE; - goto ERROR; - break; - } - - if ((count <= 0) || (count > ME4600_AI_LIST_COUNT)) { - PERROR("Invalid channel list count specified.\n"); - err = ME_ERRNO_INVALID_CONFIG_LIST_COUNT; - goto ERROR; - } -///This is general limitation -// if (fifo_irq_threshold < 0 || fifo_irq_threshold >= ME4600_AI_CIRC_BUF_COUNT) -///This is limitation from Windows. I use it for compatibility. - if (fifo_irq_threshold < 0 - || fifo_irq_threshold >= ME4600_AI_FIFO_COUNT) { - PERROR("Invalid fifo irq threshold specified.\n"); - err = ME_ERRNO_INVALID_FIFO_IRQ_THRESHOLD; - goto ERROR; - } - - if ((config_list[0].iRef == ME_REF_AI_DIFFERENTIAL) - && (instance->channels == 16)) { - PERROR - ("Differential reference is not available on this subdevice.\n"); - err = ME_ERRNO_INVALID_REF; - goto ERROR; - } - - if (flags & ME_IO_STREAM_CONFIG_SAMPLE_AND_HOLD) { - if (!instance->sh) { - PERROR - ("Sample and hold is not available for this board.\n"); - err = ME_ERRNO_INVALID_FLAGS; - goto ERROR; - } - if (config_list[0].iRef == ME_REF_AI_DIFFERENTIAL) { - PERROR - ("Sample and hold is not available in differential mode.\n"); - err = ME_ERRNO_INVALID_FLAGS; - goto ERROR; - } - } - - for (i = 0; i < count; i++) { - if ((config_list[i].iStreamConfig < 0) - || (config_list[i].iStreamConfig >= instance->ranges_len)) { - PERROR("Invalid stream config specified.\n"); - err = ME_ERRNO_INVALID_STREAM_CONFIG; - goto ERROR; - } - - if ((config_list[i].iRef != ME_REF_AI_GROUND) - && (config_list[i].iRef != ME_REF_AI_DIFFERENTIAL)) { - PERROR("Invalid references in the list. Ref=0x%x\n", - config_list[i].iRef); - err = ME_ERRNO_INVALID_REF; - goto ERROR; - } - - if (config_list[i].iStreamConfig % 2) { // StreamConfig: 1 or 3 - if (config_list[i].iRef == ME_REF_AI_DIFFERENTIAL) { - PERROR - ("Only bipolar modes support differential measurement.\n"); - err = ME_ERRNO_INVALID_REF; - goto ERROR; - } - } - - if (config_list[i].iRef != config_list[0].iRef) { - PERROR - ("Not all references in the configuration list are equal. Ref[0]=0x%x Ref[%d]=0x%x\n", - config_list[0].iRef, i, config_list[i].iRef); - err = ME_ERRNO_INVALID_REF; - goto ERROR; - } - - if ((config_list[i].iRef == ME_REF_AI_DIFFERENTIAL) - && (config_list[i].iChannel >= 16)) { - PERROR("Channel not available in differential mode.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - goto ERROR; - } - - if ((config_list[i].iChannel < 0) - || (config_list[i].iChannel >= instance->channels)) { - PERROR("Invalid channel number specified.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - goto ERROR; - } - } - - // Check settings - end - - //Cancel control task - PDEBUG("Cancel control task.\n"); - instance->ai_control_task_flag = 0; - cancel_delayed_work(&instance->ai_control_task); - - // Work around from Keith Hartley - begin - if (trigger->iScanStartTrigType == ME_TRIG_TYPE_TIMER) { - if (count == 1) { - // The hardware does not work properly with a non-zero scan time - // if there is only ONE channel in the channel list. In this case - // we must set the scan time to zero and use the channel time. - - conv_ticks = scan_ticks; - trigger->iScanStartTrigType = ME_TRIG_TYPE_FOLLOW; - } else if (scan_ticks == count * conv_ticks) { - // Another hardware problem. If the number of scan ticks is - // exactly equal to the number of channel ticks multiplied by - // the number of channels then the sampling rate is reduced - // by half. - trigger->iScanStartTrigType = ME_TRIG_TYPE_FOLLOW; - } - } - // Work around from Keith Hartley - end - - spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); - - if (inl(instance->status_reg) & ME4600_AI_STATUS_BIT_FSM) { - PERROR("Subdevice is busy.\n"); - spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); - ME_SUBDEVICE_EXIT; - return ME_ERRNO_SUBDEVICE_BUSY; - } - - instance->status = ai_status_none; - spin_lock_irqsave(instance->ctrl_reg_lock, cpu_flags); - // Stop all actions. Block all interrupts. Clear (disable) FIFOs. - ctrl = - ME4600_AI_CTRL_BIT_LE_IRQ_RESET | ME4600_AI_CTRL_BIT_HF_IRQ_RESET | - ME4600_AI_CTRL_BIT_SC_IRQ_RESET; - - tmp = inl(instance->ctrl_reg); - // Preserve EXT IRQ and OFFSET settings. Clean other bits. - tmp &= - (ME4600_AI_CTRL_BIT_EX_IRQ | ME4600_AI_CTRL_BIT_EX_IRQ_RESET | - ME4600_AI_CTRL_BIT_FULLSCALE | ME4600_AI_CTRL_BIT_OFFSET); - - // Send it to register. - outl(tmp | ctrl, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->ctrl_reg - instance->reg_base, tmp | ctrl); - - // Enable channel fifo -> data fifo in stream_start(). - ctrl |= ME4600_AI_CTRL_BIT_CHANNEL_FIFO; - outl(tmp | ctrl, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->ctrl_reg - instance->reg_base, tmp | ctrl); - spin_unlock_irqrestore(instance->ctrl_reg_lock, cpu_flags); - - // Write the channel list - for (i = 0; i < count; i++) { - entry = config_list[i].iChannel; - - switch (config_list[i].iStreamConfig) { - case 0: //BIPOLAR 10V -/* - // ME4600_AI_LIST_RANGE_BIPOLAR_10 = 0x0000 - // 'entry |= ME4600_AI_LIST_RANGE_BIPOLAR_10' <== Do nothing. Removed. - entry |= ME4600_AI_LIST_RANGE_BIPOLAR_10; -*/ - break; - case 1: //UNIPOLAR 10V - entry |= ME4600_AI_LIST_RANGE_UNIPOLAR_10; - break; - case 2: //BIPOLAR 2.5V - entry |= ME4600_AI_LIST_RANGE_BIPOLAR_2_5; - break; - case 3: //UNIPOLAR 2.5V - entry |= ME4600_AI_LIST_RANGE_UNIPOLAR_2_5; - break; - default: - PERROR_CRITICAL("UNCHECK ERROR in config_list!\n"); - PERROR_CRITICAL - ("WRONG range\nPosition:%d Range:0x%04X\n", i, - config_list[i].iStreamConfig); - goto VERIFY_ERROR; - break; - } - - switch (config_list[i].iRef) { - case ME_REF_AI_GROUND: //SINGLE ENDED -/* - // ME4600_AI_LIST_INPUT_SINGLE_ENDED = 0x0000 - // 'entry |= ME4600_AI_LIST_INPUT_SINGLE_ENDED' ==> Do nothing. Removed. - entry |= ME4600_AI_LIST_INPUT_SINGLE_ENDED; -*/ break; - case ME_REF_AI_DIFFERENTIAL: //DIFFERENTIAL - entry |= ME4600_AI_LIST_INPUT_DIFFERENTIAL; - break; - default: - PERROR_CRITICAL("UNCHECK ERROR in config_list!\n"); - PERROR_CRITICAL - ("WRONG reference\nPosition:%d Reference:0x%04X\n", - i, config_list[i].iRef); - goto VERIFY_ERROR; - break; - } - - //Add last entry flag - if (i == (count - 1)) { - entry |= ME4600_AI_LIST_LAST_ENTRY; - } - - outl(entry, instance->channel_list_reg); - PDEBUG_REG("channel_list_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->channel_list_reg - instance->reg_base, - entry); - } - - // Set triggering registers - --acq_ticks; - outl(acq_ticks, instance->chan_pre_timer_reg); - PDEBUG_REG("chan_pre_timer_reg outl(0x%lX+0x%lX)=0x%llX\n", - instance->reg_base, - instance->chan_pre_timer_reg - instance->reg_base, - acq_ticks); - outl(acq_ticks, instance->scan_pre_timer_low_reg); - PDEBUG_REG("scan_pre_timer_low_reg outl(0x%lX+0x%lX)=0x%llX\n", - instance->reg_base, - instance->scan_pre_timer_low_reg - instance->reg_base, - acq_ticks & 0xFFFFFFFF); - outl((acq_ticks >> 32), instance->scan_pre_timer_high_reg); - PDEBUG_REG("scan_pre_timer_high_reg outl(0x%lX+0x%lX)=0x%llX\n", - instance->reg_base, - instance->scan_pre_timer_high_reg - instance->reg_base, - (acq_ticks >> 32) & 0xFFFFFFFF); - - // Set triggers - switch (trigger->iAcqStartTrigType) { - // Internal - case ME_TRIG_TYPE_SW: - // Nothing to set. - break; - - // External - case ME_TRIG_TYPE_EXT_ANALOG: - ctrl |= ME4600_AI_CTRL_BIT_EX_TRIG_ANALOG; - case ME_TRIG_TYPE_EXT_DIGITAL: - ctrl |= ME4600_AI_CTRL_BIT_EX_TRIG; - - // External trigger needs edge's definition - switch (trigger->iAcqStartTrigEdge) { - case ME_TRIG_EDGE_RISING: - // Nothing to set. - break; - - case ME_TRIG_EDGE_FALLING: - ctrl |= ME4600_AI_CTRL_BIT_EX_TRIG_FALLING; - break; - - case ME_TRIG_EDGE_ANY: - ctrl |= - ME4600_AI_CTRL_BIT_EX_TRIG_FALLING | - ME4600_AI_CTRL_BIT_EX_TRIG_BOTH; - break; - - default: - PERROR_CRITICAL - ("UNCHECK TRIGGER EDGE in triggers structure!\n"); - PERROR_CRITICAL - ("WRONG acquisition start trigger:0x%04X.\n", - trigger->iAcqStartTrigEdge); - err = ME_ERRNO_INVALID_ACQ_START_TRIG_EDGE; - goto VERIFY_ERROR; - break; - } - break; - - default: - PERROR_CRITICAL("UNCHECK TRIGGER in triggers structure!\n"); - PERROR_CRITICAL("WRONG acquisition start trigger:0x%04X.\n", - trigger->iAcqStartTrigType); - err = ME_ERRNO_INVALID_ACQ_START_TRIG_TYPE; - goto VERIFY_ERROR; - break; - } - - switch (trigger->iScanStartTrigType) { - case ME_TRIG_TYPE_TIMER: - --scan_ticks; - outl(scan_ticks, instance->scan_timer_low_reg); - PDEBUG_REG("scan_timer_low_reg outl(0x%lX+0x%lX)=0x%llX\n", - instance->reg_base, - instance->scan_timer_low_reg - instance->reg_base, - scan_ticks & 0xFFFFFFFF); - outl((scan_ticks >> 32), instance->scan_timer_high_reg); - PDEBUG_REG("scan_timer_high_reg outl(0x%lX+0x%lX)=0x%llX\n", - instance->reg_base, - instance->scan_timer_high_reg - instance->reg_base, - (scan_ticks >> 32) & 0xFFFFFFFF); - - if (trigger->iAcqStartTrigType == ME_TRIG_TYPE_SW) { - ctrl |= ME4600_AI_CTRL_BIT_MODE_0; - } else { - ctrl |= ME4600_AI_CTRL_BIT_MODE_1; - } - break; - - case ME_TRIG_TYPE_EXT_DIGITAL: - case ME_TRIG_TYPE_EXT_ANALOG: - outl(0, instance->scan_timer_low_reg); - PDEBUG_REG("scan_timer_low_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->scan_timer_low_reg - instance->reg_base, - 0); - outl(0, instance->scan_timer_high_reg); - PDEBUG_REG("scan_timer_high_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->scan_timer_high_reg - instance->reg_base, - 0); - ctrl |= ME4600_AI_CTRL_BIT_MODE_2; - break; - - case ME_TRIG_TYPE_FOLLOW: - outl(0, instance->scan_timer_low_reg); - PDEBUG_REG("scan_timer_low_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->scan_timer_low_reg - instance->reg_base, - 0); - outl(0, instance->scan_timer_high_reg); - PDEBUG_REG("scan_timer_high_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->scan_timer_high_reg - instance->reg_base, - 0); - - if (trigger->iAcqStartTrigType == ME_TRIG_TYPE_SW) { - ctrl |= ME4600_AI_CTRL_BIT_MODE_0; - } else { - ctrl |= ME4600_AI_CTRL_BIT_MODE_1; - } - break; - - default: - PERROR_CRITICAL("UNCHECK TRIGGER in triggers structure!\n"); - PERROR_CRITICAL("WRONG scan start trigger:0x%04X.\n", - trigger->iScanStartTrigType); - err = ME_ERRNO_INVALID_SCAN_START_TRIG_TYPE; - goto VERIFY_ERROR; - break; - } - - switch (trigger->iConvStartTrigType) { - - case ME_TRIG_TYPE_TIMER: - --conv_ticks; - outl(conv_ticks, instance->chan_timer_reg); - PDEBUG_REG("chan_timer_reg outl(0x%lX+0x%lX)=0x%llX\n", - instance->reg_base, - instance->chan_timer_reg - instance->reg_base, - conv_ticks); - break; - - case ME_TRIG_TYPE_EXT_DIGITAL: - case ME_TRIG_TYPE_EXT_ANALOG: - outl(0, instance->chan_timer_reg); - PDEBUG_REG("chan_timer_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->chan_timer_reg - instance->reg_base, 0); - ctrl |= ME4600_AI_CTRL_BIT_MODE_0 | ME4600_AI_CTRL_BIT_MODE_1; - break; - - default: - PERROR_CRITICAL("UNCHECK TRIGGER in triggers structure!\n"); - PERROR_CRITICAL("WRONG conv start trigger:0x%04X.\n", - trigger->iConvStartTrigType); - err = ME_ERRNO_INVALID_CONV_START_TRIG_TYPE; - goto VERIFY_ERROR; - - break; - } - - //Sample & Hold feature - if (flags & ME_IO_STREAM_CONFIG_SAMPLE_AND_HOLD) { - if (instance->sh) { - ctrl |= ME4600_AI_CTRL_BIT_SAMPLE_HOLD; - } else { - PERROR_CRITICAL("UNCHECK S&H feature!\n"); - err = ME_ERRNO_INVALID_FLAGS; - goto VERIFY_ERROR; - } - } - //Enable IRQs sources but leave latches blocked. - ctrl |= (ME4600_AI_CTRL_BIT_HF_IRQ | ME4600_AI_CTRL_BIT_SC_IRQ | ME4600_AI_CTRL_BIT_LE_IRQ); //The last IRQ source (ME4600_AI_CTRL_BIT_LE_IRQ) is unused! - - //Everything is good. Finalize - spin_lock_irqsave(instance->ctrl_reg_lock, cpu_flags); - tmp = inl(instance->ctrl_reg); - - //Preserve EXT IRQ and OFFSET settings. Clean other bits. - tmp &= - (ME4600_AI_CTRL_BIT_EX_IRQ | ME4600_AI_CTRL_BIT_EX_IRQ_RESET | - ME4600_AI_CTRL_BIT_FULLSCALE | ME4600_AI_CTRL_BIT_OFFSET); - - // write the control word - outl(ctrl | tmp, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->ctrl_reg - instance->reg_base, ctrl | tmp); - spin_unlock_irqrestore(instance->ctrl_reg_lock, cpu_flags); - - //Set the global parameters end exit. - instance->chan_list_len = count; - instance->fifo_irq_threshold = fifo_irq_threshold; - - if (trigger->iAcqStopTrigType == ME_TRIG_TYPE_COUNT) { - data_required = - (unsigned long long)trigger->iAcqStopCount * - (unsigned long long)count; - if (data_required > UINT_MAX) - data_required = UINT_MAX; - instance->data_required = (unsigned int)data_required; - } else if (trigger->iScanStopTrigType == ME_TRIG_TYPE_COUNT) - instance->data_required = - (unsigned long long)trigger->iScanStopCount; - else - instance->data_required = 0; - - // Mark subdevice as configured to work in stream mode. - instance->status = ai_status_stream_configured; - - // Deinit single config. Set all entries to NOT_CONFIGURED. - for (i = 0; i < instance->channels; i++) { - instance->single_config[i].status = - ME_SINGLE_CHANNEL_NOT_CONFIGURED; - } - -VERIFY_ERROR: // Error in code. Wrong setting check. This should never ever happend! - spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); -ERROR: // Error in settings. - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me4600_ai_io_stream_new_values(me_subdevice_t *subdevice, - struct file *filep, - int time_out, int *count, int flags) -{ - me4600_ai_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - unsigned long t; - unsigned long j; - int volatile head; - - PDEBUG("executed. idx=0\n"); - - if (flags) { - PERROR("Invalid flag specified.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - if (time_out < 0) { - PERROR("Invalid time_out specified.\n"); - return ME_ERRNO_INVALID_TIMEOUT; - } - - if (time_out) { - t = (time_out * HZ) / 1000; - - if (t == 0) - t = 1; - } else { // Max time. - t = LONG_MAX; - } - - instance = (me4600_ai_subdevice_t *) subdevice; - - ME_SUBDEVICE_ENTER; - - j = jiffies; - - while (1) { - // Only runing device can generate break. - head = instance->circ_buf.head; - wait_event_interruptible_timeout(instance->wait_queue, - ((head != - instance->circ_buf.head) - || - ((instance->status <= - ai_status_stream_run_wait) - && (instance->status >= - ai_status_stream_end_wait))), - t); - - if (head != instance->circ_buf.head) { // New data in buffer. - break; - } else if (instance->status == ai_status_stream_end) { // End of work. - break; - } else if (instance->status == ai_status_stream_fifo_error) { - err = ME_ERRNO_FIFO_BUFFER_OVERFLOW; - break; - } else if (instance->status == ai_status_stream_buffer_error) { - err = ME_ERRNO_RING_BUFFER_OVERFLOW; - break; - } else if (instance->status == ai_status_stream_error) { - err = ME_ERRNO_INTERNAL; - break; - } else if ((jiffies - j) >= t) { - PERROR("Wait on values timed out.\n"); - err = ME_ERRNO_TIMEOUT; - break; - } else if (signal_pending(current)) { - PERROR("Wait on values interrupted from signal.\n"); - err = ME_ERRNO_SIGNAL; - break; - } - // Correct timeout. - t -= jiffies - j; - } - - *count = me_circ_buf_values(&instance->circ_buf); - - ME_SUBDEVICE_EXIT; - - return err; -} - -static inline int me4600_ai_io_stream_read_get_value(me4600_ai_subdevice_t * - instance, int *values, - const int count, - const int flags) -{ - int n; - int i; - uint32_t value; - - ///Checking how many datas can be copied. - n = me_circ_buf_values(&instance->circ_buf); - if (n <= 0) - return 0; - - if (n > count) - n = count; - - if (flags & ME_IO_STREAM_READ_FRAMES) { - if (n < instance->chan_list_len) //Not enough data! - return 0; - n -= n % instance->chan_list_len; - } - - for (i = 0; i < n; i++) { - value = *(instance->circ_buf.buf + instance->circ_buf.tail); - if (put_user(value, values + i)) { - PERROR("Cannot copy new values to user.\n"); - return -ME_ERRNO_INTERNAL; - } - instance->circ_buf.tail++; - instance->circ_buf.tail &= instance->circ_buf.mask; - } - return n; -} - -static int me4600_ai_io_stream_read(me_subdevice_t *subdevice, - struct file *filep, - int read_mode, - int *values, int *count, int flags) -{ - me4600_ai_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - int ret; - - int c = *count; - int min = c; - - PDEBUG("executed. idx=0\n"); - - if (flags & ~ME_IO_STREAM_READ_FRAMES) { - PERROR("Invalid flag specified.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - if (!values || !count) { - PERROR("Request has invalid pointer.\n"); - return ME_ERRNO_INVALID_POINTER; - } - - if (c < 0) { - PERROR("Request has invalid value's counter.\n"); - return ME_ERRNO_INVALID_VALUE_COUNT; - } - - if ((read_mode != ME_READ_MODE_BLOCKING) - && (read_mode != ME_READ_MODE_NONBLOCKING)) { - PERROR("Invalid read mode specified.\n"); - return ME_ERRNO_INVALID_READ_MODE; - } - - if (c == 0) { //You get what you want! Nothing more or less. - return ME_ERRNO_SUCCESS; - } - - instance = (me4600_ai_subdevice_t *) subdevice; - ME_SUBDEVICE_ENTER; - - //Check if subdevice is configured. - if (instance->chan_list_len <= 0) { - PERROR("Subdevice wasn't configured.\n"); - ME_SUBDEVICE_EXIT; - return ME_ERRNO_PREVIOUS_CONFIG; - } - - if (flags & ME_IO_STREAM_READ_FRAMES) { - if (c < instance->chan_list_len) { //Not enough data requested. - PERROR - ("When using FRAME_READ mode minimal size is defined by channel list.\n"); - ME_SUBDEVICE_EXIT; - return ME_ERRNO_INVALID_VALUE_COUNT; - } - } - - if (c > (ME4600_AI_CIRC_BUF_COUNT - instance->chan_list_len)) { // To return acceptable amount of data when user pass too big value. - min = ME4600_AI_CIRC_BUF_COUNT - instance->chan_list_len; - } - - if (flags & ME_IO_STREAM_READ_FRAMES) { - //Wait for whole list. - if (read_mode == ME_READ_MODE_BLOCKING) { - min = c - (c % instance->chan_list_len); - } - - if (read_mode == ME_READ_MODE_NONBLOCKING) { - min = instance->chan_list_len; - } - } - - if ((inl(instance->status_reg) & ME4600_AI_STATUS_BIT_FSM)) { //Working - //If blocking mode -> wait for data. - if ((me_circ_buf_values(&instance->circ_buf) < min) - && (read_mode == ME_READ_MODE_BLOCKING)) { - wait_event_interruptible(instance->wait_queue, - ((me_circ_buf_values - (&instance->circ_buf) >= min) - || !(inl(instance->status_reg) - & - ME4600_AI_STATUS_BIT_FSM))); - - if (signal_pending(current)) { - PERROR - ("Wait on values interrupted from signal.\n"); - err = ME_ERRNO_SIGNAL; - } - } - } - - ret = me4600_ai_io_stream_read_get_value(instance, values, c, flags); - if (ret < 0) { - err = -ret; - *count = 0; - } else if (ret == 0) { - *count = 0; - if (instance->status == ai_status_stream_fifo_error) { - err = ME_ERRNO_FIFO_BUFFER_OVERFLOW; - instance->status = ai_status_stream_end; - } else if (instance->status == ai_status_stream_buffer_error) { - err = ME_ERRNO_RING_BUFFER_OVERFLOW; - instance->status = ai_status_stream_end; - } else if (instance->status == ai_status_stream_end) { - err = ME_ERRNO_SUBDEVICE_NOT_RUNNING; - } else if (instance->status == ai_status_stream_error) { - err = ME_ERRNO_INTERNAL; - } else if (instance->status == ai_status_none) { - PDEBUG("Stream canceled.\n"); - err = ME_ERRNO_INTERNAL; - } - } else { - *count = ret; - } - - ME_SUBDEVICE_EXIT; - - return err; -} - -/** @brief Stop aqusation. Preserve FIFOs. -* -* @param instance The subdevice instance (pointer). -*/ - -static int ai_stop_immediately(me4600_ai_subdevice_t *instance) -{ - unsigned long cpu_flags = 0; - volatile uint32_t ctrl; - const int timeout = HZ / 10; //100ms - int i; - - for (i = 0; i <= timeout; i++) { - spin_lock_irqsave(instance->ctrl_reg_lock, cpu_flags); - ctrl = inl(instance->ctrl_reg); - ctrl &= ~ME4600_AI_CTRL_BIT_STOP; - ctrl |= - (ME4600_AI_CTRL_BIT_IMMEDIATE_STOP | - ME4600_AI_CTRL_BIT_HF_IRQ_RESET | - ME4600_AI_CTRL_BIT_SC_IRQ_RESET); - outl(ctrl, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ctrl_reg - instance->reg_base, ctrl); - spin_unlock_irqrestore(instance->ctrl_reg_lock, cpu_flags); - - if (!(inl(instance->status_reg) & ME4600_AI_STATUS_BIT_FSM)) { // Exit. - break; - } - - PINFO("Wait for stop: %d\n", i + 1); - //Still working! - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1); - } - - if (i > timeout) { - PERROR_CRITICAL("FSM IS BUSY!\n"); - return ME_ERRNO_INTERNAL; - } - - return ME_ERRNO_SUCCESS; -} - -static int me4600_ai_io_stream_start(me_subdevice_t *subdevice, - struct file *filep, - int start_mode, int time_out, int flags) -{ - me4600_ai_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - unsigned long cpu_flags = 0; - unsigned long ref; - unsigned long delay = 0; - - volatile uint32_t tmp; - - PDEBUG("executed. idx=0\n"); - - instance = (me4600_ai_subdevice_t *) subdevice; - - if (flags) { - PERROR("Invalid flag specified.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - if ((start_mode != ME_START_MODE_BLOCKING) - && (start_mode != ME_START_MODE_NONBLOCKING)) { - PERROR("Invalid start mode specified.\n"); - return ME_ERRNO_INVALID_START_MODE; - } - - if (time_out < 0) { - PERROR("Invalid timeout specified.\n"); - return ME_ERRNO_INVALID_TIMEOUT; - } - - if (time_out) { - delay = (time_out * HZ) / 1000; - - if (delay == 0) - delay = 1; - } - - ME_SUBDEVICE_ENTER - spin_lock_irqsave(instance->ctrl_reg_lock, cpu_flags); - - tmp = inl(instance->ctrl_reg); - - if ((tmp & ME4600_AI_STATUS_BIT_FSM)) { - PERROR("Conversion is already running.\n"); - spin_unlock_irqrestore(instance->ctrl_reg_lock, cpu_flags); - err = ME_ERRNO_SUBDEVICE_BUSY; - goto ERROR; - } - - if (instance->chan_list_len == 0) { //Not configured! - PERROR("Subdevice is not configured to work in stream mode!\n"); - spin_unlock_irqrestore(instance->ctrl_reg_lock, cpu_flags); - err = ME_ERRNO_PREVIOUS_CONFIG; - goto ERROR; - } - - if (!(tmp & (ME4600_AI_CTRL_BIT_MODE_0 | ME4600_AI_CTRL_BIT_MODE_1 | ME4600_AI_CTRL_BIT_MODE_2))) { //Mode 0 = single work => no stream config - PERROR("Subdevice is configured to work in single mode.\n"); - spin_unlock_irqrestore(instance->ctrl_reg_lock, cpu_flags); - err = ME_ERRNO_PREVIOUS_CONFIG; - goto ERROR; - } - //Reset stop bits. - tmp |= ME4600_AI_CTRL_BIT_IMMEDIATE_STOP | ME4600_AI_CTRL_BIT_STOP; - outl(tmp, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->ctrl_reg - instance->reg_base, tmp); - - //Start datas' FIFO. - tmp |= ME4600_AI_CTRL_BIT_DATA_FIFO; - //Free stop bits. - tmp &= ~(ME4600_AI_CTRL_BIT_IMMEDIATE_STOP | ME4600_AI_CTRL_BIT_STOP); - outl(tmp, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->ctrl_reg - instance->reg_base, tmp); - spin_unlock_irqrestore(instance->ctrl_reg_lock, cpu_flags); - - //Cancel control task - PDEBUG("Cancel control task.\n"); - instance->ai_control_task_flag = 0; - cancel_delayed_work(&instance->ai_control_task); - - //Set the starting values. - instance->ISM.global_read = 0; - instance->ISM.read = 0; - //Clear circular buffer - instance->circ_buf.head = 0; - instance->circ_buf.tail = 0; - - //Set everything. - ai_data_acquisition_logic(instance); - - //Set status to 'wait for start' - instance->status = ai_status_stream_run_wait; - - // Set control task's timeout - instance->timeout.delay = delay; - instance->timeout.start_time = jiffies; - - //Lets go! Start work - inl(instance->start_reg); - PDEBUG_REG("start_reg inl(0x%lX+0x%lX)\n", instance->reg_base, - instance->start_reg - instance->reg_base); - - // Schedule control task - instance->ai_control_task_flag = 1; - queue_delayed_work(instance->me4600_workqueue, - &instance->ai_control_task, 1); - - PDEVELOP("Delay:%ld\n", delay); - - if (start_mode == ME_START_MODE_BLOCKING) { //Wait for start. - ref = jiffies; - //Only runing process will interrupt this call. Events are signaled when status change. Extra timeout add for safe reason. - wait_event_interruptible_timeout(instance->wait_queue, - (instance->status != - ai_status_stream_run_wait), - (delay) ? delay + - 1 : LONG_MAX); - - if ((instance->status != ai_status_stream_run) - && (instance->status != ai_status_stream_end)) { - PDEBUG("Starting stream canceled. %d\n", - instance->status); - err = ME_ERRNO_CANCELLED; - } - - if (signal_pending(current)) { - PERROR("Wait on start of state machine interrupted.\n"); - instance->status = ai_status_none; - ai_stop_isr(instance); - err = ME_ERRNO_SIGNAL; - } else if ((delay) && ((jiffies - ref) > delay)) { - if (instance->status != ai_status_stream_run) { - if (instance->status == ai_status_stream_end) { - PDEBUG("Timeout reached.\n"); - } else if ((jiffies - ref) > delay + 1) { - PERROR - ("Timeout reached. Not handled by control task!\n"); - ai_stop_isr(instance); - instance->status = - ai_status_stream_error; - } else { - PERROR - ("Timeout reached. Signal come but status is strange: %d\n", - instance->status); - ai_stop_isr(instance); - instance->status = - ai_status_stream_error; - } - - instance->ai_control_task_flag = 0; - cancel_delayed_work(&instance->ai_control_task); - err = ME_ERRNO_TIMEOUT; - } - } - } -#ifdef MEDEBUG_INFO - tmp = inl(instance->ctrl_reg); - PDEBUG_REG("ctrl_reg inl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->ctrl_reg - instance->reg_base, tmp); - - PINFO("STATUS_BIT_FSM=%s.\n", - (tmp & ME4600_AI_STATUS_BIT_FSM) ? "on" : "off"); - PINFO("CTRL_BIT_HF_IRQ=%s.\n", - (tmp & ME4600_AI_CTRL_BIT_HF_IRQ) ? "enable" : "disable"); - PINFO("CTRL_BIT_HF_IRQ_RESET=%s.\n", - (tmp & ME4600_AI_CTRL_BIT_HF_IRQ_RESET) ? "reset" : "work"); - PINFO("CTRL_BIT_SC_IRQ=%s.\n", - (tmp & ME4600_AI_CTRL_BIT_SC_IRQ) ? "enable" : "disable"); - PINFO("CTRL_BIT_SC_RELOAD=%s.\n", - (tmp & ME4600_AI_CTRL_BIT_SC_RELOAD) ? "on" : "off"); - PINFO("CTRL_BIT_SC_IRQ_RESET=%s.\n", - (tmp & ME4600_AI_CTRL_BIT_SC_IRQ_RESET) ? "reset" : "work"); -#endif - -ERROR: - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me4600_ai_io_stream_status(me_subdevice_t *subdevice, - struct file *filep, - int wait, - int *status, int *values, int flags) -{ - me4600_ai_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - - PDEBUG("executed. idx=0\n"); - - instance = (me4600_ai_subdevice_t *) subdevice; - - if (flags) { - PERROR("Invalid flag specified.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - ME_SUBDEVICE_ENTER; - - switch (instance->status) { - case ai_status_single_configured: - case ai_status_stream_configured: - case ai_status_stream_end: - case ai_status_stream_fifo_error: - case ai_status_stream_buffer_error: - case ai_status_stream_error: - *status = ME_STATUS_IDLE; - break; - - case ai_status_stream_run_wait: - case ai_status_stream_run: - case ai_status_stream_end_wait: - *status = ME_STATUS_BUSY; - break; - - case ai_status_none: - default: - *status = - (inl(instance->status_reg) & ME4600_AI_STATUS_BIT_FSM) ? - ME_STATUS_BUSY : ME_STATUS_IDLE; - break; - } - - if ((wait == ME_WAIT_IDLE) && (*status == ME_STATUS_BUSY)) { - // Only runing process will interrupt this call. Events are signaled when status change. Extra timeout add for safe reason. - wait_event_interruptible_timeout(instance->wait_queue, - ((instance->status != - ai_status_stream_run_wait) - && (instance->status != - ai_status_stream_run) - && (instance->status != - ai_status_stream_end_wait)), - LONG_MAX); - - if (instance->status != ai_status_stream_end) { - PDEBUG("Wait for IDLE canceled. %d\n", - instance->status); - err = ME_ERRNO_CANCELLED; - } - - if (signal_pending(current)) { - PERROR("Wait for IDLE interrupted.\n"); - instance->status = ai_status_none; - ai_stop_isr(instance); - err = ME_ERRNO_SIGNAL; - } - - *status = ME_STATUS_IDLE; - } - - *values = me_circ_buf_values(&instance->circ_buf); - PDEBUG("me_circ_buf_values(&instance->circ_buf)=%d.\n", *values); - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me4600_ai_io_stream_stop(me_subdevice_t *subdevice, - struct file *filep, - int stop_mode, int flags) -{ -/** - @note Stop is implemented only in blocking mode. - @note Function return when state machine is stoped. -*/ - me4600_ai_subdevice_t *instance; - unsigned long cpu_flags; - uint32_t ctrl; - int ret; - - PDEBUG("executed. idx=0\n"); - - if (flags) { - PERROR("Invalid flag specified.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - if ((stop_mode != ME_STOP_MODE_IMMEDIATE) - && (stop_mode != ME_STOP_MODE_LAST_VALUE)) { - PERROR("Invalid stop mode specified.\n"); - return ME_ERRNO_INVALID_STOP_MODE; - } - - instance = (me4600_ai_subdevice_t *) subdevice; - - ME_SUBDEVICE_ENTER; - - // Mark as stopping. => Software stop. - instance->status = ai_status_stream_end_wait; - - if (stop_mode == ME_STOP_MODE_IMMEDIATE) { - ret = ai_stop_immediately(instance); - - if (ret) { - PERROR("FSM is still busy.\n"); - ME_SUBDEVICE_EXIT; - return ME_ERRNO_SUBDEVICE_BUSY; - } - instance->ai_control_task_flag = 0; - - } else if (stop_mode == ME_STOP_MODE_LAST_VALUE) { - // Set stop bit in registry. - spin_lock_irqsave(instance->ctrl_reg_lock, cpu_flags); - ctrl = inl(instance->ctrl_reg); - ctrl |= ME4600_AI_CTRL_BIT_STOP; - outl(ctrl, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ctrl_reg - instance->reg_base, ctrl); - spin_unlock_irqrestore(instance->ctrl_reg_lock, cpu_flags); - - // Only runing process will interrupt this call. Events are signaled when status change. - wait_event_interruptible_timeout(instance->wait_queue, - (instance->status != - ai_status_stream_end_wait), - LONG_MAX); - - if (instance->status != ai_status_stream_end) { - PDEBUG("Stopping stream canceled.\n"); - ret = ME_ERRNO_CANCELLED; - } - - if (signal_pending(current)) { - PERROR("Stopping stream interrupted.\n"); - instance->status = ai_status_none; - ret = ME_ERRNO_SIGNAL; - } - // End of work. - ai_stop_immediately(instance); - - } - - ret = ai_read_data_pooling(instance); - if (ret > 0) { // Everything fine. More datas put to software buffer. - instance->status = ai_status_stream_end; - ret = ME_ERRNO_SUCCESS; - // Signal that we put last data to software buffer. - wake_up_interruptible_all(&instance->wait_queue); - } else if (ret == 0) { // Everything fine. No more datas in FIFO. - instance->status = ai_status_stream_end; - ret = ME_ERRNO_SUCCESS; - } else if (ret == -ME_ERRNO_RING_BUFFER_OVERFLOW) { // Stop is unsuccessful, buffer is overflow. - instance->status = ai_status_stream_buffer_error; - ret = ME_ERRNO_SUCCESS; - } else { // Stop is unsuccessful - instance->status = ai_status_stream_end; - ret = -ret; - } - - ME_SUBDEVICE_EXIT; - - return ret; -} - -static int me4600_ai_query_range_by_min_max(me_subdevice_t *subdevice, - int unit, - int *min, - int *max, int *maxdata, int *range) -{ - me4600_ai_subdevice_t *instance; - int i; - int r = -1; - int diff = 21E6; - - PDEBUG("executed. idx=0\n"); - - instance = (me4600_ai_subdevice_t *) subdevice; - - if ((*max - *min) < 0) { - PERROR("Invalid minimum and maximum values specified.\n"); - return ME_ERRNO_INVALID_MIN_MAX; - } - - if ((unit == ME_UNIT_VOLT) || (unit == ME_UNIT_ANY)) { - for (i = 0; i < instance->ranges_len; i++) { - if ((instance->ranges[i].min <= *min) - && ((instance->ranges[i].max + 1000) >= *max)) { - if ((instance->ranges[i].max - - instance->ranges[i].min) - (*max - *min) < - diff) { - r = i; - diff = - (instance->ranges[i].max - - instance->ranges[i].min) - (*max - - *min); - } - } - } - - if (r < 0) { - PERROR("No matching range found.\n"); - return ME_ERRNO_NO_RANGE; - } else { - *min = instance->ranges[r].min; - *max = instance->ranges[r].max; - *maxdata = ME4600_AI_MAX_DATA; - *range = r; - } - } else { - PERROR("Invalid physical unit specified.\n"); - return ME_ERRNO_INVALID_UNIT; - } - - return ME_ERRNO_SUCCESS; -} - -static int me4600_ai_query_number_ranges(me_subdevice_t *subdevice, - int unit, int *count) -{ - me4600_ai_subdevice_t *instance; - - PDEBUG("executed. idx=0\n"); - - instance = (me4600_ai_subdevice_t *) subdevice; - - if ((unit == ME_UNIT_VOLT) || (unit == ME_UNIT_ANY)) { - *count = instance->ranges_len; - } else { - *count = 0; - } - - return ME_ERRNO_SUCCESS; -} - -static int me4600_ai_query_range_info(me_subdevice_t *subdevice, - int range, - int *unit, - int *min, int *max, int *maxdata) -{ - me4600_ai_subdevice_t *instance; - - PDEBUG("executed. idx=0\n"); - - instance = (me4600_ai_subdevice_t *) subdevice; - - if ((range < instance->ranges_len) && (range >= 0)) { - *unit = ME_UNIT_VOLT; - *min = instance->ranges[range].min; - *max = instance->ranges[range].max; - *maxdata = ME4600_AI_MAX_DATA; - } else { - PERROR("Invalid range number specified.\n"); - return ME_ERRNO_INVALID_RANGE; - } - - return ME_ERRNO_SUCCESS; -} - -static int me4600_ai_query_timer(me_subdevice_t *subdevice, - int timer, - int *base_frequency, - long long *min_ticks, long long *max_ticks) -{ - me4600_ai_subdevice_t *instance; - - PDEBUG("executed. idx=0\n"); - - instance = (me4600_ai_subdevice_t *) subdevice; - - switch (timer) { - - case ME_TIMER_ACQ_START: - *base_frequency = ME4600_AI_BASE_FREQUENCY; - *min_ticks = ME4600_AI_MIN_ACQ_TICKS; - *max_ticks = ME4600_AI_MAX_ACQ_TICKS; - break; - - case ME_TIMER_SCAN_START: - *base_frequency = ME4600_AI_BASE_FREQUENCY; - *min_ticks = ME4600_AI_MIN_SCAN_TICKS; - *max_ticks = ME4600_AI_MAX_SCAN_TICKS; - break; - - case ME_TIMER_CONV_START: - *base_frequency = ME4600_AI_BASE_FREQUENCY; - *min_ticks = ME4600_AI_MIN_CHAN_TICKS; - *max_ticks = ME4600_AI_MAX_CHAN_TICKS; - break; - - default: - PERROR("Invalid timer specified.(0x%04x)\n", timer); - - return ME_ERRNO_INVALID_TIMER; - } - - return ME_ERRNO_SUCCESS; -} - -static int me4600_ai_query_number_channels(me_subdevice_t *subdevice, - int *number) -{ - me4600_ai_subdevice_t *instance; - - PDEBUG("executed. idx=0\n"); - - instance = (me4600_ai_subdevice_t *) subdevice; - *number = instance->channels; - - return ME_ERRNO_SUCCESS; -} - -static int me4600_ai_query_subdevice_type(me_subdevice_t *subdevice, - int *type, int *subtype) -{ - PDEBUG("executed. idx=0\n"); - - *type = ME_TYPE_AI; - *subtype = ME_SUBTYPE_STREAMING; - - return ME_ERRNO_SUCCESS; -} - -static int me4600_ai_query_subdevice_caps(me_subdevice_t *subdevice, int *caps) -{ - PDEBUG("executed. idx=0\n"); - - *caps = - ME_CAPS_AI_TRIG_SYNCHRONOUS | ME_CAPS_AI_FIFO | - ME_CAPS_AI_FIFO_THRESHOLD; - - return ME_ERRNO_SUCCESS; -} - -static int me4600_ai_query_subdevice_caps_args(struct me_subdevice *subdevice, - int cap, int *args, int count) -{ - me4600_ai_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - - instance = (me4600_ai_subdevice_t *) subdevice; - - PDEBUG("executed. idx=0\n"); - - if (count != 1) { - PERROR("Invalid capability argument count.\n"); - return ME_ERRNO_INVALID_CAP_ARG_COUNT; - } - - switch (cap) { - case ME_CAP_AI_FIFO_SIZE: - args[0] = ME4600_AI_FIFO_COUNT; - break; - - case ME_CAP_AI_BUFFER_SIZE: - args[0] = - (instance->circ_buf.buf) ? ME4600_AI_CIRC_BUF_COUNT : 0; - break; - - default: - PERROR("Invalid capability.\n"); - err = ME_ERRNO_INVALID_CAP; - args[0] = 0; - } - - return err; -} - -void ai_limited_isr(me4600_ai_subdevice_t *instance, const uint32_t irq_status, - const uint32_t ctrl_status) -{ - int to_read; - - if (!instance->fifo_irq_threshold) { //No threshold provided. SC ends work. HF need reseting. - if (irq_status & ME4600_IRQ_STATUS_BIT_SC) { - if (ai_read_data(instance, instance->ISM.next) != instance->ISM.next) { //ERROR! - PERROR - ("Limited amounts aqusition with TH=0: Circular buffer full!\n"); - instance->status = - ai_status_stream_buffer_error; - } else { - instance->status = ai_status_stream_end; - } - //End of work. - ai_stop_isr(instance); - } else if (irq_status & ME4600_IRQ_STATUS_BIT_AI_HF) { - instance->ISM.global_read += ME4600_AI_FIFO_HALF; - - if (ai_read_data(instance, ME4600_AI_FIFO_HALF) != ME4600_AI_FIFO_HALF) { //ERROR! - PERROR - ("Limited amounts aqusition with TH = 0: Circular buffer full!\n"); - //End of work. - ai_stop_isr(instance); - instance->status = - ai_status_stream_buffer_error; - } else { - //Continue. - ai_limited_ISM(instance, irq_status); - } - } - //Signal user. - wake_up_interruptible_all(&instance->wait_queue); - } else //if(instance->fifo_irq_threshold) - { - if (irq_status & ME4600_IRQ_STATUS_BIT_SC) { - instance->ISM.read = 0; - if ((instance->fifo_irq_threshold < ME4600_AI_FIFO_HALF) - && (!(ctrl_status & ME4600_AI_STATUS_BIT_HF_DATA))) - { - to_read = - ME4600_AI_FIFO_HALF - - (ME4600_AI_FIFO_HALF % - instance->fifo_irq_threshold); - PDEBUG - ("Limited amounts aqusition with TH != 0: Not fast enough data aqusition! correction=%d\n", - to_read); - } else { - to_read = instance->ISM.next; - } - instance->ISM.global_read += to_read; - - ai_reschedule_SC(instance); - - if (ai_read_data(instance, to_read) != to_read) { //ERROR! - PERROR - ("Limited amounts aqusition with TH != 0: Circular buffer full!\n"); - //End of work. - ai_stop_isr(instance); - instance->status = - ai_status_stream_buffer_error; - } else { - //Continue. - ai_limited_ISM(instance, irq_status); - } - - //Signal user. - wake_up_interruptible_all(&instance->wait_queue); - } else if (irq_status & ME4600_IRQ_STATUS_BIT_AI_HF) { - instance->ISM.read += ME4600_AI_FIFO_HALF; - instance->ISM.global_read += ME4600_AI_FIFO_HALF; - - if (ai_read_data(instance, ME4600_AI_FIFO_HALF) != ME4600_AI_FIFO_HALF) { //ERROR! - PERROR - ("Limited amounts aqusition with TH != 0: Circular buffer full!\n"); - ai_stop_isr(instance); - - instance->status = - ai_status_stream_buffer_error; - //Signal user. - wake_up_interruptible_all(&instance-> - wait_queue); - } else { - //Countinue. - ai_limited_ISM(instance, irq_status); - } - } - - if (instance->ISM.global_read >= instance->data_required) { //End of work. Next paranoid pice of code: '>=' instead od '==' only to be sure. - ai_stop_isr(instance); - if (instance->status < ai_status_stream_end) { - instance->status = ai_status_stream_end; - } -#ifdef MEDEBUG_ERROR - if (instance->ISM.global_read > instance->data_required) { //This is security check case. This should never ever happend! - PERROR - ("Limited amounts aqusition: Read more data than necessary! data_required=%d < read=%d\n", - instance->data_required, - instance->ISM.global_read); - //Signal error (warning??). - instance->status = ai_status_stream_error; - } -#endif - } - } -} - -void ai_infinite_isr(me4600_ai_subdevice_t *instance, - const uint32_t irq_status, const uint32_t ctrl_status) -{ - int to_read; - - if (irq_status & ME4600_IRQ_STATUS_BIT_SC) { //next chunck of data -> read fifo - //Set new state in ISM. - if ((instance->fifo_irq_threshold < ME4600_AI_FIFO_HALF) && (!(ctrl_status & ME4600_AI_STATUS_BIT_HF_DATA))) { //There is more data than we ecpected. Propably we aren't fast enough. Read as many as possible. - if (instance->fifo_irq_threshold) { - to_read = - ME4600_AI_FIFO_HALF - - (ME4600_AI_FIFO_HALF % - instance->fifo_irq_threshold); - if (to_read > instance->fifo_irq_threshold) { - PDEBUG - ("Infinite aqusition: Not fast enough data aqusition! TH != 0: correction=%d\n", - to_read); - } - } else { //No threshold specified. - to_read = ME4600_AI_FIFO_HALF; - } - } else { - to_read = instance->ISM.next; - } - - instance->ISM.read += to_read; - - //Get data - if (ai_read_data(instance, to_read) != to_read) { //ERROR! - PERROR("Infinite aqusition: Circular buffer full!\n"); - ai_stop_isr(instance); - instance->status = ai_status_stream_buffer_error; - } else { - ai_infinite_ISM(instance); - instance->ISM.global_read += instance->ISM.read; - instance->ISM.read = 0; - } - - //Signal data to user - wake_up_interruptible_all(&instance->wait_queue); - } else if (irq_status & ME4600_IRQ_STATUS_BIT_AI_HF) { //fifo is half full -> read fifo Large blocks only! - instance->ISM.read += ME4600_AI_FIFO_HALF; - - if (ai_read_data(instance, ME4600_AI_FIFO_HALF) != ME4600_AI_FIFO_HALF) { //ERROR! - PERROR("Infinite aqusition: Circular buffer full!\n"); - ai_stop_isr(instance); - instance->status = ai_status_stream_buffer_error; - - //Signal it. - wake_up_interruptible_all(&instance->wait_queue); - } else { - ai_infinite_ISM(instance); - } - } -} - -static irqreturn_t me4600_ai_isr(int irq, void *dev_id) -{ /// @note This is time critical function! - uint32_t irq_status; - uint32_t ctrl_status; - me4600_ai_subdevice_t *instance = dev_id; - //int to_read; - - PDEBUG("executed. idx=0\n"); - - if (irq != instance->irq) { - PERROR("Incorrect interrupt num: %d.\n", irq); - return IRQ_NONE; - } - - irq_status = inl(instance->irq_status_reg); - if (! - (irq_status & - (ME4600_IRQ_STATUS_BIT_AI_HF | ME4600_IRQ_STATUS_BIT_SC))) { -#ifdef MEDEBUG_INFO - if ((irq_status & (ME4600_IRQ_STATUS_BIT_AI_HF | ME4600_IRQ_STATUS_BIT_SC | ME4600_IRQ_STATUS_BIT_LE)) == ME4600_IRQ_STATUS_BIT_LE) { //This is security check case. LE is unused. This should never ever happend. - PINFO - ("%ld Shared interrupt. %s(): irq_status_reg=LE_IRQ\n", - jiffies, __func__); - } else { - PINFO - ("%ld Shared interrupt. %s(): irq_status_reg=0x%04X\n", - jiffies, __func__, irq_status); - } -#endif - return IRQ_NONE; - } - - if (!instance->circ_buf.buf) { //Security check. - PERROR_CRITICAL("CIRCULAR BUFFER NOT EXISTS!\n"); - ai_stop_isr(instance); - return IRQ_HANDLED; - } - //Get the status register. - ctrl_status = inl(instance->status_reg); - -#ifdef MEDEBUG_INFO - if (irq_status & ME4600_IRQ_STATUS_BIT_AI_HF) - PINFO("HF interrupt active\n"); - if (irq_status & ME4600_IRQ_STATUS_BIT_SC) - PINFO("SC interrupt active\n"); - if (irq_status & ME4600_IRQ_STATUS_BIT_LE) - PINFO("LE interrupt active\n"); -#endif - - //This is safety check! - if ((irq_status & ME4600_IRQ_STATUS_BIT_AI_HF) - && (ctrl_status & ME4600_AI_STATUS_BIT_HF_DATA)) { - PDEBUG("HF interrupt active but FIFO under half\n"); - //Reset HF interrupt latch. - spin_lock(instance->ctrl_reg_lock); - outl(ctrl_status | ME4600_AI_CTRL_BIT_HF_IRQ_RESET, - instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ctrl_reg - instance->reg_base, - ctrl_status); - outl(ctrl_status, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ctrl_reg - instance->reg_base, - ctrl_status); - spin_unlock(instance->ctrl_reg_lock); - return IRQ_HANDLED; - } -#ifdef MEDEBUG_INFO - PINFO("STATUS_BIT_FSM=%s.\n", - (ctrl_status & ME4600_AI_STATUS_BIT_FSM) ? "on" : "off"); - - PINFO("STATUS_BIT_EF_CHANNEL=%s.\n", - (ctrl_status & ME4600_AI_STATUS_BIT_EF_CHANNEL) ? "not empty" : - "empty"); - PINFO("STATUS_BIT_HF_CHANNEL=%s.\n", - (ctrl_status & ME4600_AI_STATUS_BIT_HF_CHANNEL) ? " < HF" : - " > HF"); - PINFO("STATUS_BIT_FF_CHANNEL=%s.\n", - (ctrl_status & ME4600_AI_STATUS_BIT_FF_CHANNEL) ? "not full" : - "full"); - - PINFO("STATUS_BIT_EF_DATA=%s.\n", - (ctrl_status & ME4600_AI_STATUS_BIT_EF_DATA) ? "not empty" : - "empty"); - PINFO("STATUS_BIT_HF_DATA=%s.\n", - (ctrl_status & ME4600_AI_STATUS_BIT_HF_DATA) ? " < HF" : " > HF"); - PINFO("STATUS_BIT_FF_DATA=%s.\n", - (ctrl_status & ME4600_AI_STATUS_BIT_FF_DATA) ? "not full" : - "full"); - - PINFO("CTRL_BIT_HF_IRQ=%s.\n", - (ctrl_status & ME4600_AI_CTRL_BIT_HF_IRQ) ? "enable" : "disable"); - PINFO("CTRL_BIT_HF_IRQ_RESET=%s.\n", - (ctrl_status & ME4600_AI_CTRL_BIT_HF_IRQ_RESET) ? "reset" : - "work"); - PINFO("CTRL_BIT_SC_IRQ=%s.\n", - (ctrl_status & ME4600_AI_CTRL_BIT_SC_IRQ) ? "enable" : "disable"); - PINFO("CTRL_BIT_SC_RELOAD=%s.\n", - (ctrl_status & ME4600_AI_CTRL_BIT_SC_RELOAD) ? "on" : "off"); - PINFO("CTRL_BIT_SC_IRQ_RESET=%s.\n", - (ctrl_status & ME4600_AI_CTRL_BIT_SC_IRQ_RESET) ? "reset" : - "work"); -#endif - - //Look for overflow error. - if (!(ctrl_status & ME4600_AI_STATUS_BIT_FF_DATA)) { - //FIFO is full. Read datas and reset all settings. - PERROR("FIFO overflow.\n"); - ai_read_data(instance, ME4600_AI_FIFO_COUNT); - ai_stop_isr(instance); - - instance->status = ai_status_stream_fifo_error; - //Signal it. - wake_up_interruptible_all(&instance->wait_queue); - - return IRQ_HANDLED; - } - - if (!instance->data_required) { //This is infinite aqusition. -#ifdef MEDEBUG_ERROR - if ((irq_status & - (ME4600_IRQ_STATUS_BIT_AI_HF | ME4600_IRQ_STATUS_BIT_SC)) - == - (ME4600_IRQ_STATUS_BIT_AI_HF | ME4600_IRQ_STATUS_BIT_SC)) { - ///In infinite mode only one interrupt source should be reported! - PERROR - ("Error in ISM! Infinite aqusition: HF and SC interrupts active! threshold=%d next=%d ctrl=0x%04X irq_status_reg=0x%04X", - instance->fifo_irq_threshold, instance->ISM.next, - ctrl_status, irq_status); - } -#endif - - ai_infinite_isr(instance, irq_status, ctrl_status); - -#ifdef MEDEBUG_INFO - ctrl_status = inl(instance->ctrl_reg); -#endif - } else { - - ai_limited_isr(instance, irq_status, ctrl_status); - ctrl_status = inl(instance->status_reg); - if (!(ctrl_status & (ME4600_AI_STATUS_BIT_HF_DATA | ME4600_AI_CTRL_BIT_HF_IRQ_RESET))) { //HF active, but we have more than half already => HF will never come - PDEBUG - ("MISSED HF. data_required=%d ISM.read=%d ISM.global=%d ISM.next=%d\n", - instance->data_required, instance->ISM.read, - instance->ISM.global_read, instance->ISM.next); - ai_limited_isr(instance, ME4600_IRQ_STATUS_BIT_AI_HF, - ctrl_status); - } - } - -#ifdef MEDEBUG_INFO - PINFO("STATUS_BIT_FSM=%s.\n", - (ctrl_status & ME4600_AI_STATUS_BIT_FSM) ? "on" : "off"); - - PINFO("STATUS_BIT_EF_CHANNEL=%s.\n", - (ctrl_status & ME4600_AI_STATUS_BIT_EF_CHANNEL) ? "not empty" : - "empty"); - PINFO("STATUS_BIT_HF_CHANNEL=%s.\n", - (ctrl_status & ME4600_AI_STATUS_BIT_HF_CHANNEL) ? " < HF" : - " > HF"); - PINFO("STATUS_BIT_FF_CHANNEL=%s.\n", - (ctrl_status & ME4600_AI_STATUS_BIT_FF_CHANNEL) ? "not full" : - "full"); - - PINFO("STATUS_BIT_EF_DATA=%s.\n", - (ctrl_status & ME4600_AI_STATUS_BIT_EF_DATA) ? "not empty" : - "empty"); - PINFO("STATUS_BIT_HF_DATA=%s.\n", - (ctrl_status & ME4600_AI_STATUS_BIT_HF_DATA) ? " < HF" : " > HF"); - PINFO("STATUS_BIT_FF_DATA=%s.\n", - (ctrl_status & ME4600_AI_STATUS_BIT_FF_DATA) ? "not full" : - "full"); - - PINFO("CTRL_BIT_HF_IRQ_RESET=%s.\n", - (ctrl_status & ME4600_AI_CTRL_BIT_HF_IRQ_RESET) ? "reset" : - "work"); - PINFO("CTRL_BIT_SC_IRQ=%s.\n", - (ctrl_status & ME4600_AI_CTRL_BIT_SC_IRQ) ? "enable" : "disable"); - PINFO("CTRL_BIT_SC_RELOAD=%s.\n", - (ctrl_status & ME4600_AI_CTRL_BIT_SC_RELOAD) ? "on" : "off"); - PINFO("CTRL_BIT_SC_IRQ_RESET=%s.\n", - (ctrl_status & ME4600_AI_CTRL_BIT_SC_IRQ_RESET) ? "reset" : - "work"); - PINFO("%ld END\n", jiffies); -#endif - - return IRQ_HANDLED; -} - -/** @brief Stop aqusation of data. Reset interrupts' laches. Clear data's FIFO. -* -* @param instance The subdevice instance (pointer). -*/ -inline void ai_stop_isr(me4600_ai_subdevice_t *instance) -{ /// @note This is soft time critical function! - register uint32_t tmp; - - spin_lock(instance->ctrl_reg_lock); - //Stop all. Reset interrupt laches. Reset data FIFO. - tmp = inl(instance->ctrl_reg); - tmp |= - (ME4600_AI_CTRL_BIT_IMMEDIATE_STOP | ME4600_AI_CTRL_BIT_HF_IRQ_RESET - | ME4600_AI_CTRL_BIT_LE_IRQ_RESET | - ME4600_AI_CTRL_BIT_SC_IRQ_RESET); - tmp &= ~ME4600_AI_CTRL_BIT_DATA_FIFO; - outl(tmp, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->ctrl_reg - instance->reg_base, tmp); - spin_unlock(instance->ctrl_reg_lock); -} - -/** @brief Copy data from fifo to circular buffer. -* -* @param instance The subdevice instance (pointer). -* @param count The number of requested data. -* -* @return On success: Number of copied values. -* @return On error: -ME_ERRNO_RING_BUFFER_OVERFLOW. -*/ -static inline int ai_read_data(me4600_ai_subdevice_t *instance, - const int count) -{ /// @note This is time critical function! - int c = count; - int empty_space; - int copied = 0; - int i, j; - - empty_space = me_circ_buf_space_to_end(&instance->circ_buf); - if (empty_space <= 0) { - PDEBUG("Circular buffer full.\n"); - return -ME_ERRNO_RING_BUFFER_OVERFLOW; - } - - if (empty_space < c) { //Copy first part. Max to end of buffer. - PDEBUG - ("Try to copy %d values from FIFO to circular buffer (pass 1).\n", - empty_space); - for (i = 0; i < empty_space; i++) { - *(instance->circ_buf.buf + instance->circ_buf.head) = - (inw(instance->data_reg) ^ 0x8000); - instance->circ_buf.head++; - } - instance->circ_buf.head &= instance->circ_buf.mask; - c -= empty_space; - copied = empty_space; - - empty_space = me_circ_buf_space_to_end(&instance->circ_buf); - } - - if (empty_space > 0) { - j = (empty_space < c) ? empty_space : c; - PDEBUG - ("Try to copy %d values from FIFO to circular buffer (pass 2).\n", - c); - for (i = 0; i < j; i++) { - *(instance->circ_buf.buf + instance->circ_buf.head) = - (inw(instance->data_reg) ^ 0x8000); - instance->circ_buf.head++; - } - instance->circ_buf.head &= instance->circ_buf.mask; - copied += j; - } - return copied; -} - -inline void ai_infinite_ISM(me4600_ai_subdevice_t *instance) -{ /// @note This is time critical function! - register volatile uint32_t ctrl_set, ctrl_reset, tmp; - - if (instance->fifo_irq_threshold < ME4600_AI_FIFO_MAX_SC) { // Only sample counter with reloadnig is working. Reset it. - PINFO - ("Only sample counter with reloadnig is working. Reset it.\n"); - ctrl_set = ME4600_AI_CTRL_BIT_SC_IRQ_RESET; - ctrl_reset = ~ME4600_AI_CTRL_BIT_SC_IRQ_RESET; - } else if (instance->fifo_irq_threshold == instance->ISM.read) { //This is SC interrupt for large block. The whole section is done. Reset SC_IRQ an HF_IRQ and start everything again from beginning. - PINFO - ("This is SC interrupt for large block. The whole section is done. Reset SC_IRQ an HF_IRQ and start everything again from beginning.\n"); - ctrl_set = - ME4600_AI_CTRL_BIT_SC_IRQ_RESET | - ME4600_AI_CTRL_BIT_HF_IRQ_RESET; - ctrl_reset = - ~(ME4600_AI_CTRL_BIT_SC_IRQ_RESET | - ME4600_AI_CTRL_BIT_HF_IRQ_RESET); - } else if (instance->fifo_irq_threshold >= (ME4600_AI_FIFO_MAX_SC + instance->ISM.read)) { //This is HF interrupt for large block.The next interrupt should be from HF, also. Reset HF. - PINFO - ("This is HF interrupt for large block.The next interrupt should be from HF, also. Reset HF.\n"); - ctrl_set = ME4600_AI_CTRL_BIT_HF_IRQ_RESET; - ctrl_reset = ~ME4600_AI_CTRL_BIT_HF_IRQ_RESET; - } else { //This is HF interrupt for large block.The next interrupt should be from SC. Don't reset HF! - PINFO - ("This is HF interrupt for large block.The next interrupt should be from SC. Don't reset HF!\n"); - ctrl_set = ME4600_AI_CTRL_BIT_HF_IRQ_RESET; - ctrl_reset = 0xFFFFFFFF; - } - - //Reset interrupt latch. - spin_lock(instance->ctrl_reg_lock); - tmp = inl(instance->ctrl_reg); - PINFO("ctrl=0x%x ctrl_set=0x%x ctrl_reset=0x%x\n", tmp, ctrl_set, - ctrl_reset); - tmp |= ctrl_set; - outl(tmp, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->ctrl_reg - instance->reg_base, tmp); - if (ctrl_reset != 0xFFFFFFFF) { - outl(tmp & ctrl_reset, instance->ctrl_reg); - PDEBUG_REG("ctrl_reset outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ctrl_reg - instance->reg_base, - tmp & ctrl_reset); - } - spin_unlock(instance->ctrl_reg_lock); - -} - -inline void ai_limited_ISM(me4600_ai_subdevice_t *instance, - uint32_t irq_status) -{ /// @note This is time critical function! - register volatile uint32_t ctrl_set, ctrl_reset = 0xFFFFFFFF, tmp; - - if (!instance->fifo_irq_threshold) { //No threshold provided. SC ends work. - PINFO("No threshold provided. SC ends work.\n"); - ctrl_set = ME4600_AI_CTRL_BIT_HF_IRQ_RESET; - if (instance->data_required > (ME4600_AI_FIFO_COUNT - 1 + instance->ISM.global_read)) { //HF need reseting. - ctrl_reset &= ~ME4600_AI_CTRL_BIT_HF_IRQ_RESET; - } - } else //if(instance->fifo_irq_threshold) - { - if (irq_status & ME4600_IRQ_STATUS_BIT_AI_HF) { - PINFO("Threshold provided. Clear HF latch.\n"); - ctrl_set = ME4600_AI_CTRL_BIT_HF_IRQ_RESET; - - if (instance->fifo_irq_threshold >= (ME4600_AI_FIFO_MAX_SC + instance->ISM.read)) { //This is not the last one. HF need reseting. - PINFO - ("The next interrupt is HF. HF need be activating.\n"); - ctrl_reset = ~ME4600_AI_CTRL_BIT_HF_IRQ_RESET; - } - } - - if (irq_status & ME4600_IRQ_STATUS_BIT_SC) { - PINFO("Threshold provided. Restart SC.\n"); - ctrl_set = ME4600_AI_CTRL_BIT_SC_IRQ_RESET; - ctrl_reset &= ~ME4600_AI_CTRL_BIT_SC_IRQ_RESET; - - if (instance->fifo_irq_threshold >= ME4600_AI_FIFO_MAX_SC) { //This is not the last one. HF need to be activating. - PINFO - ("The next interrupt is HF. HF need to be activating.\n"); - ctrl_reset &= ~ME4600_AI_CTRL_BIT_HF_IRQ_RESET; - } - } - } - - //Reset interrupt latch. - spin_lock(instance->ctrl_reg_lock); - tmp = inl(instance->ctrl_reg); - tmp |= ctrl_set; - outl(tmp, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->ctrl_reg - instance->reg_base, tmp); - - if (ctrl_reset != 0xFFFFFFFF) { - outl(tmp & ctrl_reset, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ctrl_reg - instance->reg_base, - tmp & ctrl_reset); - } - spin_unlock(instance->ctrl_reg_lock); - -} - -/** @brief Last chunck of datas. We must reschedule sample counter. -* @note Last chunck. -* Leaving SC_RELOAD doesn't do any harm, but in some bad case can make extra interrupts. -* @warning When threshold is wrongly set some IRQ are lost.(!!!) -*/ -inline void ai_reschedule_SC(me4600_ai_subdevice_t *instance) -{ - register uint32_t rest; - - if (instance->data_required <= instance->ISM.global_read) - return; - - rest = instance->data_required - instance->ISM.global_read; - if (rest < instance->fifo_irq_threshold) { //End of work soon .... - PDEBUG("Rescheduling SC from %d to %d.\n", - instance->fifo_irq_threshold, rest); - /// @note Write new value to SC <== DANGER! This is not safe solution! We can miss some inputs. - outl(rest, instance->sample_counter_reg); - PDEBUG_REG("sample_counter_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->sample_counter_reg - instance->reg_base, - rest); - instance->fifo_irq_threshold = rest; - - if (rest < ME4600_AI_FIFO_MAX_SC) { - instance->ISM.next = rest; - } else { - instance->ISM.next = rest % ME4600_AI_FIFO_HALF; - if (instance->ISM.next + ME4600_AI_FIFO_HALF < - ME4600_AI_FIFO_MAX_SC) { - instance->ISM.next += ME4600_AI_FIFO_HALF; - } - } - } -} - -/** Start the ISM. All must be reseted before enter to this function. */ -inline void ai_data_acquisition_logic(me4600_ai_subdevice_t *instance) -{ - register uint32_t tmp; - - if (!instance->data_required) { //This is infinite aqusition. - if (!instance->fifo_irq_threshold) { //No threshold provided. Set SC to 0.5*FIFO. Clear the SC's latch. - //Set the sample counter - outl(ME4600_AI_FIFO_HALF, instance->sample_counter_reg); - PDEBUG_REG - ("sample_counter_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->sample_counter_reg - instance->reg_base, - ME4600_AI_FIFO_HALF); - } else { //Threshold provided. Set SC to treshold. Clear the SC's latch. - //Set the sample counter - outl(instance->fifo_irq_threshold, - instance->sample_counter_reg); - PDEBUG_REG - ("sample_counter_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->sample_counter_reg - instance->reg_base, - instance->fifo_irq_threshold); - } - - if (instance->fifo_irq_threshold < ME4600_AI_FIFO_MAX_SC) { //Enable only sample counter's interrupt. Set reload bit. Clear the SC's latch. - spin_lock(instance->ctrl_reg_lock); - tmp = inl(instance->ctrl_reg); - tmp |= ME4600_AI_CTRL_BIT_SC_RELOAD; - tmp &= ~ME4600_AI_CTRL_BIT_SC_IRQ_RESET; - outl(tmp, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ctrl_reg - instance->reg_base, - tmp); - spin_unlock(instance->ctrl_reg_lock); - if (!instance->fifo_irq_threshold) { //No threshold provided. Set ISM.next to 0.5*FIFO. - instance->ISM.next = ME4600_AI_FIFO_HALF; - } else { //Threshold provided. Set ISM.next to treshold. - instance->ISM.next = - instance->fifo_irq_threshold; - } - } else { //Enable sample counter's and HF's interrupts. - spin_lock(instance->ctrl_reg_lock); - tmp = inl(instance->ctrl_reg); - tmp |= ME4600_AI_CTRL_BIT_SC_RELOAD; - tmp &= - ~(ME4600_AI_CTRL_BIT_SC_IRQ_RESET | - ME4600_AI_CTRL_BIT_HF_IRQ_RESET); - outl(tmp, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ctrl_reg - instance->reg_base, - tmp); - spin_unlock(instance->ctrl_reg_lock); - - instance->ISM.next = - instance->fifo_irq_threshold % ME4600_AI_FIFO_HALF; - if (instance->ISM.next + ME4600_AI_FIFO_HALF < - ME4600_AI_FIFO_MAX_SC) { - instance->ISM.next += ME4600_AI_FIFO_HALF; - } - } - } else { //This aqusition is limited to set number of data. - if (instance->fifo_irq_threshold >= instance->data_required) { //Stupid situation. - instance->fifo_irq_threshold = 0; - PDEBUG - ("Stupid situation: data_required(%d) < threshold(%d).\n", - instance->fifo_irq_threshold, - instance->data_required); - } - - if (!instance->fifo_irq_threshold) { //No threshold provided. Easy case: HF=read and SC=end. - //Set the sample counter to data_required. - outl(instance->data_required, - instance->sample_counter_reg); - PDEBUG_REG - ("sample_counter_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->sample_counter_reg - instance->reg_base, - instance->data_required); - - //Reset the latches of sample counter and HF (if SC>FIFO). - //No SC reload! - spin_lock(instance->ctrl_reg_lock); - tmp = inl(instance->ctrl_reg); - tmp &= - ~(ME4600_AI_CTRL_BIT_SC_IRQ_RESET | - ME4600_AI_CTRL_BIT_SC_RELOAD); - if (instance->data_required > - (ME4600_AI_FIFO_COUNT - 1)) { - tmp &= ~ME4600_AI_CTRL_BIT_HF_IRQ_RESET; - instance->ISM.next = - instance->data_required % - ME4600_AI_FIFO_HALF; - instance->ISM.next += ME4600_AI_FIFO_HALF; - - } else { - instance->ISM.next = instance->data_required; - } - outl(tmp, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ctrl_reg - instance->reg_base, - tmp); - spin_unlock(instance->ctrl_reg_lock); - - } else { //The most general case. We have concret numbe of required data and threshold. SC=TH - //Set the sample counter to threshold. - outl(instance->fifo_irq_threshold, - instance->sample_counter_reg); - PDEBUG_REG - ("sample_counter_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->sample_counter_reg - instance->reg_base, - instance->fifo_irq_threshold); - - spin_lock(instance->ctrl_reg_lock); - tmp = inl(instance->ctrl_reg); - //In this moment we are sure that SC will come more than once. - tmp |= ME4600_AI_CTRL_BIT_SC_RELOAD; - - if (instance->fifo_irq_threshold < ME4600_AI_FIFO_MAX_SC) { //The threshold is so small that we do need HF. - tmp &= ~ME4600_AI_CTRL_BIT_SC_IRQ_RESET; - instance->ISM.next = - instance->fifo_irq_threshold; - } else { //The threshold is large. The HF must be use. - tmp &= - ~(ME4600_AI_CTRL_BIT_SC_IRQ_RESET | - ME4600_AI_CTRL_BIT_HF_IRQ_RESET); - instance->ISM.next = - instance->fifo_irq_threshold % - ME4600_AI_FIFO_HALF; - if (instance->ISM.next + ME4600_AI_FIFO_HALF < - ME4600_AI_FIFO_MAX_SC) { - instance->ISM.next += - ME4600_AI_FIFO_HALF; - } - } - outl(tmp, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ctrl_reg - instance->reg_base, - tmp); - spin_unlock(instance->ctrl_reg_lock); - } - } -} - -static int ai_mux_toggler(me4600_ai_subdevice_t *instance) -{ - uint32_t tmp; - - PDEBUG("executed. idx=0\n"); - - outl(0, instance->scan_pre_timer_low_reg); - PDEBUG_REG("scan_pre_timer_low_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->scan_pre_timer_low_reg - instance->reg_base, 0); - outl(0, instance->scan_pre_timer_high_reg); - PDEBUG_REG("scan_pre_timer_high_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->scan_pre_timer_high_reg - instance->reg_base, 0); - outl(0, instance->scan_timer_low_reg); - PDEBUG_REG("scan_timer_low_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->scan_timer_low_reg - instance->reg_base, 0); - outl(0, instance->scan_timer_high_reg); - PDEBUG_REG("scan_timer_high_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->scan_timer_high_reg - instance->reg_base, 0); - outl(65, instance->chan_timer_reg); - PDEBUG_REG("chan_timer_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->chan_timer_reg - instance->reg_base, 65); - outl(65, instance->chan_pre_timer_reg); - PDEBUG_REG("chan_pre_timer_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->chan_pre_timer_reg - instance->reg_base, 65); - - // Turn on internal reference. - tmp = inl(instance->ctrl_reg); - tmp |= ME4600_AI_CTRL_BIT_FULLSCALE; - outl(tmp, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->ctrl_reg - instance->reg_base, tmp); - - // Clear data and channel fifo. - tmp &= - ~(ME4600_AI_CTRL_BIT_CHANNEL_FIFO | ME4600_AI_CTRL_BIT_DATA_FIFO); - outl(tmp, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->ctrl_reg - instance->reg_base, tmp); - tmp |= ME4600_AI_CTRL_BIT_CHANNEL_FIFO | ME4600_AI_CTRL_BIT_DATA_FIFO; - outl(tmp, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->ctrl_reg - instance->reg_base, tmp); - - // Write channel entry. - outl(ME4600_AI_LIST_INPUT_DIFFERENTIAL | - ME4600_AI_LIST_RANGE_UNIPOLAR_2_5 | 31, - instance->channel_list_reg); - PDEBUG_REG("channel_list_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->channel_list_reg - instance->reg_base, - ME4600_AI_LIST_INPUT_DIFFERENTIAL | - ME4600_AI_LIST_RANGE_UNIPOLAR_2_5 | 31); - - // Start conversion. - inl(instance->start_reg); - PDEBUG_REG("start_reg inl(0x%lX+0x%lX)\n", instance->reg_base, - instance->start_reg - instance->reg_base); - udelay(10); - - // Clear data and channel fifo. - tmp &= - ~(ME4600_AI_CTRL_BIT_CHANNEL_FIFO | ME4600_AI_CTRL_BIT_DATA_FIFO); - outl(tmp, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->ctrl_reg - instance->reg_base, tmp); - tmp |= ME4600_AI_CTRL_BIT_CHANNEL_FIFO | ME4600_AI_CTRL_BIT_DATA_FIFO; - outl(tmp, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->ctrl_reg - instance->reg_base, tmp); - - // Write channel entry. - // ME4600_AI_LIST_INPUT_SINGLE_ENDED | ME4600_AI_LIST_RANGE_BIPOLAR_10 <= 0x0000 - outl(ME4600_AI_LIST_INPUT_SINGLE_ENDED | - ME4600_AI_LIST_RANGE_BIPOLAR_10, instance->channel_list_reg); - PDEBUG_REG("channel_list_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->channel_list_reg - instance->reg_base, - ME4600_AI_LIST_INPUT_SINGLE_ENDED | - ME4600_AI_LIST_RANGE_BIPOLAR_10); - - // Start conversion. - inl(instance->start_reg); - PDEBUG_REG("start_reg inl(0x%lX+0x%lX)\n", instance->reg_base, - instance->start_reg - instance->reg_base); - udelay(10); - - // Clear control register. - tmp &= (ME4600_AI_CTRL_BIT_EX_IRQ | ME4600_AI_CTRL_BIT_EX_IRQ_RESET); - outl(tmp, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->ctrl_reg - instance->reg_base, tmp); - - return ME_ERRNO_SUCCESS; -} - -/** @brief Copy rest of data from fifo to circular buffer. -* @note Helper for STOP command. After FSM is stopped. -* @note This is slow function that copy all remainig data from FIFO to buffer. -* -* @param instance The subdevice instance (pointer). -* -* @return On success: Number of copied values. -* @return On error: Negative error code -ME_ERRNO_RING_BUFFER_OVERFLOW. -*/ -static inline int ai_read_data_pooling(me4600_ai_subdevice_t *instance) -{ /// @note This is time critical function! - int empty_space; - int copied = 0; - int status = ME_ERRNO_SUCCESS; - - PDEBUG("Space left in circular buffer = %d.\n", - me_circ_buf_space(&instance->circ_buf)); - - while ((empty_space = me_circ_buf_space(&instance->circ_buf))) { - if (!(status = inl(instance->status_reg) & ME4600_AI_STATUS_BIT_EF_DATA)) { //No more data. status = ME_ERRNO_SUCCESS = 0 - break; - } - *(instance->circ_buf.buf + instance->circ_buf.head) = - (inw(instance->data_reg) ^ 0x8000); - instance->circ_buf.head++; - instance->circ_buf.head &= instance->circ_buf.mask; - } - -#ifdef MEDEBUG_ERROR - if (!status) - PDEBUG - ("Copied all remaining datas (%d) from FIFO to circular buffer.\n", - copied); - else { - PDEBUG("No more empty space in buffer.\n"); - PDEBUG("Copied %d datas from FIFO to circular buffer.\n", - copied); - PDEBUG("FIFO still not empty.\n"); - } -#endif - return (!status) ? copied : -ME_ERRNO_RING_BUFFER_OVERFLOW; -} - -static void me4600_ai_work_control_task(struct work_struct *work) -{ - me4600_ai_subdevice_t *instance; - uint32_t status; - uint32_t ctrl; - unsigned long cpu_flags = 0; - int reschedule = 0; - int signaling = 0; - - instance = - container_of((void *)work, me4600_ai_subdevice_t, ai_control_task); - PINFO("<%s: %ld> executed.\n", __func__, jiffies); - - status = inl(instance->status_reg); - PDEBUG_REG("status_reg inl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->status_reg - instance->reg_base, status); - - switch (instance->status) { // Checking actual mode. - // Not configured for work. - case ai_status_none: - break; - - //This are stable modes. No need to do anything. (?) - case ai_status_single_configured: - case ai_status_stream_configured: - case ai_status_stream_fifo_error: - case ai_status_stream_buffer_error: - case ai_status_stream_error: - PERROR("Shouldn't be running!.\n"); - break; - - // Stream modes - case ai_status_stream_run_wait: - if (status & ME4600_AI_STATUS_BIT_FSM) { // ISM started.. - instance->status = ai_status_stream_run; - // Signal the end of wait for start. - signaling = 1; - // Wait now for stop. - reschedule = 1; - break; - - // Check timeout. - if ((instance->timeout.delay) && ((jiffies - instance->timeout.start_time) >= instance->timeout.delay)) { // Timeout - PDEBUG("Timeout reached.\n"); - // Stop all actions. No conditions! Block interrupts. Reset FIFO => Too late! - ai_stop_isr(instance); - - instance->status = ai_status_stream_end; - - // Signal the end. - signaling = 1; - } - } - break; - - case ai_status_stream_run: - // Wait for stop ISM. - reschedule = 1; - break; - - case ai_status_stream_end_wait: - if (!(status & ME4600_AI_STATUS_BIT_FSM)) { // ISM stoped. Overwrite ISR. - instance->status = ai_status_stream_end; - // Signal the end of wait for stop. - signaling = 1; - } else { - // Wait for stop ISM. - reschedule = 1; - } - break; - - case ai_status_stream_end: - //End work. - if (status & ME4600_AI_STATUS_BIT_FSM) { // Still working? Stop it! - PERROR - ("Status is 'ai_status_stream_end' but hardware is still working!\n"); - spin_lock_irqsave(instance->ctrl_reg_lock, cpu_flags); - ctrl = inl(instance->ctrl_reg); - ctrl |= - (ME4600_AI_CTRL_BIT_IMMEDIATE_STOP | - ME4600_AI_CTRL_BIT_HF_IRQ_RESET | - ME4600_AI_CTRL_BIT_SC_IRQ_RESET); - outl(ctrl, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ctrl_reg - instance->reg_base, - ctrl); - spin_unlock_irqrestore(instance->ctrl_reg_lock, - cpu_flags); - } - break; - - default: - PERROR_CRITICAL("Status is in wrong state (%d)!\n", - instance->status); - instance->status = ai_status_stream_error; - // Signal the end. - signaling = 1; - break; - - } - - if (signaling) { //Signal it. - wake_up_interruptible_all(&instance->wait_queue); - } - - if (instance->ai_control_task_flag && reschedule) { // Reschedule task - queue_delayed_work(instance->me4600_workqueue, - &instance->ai_control_task, 1); - } else { - PINFO("<%s> Ending control task.\n", __func__); - } - -} |