Re: [PATCH v2 34/36] staging: comedi: amplc_dio200_common: convert driver to use the comedi_8254 module

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 23/02/15 21:58, H Hartley Sweeten wrote:
Convert this driver to use the comedi_8254 module to provide the 8254 timer support.

Add 'clock_src' and 'gate_src' members to the comedi_8254 data for convienence.

Signed-off-by: H Hartley Sweeten <hsweeten@xxxxxxxxxxxxxxxxxxx>
Cc: Ian Abbott <abbotti@xxxxxxxxx>
Cc: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx>
---
v2: no change

  drivers/staging/comedi/Kconfig                     |   1 +
  .../staging/comedi/drivers/amplc_dio200_common.c   | 263 ++++++---------------
  drivers/staging/comedi/drivers/comedi_8254.h       |   4 +
  3 files changed, 72 insertions(+), 196 deletions(-)
[snip]
+static int dio200_subdev_8254_offset(struct comedi_device *dev,
+				     struct comedi_subdevice *s)
  {
-	const struct dio200_board *board = dev->board_ptr;
-	struct dio200_subdev_8254 *subpriv = s->private;
+	struct comedi_8254 *i8254 = s->private;

-	if (!board->has_clk_gat_sce)
-		return -1;
+	if (dev->mmio)
+		return i8254->mmio - dev->mmio;

-	return subpriv->gate_src[counter_number];
+	return i8254->iobase - dev->iobase;
  }

-static int dio200_subdev_8254_set_clock_src(struct comedi_device *dev,
+static void dio200_subdev_8254_set_gate_src(struct comedi_device *dev,
  					    struct comedi_subdevice *s,
-					    unsigned int counter_number,
-					    unsigned int clock_src)
+					    unsigned int chan,
+					    unsigned int src)
  {
-	const struct dio200_board *board = dev->board_ptr;
-	struct dio200_subdev_8254 *subpriv = s->private;
-	unsigned char byte;
+	unsigned int offset = dio200_subdev_8254_offset(dev, s);

-	if (!board->has_clk_gat_sce)
-		return -1;
-	if (clock_src > (board->is_pcie ? 31 : 7))
-		return -1;
-
-	subpriv->clock_src[counter_number] = clock_src;
-	byte = clk_sce((subpriv->ofs >> 2) & 1, counter_number, clock_src);
-	dio200_write8(dev, DIO200_CLK_SCE(subpriv->ofs >> 3), byte);
-
-	return 0;
+	dio200_write8(dev, DIO200_GAT_SCE(offset >> 3),
+		      gat_sce((offset >> 2) & 1, chan, src));
  }

-static int dio200_subdev_8254_get_clock_src(struct comedi_device *dev,
-					    struct comedi_subdevice *s,
-					    unsigned int counter_number,
-					    unsigned int *period_ns)
+static void dio200_subdev_8254_set_clock_src(struct comedi_device *dev,
+					     struct comedi_subdevice *s,
+					     unsigned int chan,
+					     unsigned int src)
  {
-	const struct dio200_board *board = dev->board_ptr;
-	struct dio200_subdev_8254 *subpriv = s->private;
-	unsigned clock_src;
-
-	if (!board->has_clk_gat_sce)
-		return -1;
+	unsigned int offset = dio200_subdev_8254_offset(dev, s);

-	clock_src = subpriv->clock_src[counter_number];
-	*period_ns = clock_period[clock_src];
-	return clock_src;
+	dio200_write8(dev, DIO200_CLK_SCE(offset >> 3),
+		      clk_sce((offset >> 2) & 1, chan, src));
  }
[snip]
@@ -686,28 +551,34 @@ static int dio200_subdev_8254_init(struct comedi_device *dev,
  				   unsigned int offset)
  {
  	const struct dio200_board *board = dev->board_ptr;
-	struct dio200_subdev_8254 *subpriv;
-	unsigned int chan;
+	struct comedi_8254 *i8254;
+	unsigned int regshift;
+	int chan;

-	subpriv = comedi_alloc_spriv(s, sizeof(*subpriv));
-	if (!subpriv)
+	regshift = (board->is_pcie) ? 3 : 0;
+
+	if (dev->mmio)
+		i8254 = comedi_8254_mm_init(dev->mmio + offset,
+					    0, I8254_IO8, regshift);
+	else
+		i8254 = comedi_8254_init(dev->iobase + offset,
+					 0, I8254_IO8, regshift);
+	if (!i8254)
  		return -ENOMEM;

-	s->type = COMEDI_SUBD_COUNTER;
-	s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
-	s->n_chan = 3;
-	s->maxdata = 0xFFFF;
-	s->insn_read = dio200_subdev_8254_read;
-	s->insn_write = dio200_subdev_8254_write;
-	s->insn_config = dio200_subdev_8254_config;
+	comedi_8254_subdevice_init(s, i8254);

-	subpriv->ofs = offset;
+	i8254->insn_config = dio200_subdev_8254_config;
+
+	/*
+	 * Set the runflag bit so that the core will autmatically
+	 * kfree(s->private) when the driver is detached.
+	 */
+	s->runflags |= COMEDI_SRF_FREE_SPRIV;

  	/* Initialize channels. */
-	for (chan = 0; chan < 3; chan++) {
-		dio200_subdev_8254_set_mode(dev, s, chan,
-					    I8254_MODE0 | I8254_BINARY);
-		if (board->has_clk_gat_sce) {
+	if (board->has_clk_gat_sce) {
+		for (chan = 0; chan < 3; chan++) {
  			/* Gate source 0 is VCC (logic 1). */
  			dio200_subdev_8254_set_gate_src(dev, s, chan, 0);
  			/* Clock source 0 is the dedicated clock input. */

These are still wrong.  As an example, let's use subdevice 4 of pcie215.

board->sd_type[4] is sd_8254, board->sd_info[4] is 0x10. 0x10 is the offset that gets passed to dio200_subdev_8254_init().

Previously, the 0x10 would be stored in subpriv->ofs. Let's say the insn_read handler is called for one of the three channels. dio200_subdev_8254_read() would call dio200_subdev_8254_read_chan() for the specified channel of the subdevice. The first thing that does is write to the 8254 control register (to latch the counter). To do that it calls dio200_write8() with an offset of subpriv->ofs + i8254_control_reg, which is 0x10 + 3, or 0x13. Since this board has a regshift of 3, dio200_write8() changes the offset to 0x13 << 3, or 0x98. The register written to is at dev->mmio + 0x98.

The new code sets up the 8254 by calling comedi_mm_init() with a base address of dev->mmio + 0x10 and a regshift of 3. So the four registers it accesses will be at dev->mmio + 0x10, dev->mmio + 0x18, dev->mmio + 0x20 and dev->mmio + 0x28. These are all 0x70 less than they should be. The correct base address to pass to comedi_mm_init() is dev->mmio + 0x80, i.e. dev->mmio + (offset << regshift). However, that would cause your dio200_subdev_8254_offset() to return an offset 8 times bigger than it needs to be, so dio200_subdev_8254_offset() should shift the offset right by regshift before returning it.

--
-=( Ian Abbott @ MEV Ltd.    E-mail: <abbotti@xxxxxxxxx> )=-
-=(                          Web: http://www.mev.co.uk/  )=-
_______________________________________________
devel mailing list
devel@xxxxxxxxxxxxxxxxxxxxxx
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel




[Index of Archives]     [Linux Driver Backports]     [DMA Engine]     [Linux GPIO]     [Linux SPI]     [Video for Linux]     [Linux USB Devel]     [Linux Coverity]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux