// SPDX-License-Identifier: GPL-2.0+
/*
 * Command support for NI general purpose counters
 *
 * Copyright (C) 2006 Frank Mori Hess <fmhess@users.sourceforge.net>
 */

/*
 * Module: ni_tiocmd
 * Description: National Instruments general purpose counters command support
 * Author: J.P. Mellor <jpmellor@rose-hulman.edu>,
 *         Herman.Bruyninckx@mech.kuleuven.ac.be,
 *         Wim.Meeussen@mech.kuleuven.ac.be,
 *         Klaas.Gadeyne@mech.kuleuven.ac.be,
 *         Frank Mori Hess <fmhess@users.sourceforge.net>
 * Updated: Fri, 11 Apr 2008 12:32:35 +0100
 * Status: works
 *
 * This module is not used directly by end-users.  Rather, it
 * is used by other drivers (for example ni_660x and ni_pcimio)
 * to provide command support for NI's general purpose counters.
 * It was originally split out of ni_tio.c to stop the 'ni_tio'
 * module depending on the 'mite' module.
 *
 * References:
 * DAQ 660x Register-Level Programmer Manual  (NI 370505A-01)
 * DAQ 6601/6602 User Manual (NI 322137B-01)
 * 340934b.pdf  DAQ-STC reference manual
 *
 * TODO: Support use of both banks X and Y
 */

#include <linux/module.h>
#include "ni_tio_internal.h"
#include "mite.h"
#include "ni_routes.h"

static void ni_tio_configure_dma(struct ni_gpct *counter,
				 bool enable, bool read)
{
	struct ni_gpct_device *counter_dev = counter->counter_dev;
	unsigned int cidx = counter->counter_index;
	unsigned int mask;
	unsigned int bits;

	mask = GI_READ_ACKS_IRQ | GI_WRITE_ACKS_IRQ;
	bits = 0;

	if (enable) {
		if (read)
			bits |= GI_READ_ACKS_IRQ;
		else
			bits |= GI_WRITE_ACKS_IRQ;
	}
	ni_tio_set_bits(counter, NITIO_INPUT_SEL_REG(cidx), mask, bits);

	switch (counter_dev->variant) {
	case ni_gpct_variant_e_series:
		break;
	case ni_gpct_variant_m_series:
	case ni_gpct_variant_660x:
		mask = GI_DMA_ENABLE | GI_DMA_INT_ENA | GI_DMA_WRITE;
		bits = 0;

		if (enable)
			bits |= GI_DMA_ENABLE | GI_DMA_INT_ENA;
		if (!read)
			bits |= GI_DMA_WRITE;
		ni_tio_set_bits(counter, NITIO_DMA_CFG_REG(cidx), mask, bits);
		break;
	}
}

static int ni_tio_input_inttrig(struct comedi_device *dev,
				struct comedi_subdevice *s,
				unsigned int trig_num)
{
	struct ni_gpct *counter = s->private;
	struct comedi_cmd *cmd = &s->async->cmd;
	unsigned long flags;
	int ret = 0;

	if (trig_num != cmd->start_arg)
		return -EINVAL;

	spin_lock_irqsave(&counter->lock, flags);
	if (counter->mite_chan)
		mite_dma_arm(counter->mite_chan);
	else
		ret = -EIO;
	spin_unlock_irqrestore(&counter->lock, flags);
	if (ret < 0)
		return ret;
	ret = ni_tio_arm(counter, true, NI_GPCT_ARM_IMMEDIATE);
	s->async->inttrig = NULL;

	return ret;
}

static int ni_tio_input_cmd(struct comedi_subdevice *s)
{
	struct ni_gpct *counter = s->private;
	struct ni_gpct_device *counter_dev = counter->counter_dev;
	const struct ni_route_tables *routing_tables =
		counter_dev->routing_tables;
	unsigned int cidx = counter->counter_index;
	struct comedi_async *async = s->async;
	struct comedi_cmd *cmd = &async->cmd;
	int ret = 0;

	/* write alloc the entire buffer */
	comedi_buf_write_alloc(s, async->prealloc_bufsz);
	counter->mite_chan->dir = COMEDI_INPUT;
	switch (counter_dev->variant) {
	case ni_gpct_variant_m_series:
	case ni_gpct_variant_660x:
		mite_prep_dma(counter->mite_chan, 32, 32);
		break;
	case ni_gpct_variant_e_series:
		mite_prep_dma(counter->mite_chan, 16, 32);
		break;
	}
	ni_tio_set_bits(counter, NITIO_CMD_REG(cidx), GI_SAVE_TRACE, 0);
	ni_tio_configure_dma(counter, true, true);

	if (cmd->start_src == TRIG_INT) {
		async->inttrig = &ni_tio_input_inttrig;
	} else {	/* TRIG_NOW || TRIG_EXT || TRIG_OTHER */
		async->inttrig = NULL;
		mite_dma_arm(counter->mite_chan);

		if (cmd->start_src == TRIG_NOW)
			ret = ni_tio_arm(counter, true, NI_GPCT_ARM_IMMEDIATE);
		else if (cmd->start_src == TRIG_EXT) {
			int reg = CR_CHAN(cmd->start_arg);

			if (reg >= NI_NAMES_BASE) {
				/* using a device-global name. lookup reg */
				reg = ni_get_reg_value(reg,
						       NI_CtrArmStartTrigger(cidx),
						       routing_tables);
				/* mark this as a raw register value */
				reg |= NI_GPCT_HW_ARM;
			}
			ret = ni_tio_arm(counter, true, reg);
		}
	}
	return ret;
}

