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

Ian Abbott abbotti at mev.co.uk
Tue Feb 24 13:20:25 UTC 2015


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 at visionengravers.com>
> Cc: Ian Abbott <abbotti at mev.co.uk>
> Cc: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
> ---
> 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 at mev.co.uk> )=-
-=(                          Web: http://www.mev.co.uk/  )=-


More information about the devel mailing list