linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/4] staging: comedi: ni_65xx: edge detection changes
@ 2014-07-23  9:41 Ian Abbott
  2014-07-23  9:41 ` [PATCH 1/4] staging: comedi: ni_65xx: add ni_65xx_num_ports() Ian Abbott
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Ian Abbott @ 2014-07-23  9:41 UTC (permalink / raw)
  To: driverdev-devel
  Cc: Greg Kroah-Hartman, Ian Abbott, H Hartley Sweeten, linux-kernel

Add partial support for INSN_CONFIG_DIGITAL_TRIG as an alternative to
INSN_CONFIG_CHANGE_NOTIFY (with the advantage that more than the first 32
channels are supported), and initialize the edge detection registers.

1) staging: comedi: ni_65xx: add ni_65xx_num_ports()
2) staging: comedi: ni_65xx: refactor edge detection configuration
3) staging: comedi: ni_65xx: support INSN_CONFIG_DIGITAL_TRIG
4) staging: comedi: ni_65xx: disable edge detection on initialization

 drivers/staging/comedi/drivers/ni_65xx.c | 125 +++++++++++++++++++++++--------
 1 file changed, 94 insertions(+), 31 deletions(-)

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 1/4] staging: comedi: ni_65xx: add ni_65xx_num_ports()
  2014-07-23  9:41 [PATCH 0/4] staging: comedi: ni_65xx: edge detection changes Ian Abbott
@ 2014-07-23  9:41 ` Ian Abbott
  2014-07-23  9:41 ` [PATCH 2/4] staging: comedi: ni_65xx: refactor edge detection configuration Ian Abbott
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Ian Abbott @ 2014-07-23  9:41 UTC (permalink / raw)
  To: driverdev-devel
  Cc: Greg Kroah-Hartman, Ian Abbott, H Hartley Sweeten, linux-kernel

Add a function to return the total number of digital I/O, digital input,
and digital output ports on the board.  Each port has 8 channels (bits).

Signed-off-by: Ian Abbott <abbotti@mev.co.uk>
---
 drivers/staging/comedi/drivers/ni_65xx.c | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/drivers/staging/comedi/drivers/ni_65xx.c b/drivers/staging/comedi/drivers/ni_65xx.c
index aba6fbb..0f9185e 100644
--- a/drivers/staging/comedi/drivers/ni_65xx.c
+++ b/drivers/staging/comedi/drivers/ni_65xx.c
@@ -296,17 +296,19 @@ struct ni_65xx_private {
 	void __iomem *mmio;
 };
 
-static void ni_65xx_disable_input_filters(struct comedi_device *dev)
+static unsigned int ni_65xx_num_ports(struct comedi_device *dev)
 {
 	const struct ni_65xx_board *board = comedi_board(dev);
+
+	return board->num_dio_ports + board->num_di_ports + board->num_do_ports;
+}
+
+static void ni_65xx_disable_input_filters(struct comedi_device *dev)
+{
 	struct ni_65xx_private *devpriv = dev->private;
-	unsigned num_ports;
+	unsigned int num_ports = ni_65xx_num_ports(dev);
 	int i;
 
-	num_ports = board->num_dio_ports +
-		    board->num_di_ports +
-		    board->num_do_ports;
-
 	/* disable input filtering on all ports */
 	for (i = 0; i < num_ports; ++i)
 		writeb(0x00, devpriv->mmio + NI_65XX_FILTER_ENA(i));
-- 
2.0.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 2/4] staging: comedi: ni_65xx: refactor edge detection configuration
  2014-07-23  9:41 [PATCH 0/4] staging: comedi: ni_65xx: edge detection changes Ian Abbott
  2014-07-23  9:41 ` [PATCH 1/4] staging: comedi: ni_65xx: add ni_65xx_num_ports() Ian Abbott
@ 2014-07-23  9:41 ` Ian Abbott
  2014-07-23  9:41 ` [PATCH 3/4] staging: comedi: ni_65xx: support INSN_CONFIG_DIGITAL_TRIG Ian Abbott
  2014-07-23  9:41 ` [PATCH 4/4] staging: comedi: ni_65xx: disable edge detection on initialization Ian Abbott
  3 siblings, 0 replies; 5+ messages in thread
From: Ian Abbott @ 2014-07-23  9:41 UTC (permalink / raw)
  To: driverdev-devel
  Cc: Greg Kroah-Hartman, Ian Abbott, H Hartley Sweeten, linux-kernel

Refactor the code that updates the rising and falling edge detection
registers into new function `ni_65xx_update_edge_detection()`.  This
updates the rising and falling edge detection registers for up to 32
channels starting at an arbitrary channel.  Call it from the code that
handles the `INSN_CONFIG_CHANGE_NOTIFY` instruction, which is limited to
the first 32 channels.

(For the purposes of edge detection, the channels are in the natural
port order of the board, 8 channels per port.  In practice, this is all
the digital I/O channels (if any), followed by all the digital input
channels (if any), followed by all the digital output channels (if any).

Signed-off-by: Ian Abbott <abbotti@mev.co.uk>
---
 drivers/staging/comedi/drivers/ni_65xx.c | 71 ++++++++++++++++++++++----------
 1 file changed, 49 insertions(+), 22 deletions(-)

diff --git a/drivers/staging/comedi/drivers/ni_65xx.c b/drivers/staging/comedi/drivers/ni_65xx.c
index 0f9185e..f7566fe 100644
--- a/drivers/staging/comedi/drivers/ni_65xx.c
+++ b/drivers/staging/comedi/drivers/ni_65xx.c
@@ -317,6 +317,54 @@ static void ni_65xx_disable_input_filters(struct comedi_device *dev)
 	writel(0x00000000, devpriv->mmio + NI_65XX_FILTER_REG);
 }
 
+/* updates edge detection for base_chan to base_chan+31 */
+static void ni_65xx_update_edge_detection(struct comedi_device *dev,
+					  unsigned int base_chan,
+					  unsigned int rising,
+					  unsigned int falling)
+{
+	struct ni_65xx_private *devpriv = dev->private;
+	unsigned int num_ports = ni_65xx_num_ports(dev);
+	unsigned int port;
+
+	if (base_chan >= NI_65XX_PORT_TO_CHAN(num_ports))
+		return;
+
+	for (port = NI_65XX_CHAN_TO_PORT(base_chan); port < num_ports; port++) {
+		int bitshift = (int)(NI_65XX_PORT_TO_CHAN(port) - base_chan);
+		unsigned int port_mask, port_rising, port_falling;
+
+		if (bitshift >= 32)
+			break;
+
+		if (bitshift >= 0) {
+			port_mask = ~0U >> bitshift;
+			port_rising = rising >> bitshift;
+			port_falling = falling >> bitshift;
+		} else {
+			port_mask = ~0U << -bitshift;
+			port_rising = rising << -bitshift;
+			port_falling = falling << -bitshift;
+		}
+		if (port_mask & 0xff) {
+			if (~port_mask & 0xff) {
+				port_rising |=
+				    readb(devpriv->mmio +
+					  NI_65XX_RISE_EDGE_ENA_REG(port)) &
+				    ~port_mask;
+				port_falling |=
+				    readb(devpriv->mmio +
+					  NI_65XX_FALL_EDGE_ENA_REG(port)) &
+				    ~port_mask;
+			}
+			writeb(port_rising & 0xff,
+			       devpriv->mmio + NI_65XX_RISE_EDGE_ENA_REG(port));
+			writeb(port_falling & 0xff,
+			       devpriv->mmio + NI_65XX_FALL_EDGE_ENA_REG(port));
+		}
+	}
+}
+
 static int ni_65xx_dio_insn_config(struct comedi_device *dev,
 				   struct comedi_subdevice *s,
 				   struct comedi_insn *insn,
@@ -545,8 +593,6 @@ static int ni_65xx_intr_insn_config(struct comedi_device *dev,
 				    struct comedi_insn *insn,
 				    unsigned int *data)
 {
-	struct ni_65xx_private *devpriv = dev->private;
-
 	switch (data[0]) {
 	case INSN_CONFIG_CHANGE_NOTIFY:
 		/* add instruction to check_insn_config_length() */
@@ -556,26 +602,7 @@ static int ni_65xx_intr_insn_config(struct comedi_device *dev,
 		/*
 		 * This only works for the first 4 ports (32 channels)!
 		 */
-
-		/* set the channels to monitor for rising edges */
-		writeb(data[1] & 0xff,
-		       devpriv->mmio + NI_65XX_RISE_EDGE_ENA_REG(0));
-		writeb((data[1] >> 8) & 0xff,
-		       devpriv->mmio + NI_65XX_RISE_EDGE_ENA_REG(1));
-		writeb((data[1] >> 16) & 0xff,
-		       devpriv->mmio + NI_65XX_RISE_EDGE_ENA_REG(2));
-		writeb((data[1] >> 24) & 0xff,
-		       devpriv->mmio + NI_65XX_RISE_EDGE_ENA_REG(3));
-
-		/* set the channels to monitor for falling edges */
-		writeb(data[2] & 0xff,
-		       devpriv->mmio + NI_65XX_FALL_EDGE_ENA_REG(0));
-		writeb((data[2] >> 8) & 0xff,
-		       devpriv->mmio + NI_65XX_FALL_EDGE_ENA_REG(1));
-		writeb((data[2] >> 16) & 0xff,
-		       devpriv->mmio + NI_65XX_FALL_EDGE_ENA_REG(2));
-		writeb((data[2] >> 24) & 0xff,
-		       devpriv->mmio + NI_65XX_FALL_EDGE_ENA_REG(3));
+		ni_65xx_update_edge_detection(dev, 0, data[1], data[2]);
 		break;
 	default:
 		return -EINVAL;
-- 
2.0.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 3/4] staging: comedi: ni_65xx: support INSN_CONFIG_DIGITAL_TRIG
  2014-07-23  9:41 [PATCH 0/4] staging: comedi: ni_65xx: edge detection changes Ian Abbott
  2014-07-23  9:41 ` [PATCH 1/4] staging: comedi: ni_65xx: add ni_65xx_num_ports() Ian Abbott
  2014-07-23  9:41 ` [PATCH 2/4] staging: comedi: ni_65xx: refactor edge detection configuration Ian Abbott
@ 2014-07-23  9:41 ` Ian Abbott
  2014-07-23  9:41 ` [PATCH 4/4] staging: comedi: ni_65xx: disable edge detection on initialization Ian Abbott
  3 siblings, 0 replies; 5+ messages in thread
From: Ian Abbott @ 2014-07-23  9:41 UTC (permalink / raw)
  To: driverdev-devel
  Cc: Greg Kroah-Hartman, Ian Abbott, H Hartley Sweeten, linux-kernel

The "edge detection interrupt" subdevice supports the
`INSN_CONFIG_CHANGE_NOTIFY` comedi instruction which is only supported
by one other driver.  It is limited to the first 32 channels, but boards
supported by this driver support edge detection on all digital I/O,
digital input and digital output channels.  The
`INSN_CONFIG_DIGITAL_TRIG` comedi instruction is more flexible as it
supports more than 32 channels (with multiple instructions).  It can
also support level detection, but the hardware does not support that.

Add partial support for the `INSN_CONFIG_DIGITAL_TRIG` instruction, but
only for edge detection.

Since `INSN_CONFIG_CHANGE_NOTIFY` can only deal with 32 channels, make
it disable edge detection for any remaining channels.

Signed-off-by: Ian Abbott <abbotti@mev.co.uk>
---
 drivers/staging/comedi/drivers/ni_65xx.c | 39 +++++++++++++++++++++++++++++---
 1 file changed, 36 insertions(+), 3 deletions(-)

diff --git a/drivers/staging/comedi/drivers/ni_65xx.c b/drivers/staging/comedi/drivers/ni_65xx.c
index f7566fe..ddf9135 100644
--- a/drivers/staging/comedi/drivers/ni_65xx.c
+++ b/drivers/staging/comedi/drivers/ni_65xx.c
@@ -365,6 +365,16 @@ static void ni_65xx_update_edge_detection(struct comedi_device *dev,
 	}
 }
 
+static void ni_65xx_disable_edge_detection(struct comedi_device *dev)
+{
+	/* clear edge detection for channels 0 to 31 */
+	ni_65xx_update_edge_detection(dev, 0, 0, 0);
+	/* clear edge detection for channels 32 to 63 */
+	ni_65xx_update_edge_detection(dev, 32, 0, 0);
+	/* clear edge detection for channels 64 to 95 */
+	ni_65xx_update_edge_detection(dev, 64, 0, 0);
+}
+
 static int ni_65xx_dio_insn_config(struct comedi_device *dev,
 				   struct comedi_subdevice *s,
 				   struct comedi_insn *insn,
@@ -599,10 +609,33 @@ static int ni_65xx_intr_insn_config(struct comedi_device *dev,
 		if (insn->n != 3)
 			return -EINVAL;
 
-		/*
-		 * This only works for the first 4 ports (32 channels)!
-		 */
+		/* update edge detection for channels 0 to 31 */
 		ni_65xx_update_edge_detection(dev, 0, data[1], data[2]);
+		/* clear edge detection for channels 32 to 63 */
+		ni_65xx_update_edge_detection(dev, 32, 0, 0);
+		/* clear edge detection for channels 64 to 95 */
+		ni_65xx_update_edge_detection(dev, 64, 0, 0);
+		break;
+	case INSN_CONFIG_DIGITAL_TRIG:
+		/* check trigger number */
+		if (data[1] != 0)
+			return -EINVAL;
+		/* check digital trigger operation */
+		switch (data[2]) {
+		case COMEDI_DIGITAL_TRIG_DISABLE:
+			ni_65xx_disable_edge_detection(dev);
+			break;
+		case COMEDI_DIGITAL_TRIG_ENABLE_EDGES:
+			/*
+			 * update edge detection for channels data[3]
+			 * to (data[3] + 31)
+			 */
+			ni_65xx_update_edge_detection(dev, data[3],
+						      data[4], data[5]);
+			break;
+		default:
+			return -EINVAL;
+		}
 		break;
 	default:
 		return -EINVAL;
-- 
2.0.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 4/4] staging: comedi: ni_65xx: disable edge detection on initialization
  2014-07-23  9:41 [PATCH 0/4] staging: comedi: ni_65xx: edge detection changes Ian Abbott
                   ` (2 preceding siblings ...)
  2014-07-23  9:41 ` [PATCH 3/4] staging: comedi: ni_65xx: support INSN_CONFIG_DIGITAL_TRIG Ian Abbott
@ 2014-07-23  9:41 ` Ian Abbott
  3 siblings, 0 replies; 5+ messages in thread
From: Ian Abbott @ 2014-07-23  9:41 UTC (permalink / raw)
  To: driverdev-devel
  Cc: Greg Kroah-Hartman, Ian Abbott, H Hartley Sweeten, linux-kernel

When the hardware is being initialized, the edge detection interrupts
are cleared and disabled.  Also disable edge detection for all channels
at this time so they start off in a known state.

Signed-off-by: Ian Abbott <abbotti@mev.co.uk>
---
 drivers/staging/comedi/drivers/ni_65xx.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/staging/comedi/drivers/ni_65xx.c b/drivers/staging/comedi/drivers/ni_65xx.c
index ddf9135..1b8a397 100644
--- a/drivers/staging/comedi/drivers/ni_65xx.c
+++ b/drivers/staging/comedi/drivers/ni_65xx.c
@@ -804,6 +804,7 @@ static int ni_65xx_auto_attach(struct comedi_device *dev,
 	}
 
 	ni_65xx_disable_input_filters(dev);
+	ni_65xx_disable_edge_detection(dev);
 
 	return 0;
 }
-- 
2.0.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2014-07-23  9:41 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-07-23  9:41 [PATCH 0/4] staging: comedi: ni_65xx: edge detection changes Ian Abbott
2014-07-23  9:41 ` [PATCH 1/4] staging: comedi: ni_65xx: add ni_65xx_num_ports() Ian Abbott
2014-07-23  9:41 ` [PATCH 2/4] staging: comedi: ni_65xx: refactor edge detection configuration Ian Abbott
2014-07-23  9:41 ` [PATCH 3/4] staging: comedi: ni_65xx: support INSN_CONFIG_DIGITAL_TRIG Ian Abbott
2014-07-23  9:41 ` [PATCH 4/4] staging: comedi: ni_65xx: disable edge detection on initialization Ian Abbott

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).