static int ni_tio_output_cmd(struct comedi_subdevice *s)
{
	struct ni_gpct *counter = s->private;

	dev_err(counter->counter_dev->dev->class_dev,
		"output commands not yet implemented.\n");
	return -ENOTSUPP;
}

static int ni_tio_cmd_setup(struct comedi_subdevice *s)
{
	struct comedi_cmd *cmd = &s->async->cmd;
	struct ni_gpct *counter = s->private;
	unsigned int cidx = counter->counter_index;
	const struct ni_route_tables *routing_tables =
		counter->counter_dev->routing_tables;
	int set_gate_source = 0;
	unsigned int gate_source;
	int retval = 0;

	if (cmd->scan_begin_src == TRIG_EXT) {
		set_gate_source = 1;
		gate_source = cmd->scan_begin_arg;
	} else if (cmd->convert_src == TRIG_EXT) {
		set_gate_source = 1;
		gate_source = cmd->convert_arg;
	}
	if (set_gate_source) {
		if (CR_CHAN(gate_source) >= NI_NAMES_BASE) {
			/* Lookup and use the real register values */
			int reg = ni_get_reg_value(CR_CHAN(gate_source),
						   NI_CtrGate(cidx),
						   routing_tables);
			if (reg < 0)
				return -EINVAL;
			retval = ni_tio_set_gate_src_raw(counter, 0, reg);
		} else {
			/*
			 * This function must be used separately since it does
			 * not expect real register values and attempts to
			 * convert these to real register values.
			 */
			retval = ni_tio_set_gate_src(counter, 0, gate_source);
		}
	}
	if (cmd->flags & CMDF_WAKE_EOS) {
		ni_tio_set_bits(counter, NITIO_INT_ENA_REG(cidx),
				GI_GATE_INTERRUPT_ENABLE(cidx),
				GI_GATE_INTERRUPT_ENABLE(cidx));
	}
	return retval;
}

int ni_tio_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
{
	struct ni_gpct *counter = s->private;
	struct comedi_async *async = s->async;
	struct comedi_cmd *cmd = &async->cmd;
	int retval = 0;
	unsigned long flags;

	spin_lock_irqsave(&counter->lock, flags);
	if (!counter->mite_chan) {
		dev_err(counter->counter_dev->dev->class_dev,
			"commands only supported with DMA.  ");
		dev_err(counter->counter_dev->dev->class_dev,
			"Interrupt-driven commands not yet implemented.\n");
		retval = -EIO;
	} else {
		retval = ni_tio_cmd_setup(s);
		if (retval == 0) {
			if (cmd->flags & CMDF_WRITE)
				retval = ni_tio_output_cmd(s);
			else
				retval = ni_tio_input_cmd(s);
		}
	}
	spin_unlock_irqrestore(&counter->lock, flags);
	return retval;
}
EXPORT_SYMBOL_GPL(ni_tio_cmd);

int ni_tio_cmdtest(struct comedi_device *dev,
		   struct comedi_subdevice *s,
		   struct comedi_cmd *cmd)
{
	struct ni_gpct *counter = s->private;
	unsigned int cidx = counter->counter_index;
	const struct ni_route_tables *routing_tables =
		counter->counter_dev->routing_tables;
	int err = 0;
	unsigned int sources;

	/* Step 1 : check if triggers are trivially valid */

	sources = TRIG_NOW | TRIG_INT | TRIG_OTHER;
	if (ni_tio_counting_mode_registers_present(counter->counter_dev))
		sources |= TRIG_EXT;
	err |= comedi_check_trigger_src(&cmd->start_src, sources);

	err |= comedi_check_trigger_src(&cmd->scan_begin_src,
					TRIG_FOLLOW | TRIG_EXT | TRIG_OTHER);
	err |= comedi_check_trigger_src(&cmd->convert_src,
					TRIG_NOW | TRIG_EXT | TRIG_OTHER);
	err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
	err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_NONE);

	if (err)
		return 1;

	/* Step 2a : make sure trigger sources are unique */

	err |= comedi_check_trigger_is_unique(cmd->start_src);
	err |= comedi_check_trigger_is_unique(cmd->scan_begin_src);
	err |= comedi_check_trigger_is_unique(cmd->convert_src);

	/* Step 2b : and mutually compatible */

	if (cmd->convert_src != TRIG_NOW && cmd->scan_begin_src != TRIG_FOLLOW)
		err |= -EINVAL;

	if (err)
		return 2;

	/* Step 3: check if arguments are trivially valid */

	switch (cmd->start_src) {
	case TRIG_NOW:
	case TRIG_INT:
	case TRIG_OTHER:
		err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
		break;
	case TRIG_EXT:
		/* start_arg is the start_trigger passed to ni_tio_arm() */
		/*
		 * This should be done, but we don't yet know the actual
		 * register values.  These should be tested and then documented
		 * in the ni_route_values/ni_*.csv files, with indication of
		 * who/when/which/how these were tested.
		 * When at least a e/m/660x series have been tested, this code
		 * should be uncommented:
		 *
		 * err |= ni_check_trigger_arg(CR_CHAN(cmd->start_arg),
		 *			    NI_CtrArmStartTrigger(cidx),
		 *			    routing_tables);
		 */
		break;
	}

	/*
	 * It seems that convention is to allow either scan_begin_arg or
	 * convert_arg to specify the Gate source, with scan_begin_arg taking
	 * precedence.
	 */
	if (cmd->scan_begin_src != TRIG_EXT)
		err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
	else
		err |= ni_check_trigger_arg(CR_CHAN(cmd->scan_begin_arg),
					    NI_CtrGate(cidx), routing_tables);

	if (cmd->convert_src != TRIG_EXT)
		err |= comedi_check_trigger_arg_is(&cmd->convert_arg, 0);
	else
		err |= ni_check_trigger_arg(CR_CHAN(cmd->convert_arg),
					    NI_CtrGate(cidx), routing_tables);

	err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
					   cmd->chanlist_len);
	err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);

	if (err)
		return 3;

	/* Step 4: fix up any arguments */

	/* Step 5: check channel list if it exists */

	return 0;
}
EXPORT_SYMBOL_GPL(ni_tio_cmdtest);

int ni_tio_cancel(struct ni_gpct *counter)
{
	unsigned int cidx = counter->counter_index;
	unsigned long flags;

	ni_tio_arm(counter, false, 0);
	spin_lock_irqsave(&counter->lock, flags);
	if (counter->mite_chan)
		mite_dma_disarm(counter->mite_chan);
	spin_unlock_irqrestore(&counter->lock, flags);
	ni_tio_configure_dma(counter, false, false);

	ni_tio_set_bits(counter, NITIO_INT_ENA_REG(cidx),
			GI_GATE_INTERRUPT_ENABLE(cidx), 0x0);
	return 0;
}
EXPORT_SYMBOL_GPL(ni_tio_cancel);

static int should_ack_gate(struct ni_gpct *counter)
{
	unsigned long flags;
	int retval = 0;

	switch (counter->counter_dev->variant) {
	case ni_gpct_variant_m_series:
	case ni_gpct_variant_660x:
		/*
		 * not sure if 660x really supports gate interrupts
		 * (the bits are not listed in register-level manual)
		 */
		return 1;
	case ni_gpct_variant_e_series:
		/*
		 * During buffered input counter operation for e-series,
		 * the gate interrupt is acked automatically by the dma
		 * controller, due to the Gi_Read/Write_Acknowledges_IRQ
		 * bits in the input select register.
		 */
		spin_lock_irqsave(&counter->lock, flags);
		{
			if (!counter->mite_chan ||
			    counter->mite_chan->dir != COMEDI_INPUT ||
			    (mite_done(counter->mite_chan))) {
				retval = 1;
			}
		}
		spin_unlock_irqrestore(&counter->lock, flags);
		break;
	}
	return retval;
}

static void ni_tio_acknowledge_and_confirm(struct ni_gpct *counter,
					   int *gate_error,
					   int *tc_error,
					   int *perm_stale_data)
{
	unsigned int cidx = counter->counter_index;
	const unsigned short gxx_status = ni_tio_read(counter,
						NITIO_SHARED_STATUS_REG(cidx));
	const unsigned short gi_status = ni_tio_read(counter,
						NITIO_STATUS_REG(cidx));
	unsigned int ack = 0;

	if (gate_error)
		*gate_error = 0;
	if (tc_error)
		*tc_error = 0;
	if (perm_stale_data)
		*perm_stale_data = 0;

	if (gxx_status & GI_GATE_ERROR(cidx)) {
		ack |= GI_GATE_ERROR_CONFIRM(cidx);
		if (gate_error) {
			/*
			 * 660x don't support automatic acknowledgment
			 * of gate interrupt via dma read/write
			 * and report bogus gate errors
			 */
			if (counter->counter_dev->variant !=
			    ni_gpct_variant_660x)
				*gate_error = 1;
		}
	}
	if (gxx_status & GI_TC_ERROR(cidx)) {
		ack |= GI_TC_ERROR_CONFIRM(cidx);
		if (tc_error)
			*tc_error = 1;
	}
	if (gi_status & GI_TC)
		ack |= GI_TC_INTERRUPT_ACK;
	if (gi_status & GI_GATE_INTERRUPT) {
		if (should_ack_gate(counter))
			ack |= GI_GATE_INTERRUPT_ACK;
	}
	if (ack)
		ni_tio_write(counter, ack, NITIO_INT_ACK_REG(cidx));
	if (ni_tio_get_soft_copy(counter, NITIO_MODE_REG(cidx)) &
	    GI_LOADING_ON_GATE) {
		if (ni_tio_read(counter, NITIO_STATUS2_REG(cidx)) &
		    GI_PERMANENT_STALE(cidx)) {
			dev_info(counter->counter_dev->dev->class_dev,
				 "%s: Gi_Permanent_Stale_Data detected.\n",
				 __func__);
			if (perm_stale_data)
				*perm_stale_data = 1;
		}
	}
}

void ni_tio_acknowledge(struct ni_gpct *counter)
{
	ni_tio_acknowledge_and_confirm(counter, NULL, NULL, NULL);
}
EXPORT_SYMBOL_GPL(ni_tio_acknowledge);

void ni_tio_handle_interrupt(struct ni_gpct *counter,
			     struct comedi_subdevice *s)
{
	unsigned int cidx = counter->counter_index;
	unsigned long flags;
	int gate_error;
	int tc_error;
	int perm_stale_data;

	ni_tio_acknowledge_and_confirm(counter, &gate_error, &tc_error,
				       &perm_stale_data);
	if (gate_error) {
		dev_notice(counter->counter_dev->dev->class_dev,
			   "%s: Gi_Gate_Error detected.\n", __func__);
		s->async->events |= COMEDI_CB_OVERFLOW;
	}
	if (perm_stale_data)
		s->async->events |= COMEDI_CB_ERROR;
	switch (counter->counter_dev->variant) {
	case ni_gpct_variant_m_series:
	case ni_gpct_variant_660x:
		if (ni_tio_read(counter, NITIO_DMA_STATUS_REG(cidx)) &
		    GI_DRQ_ERROR) {
			dev_notice(counter->counter_dev->dev->class_dev,
				   "%s: Gi_DRQ_Error detected.\n", __func__);
			s->async->events |= COMEDI_CB_OVERFLOW;
		}
		break;
	case ni_gpct_variant_e_series:
		break;
	}
	spin_lock_irqsave(&counter->lock, flags);
	if (counter->mite_chan)
		mite_ack_linkc(counter->mite_chan, s, true);
	spin_unlock_irqrestore(&counter->lock, flags);
}
EXPORT_SYMBOL_GPL(ni_tio_handle_interrupt);

void ni_tio_set_mite_channel(struct ni_gpct *counter,
			     struct mite_channel *mite_chan)
{
	unsigned long flags;

	spin_lock_irqsave(&counter->lock, flags);
	counter->mite_chan = mite_chan;
	spin_unlock_irqrestore(&counter->lock, flags);
}
EXPORT_SYMBOL_GPL(ni_tio_set_mite_channel);

static int __init ni_tiocmd_init_module(void)
{
	return 0;
}
module_init(ni_tiocmd_init_module);

static void __exit ni_tiocmd_cleanup_module(void)
{
}
module_exit(ni_tiocmd_cleanup_module);

MODULE_AUTHOR("Comedi <comedi@comedi.org>");
MODULE_DESCRIPTION("Comedi command support for NI general-purpose counters");
MODULE_LICENSE("GPL");
