Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e4eae7c0 authored by H Hartley Sweeten's avatar H Hartley Sweeten Committed by Greg Kroah-Hartman
Browse files

staging: comedi: pcmuio: introduce pcmuio_write()



Introduce a helper function to handle writing a 24-bit value to the
three 8-bit registers associated with a "port" or "page".

Signed-off-by: default avatarH Hartley Sweeten <hsweeten@visionengravers.com>
Reviewed-by: default avatarIan Abbott <abbotti@mev.co.uk>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 46317da7
Loading
Loading
Loading
Loading
+32 −50
Original line number Original line Diff line number Diff line
@@ -126,8 +126,6 @@
#define PCMUIO96_IOSIZE		(ASIC_IOSIZE * 2)
#define PCMUIO96_IOSIZE		(ASIC_IOSIZE * 2)


#define NUM_PAGED_REGS		3
#define NUM_PAGED_REGS		3
#define NUM_PAGES		4
#define FIRST_PAGED_REG		0x8


struct pcmuio_board {
struct pcmuio_board {
	const char *name;
	const char *name;
@@ -194,6 +192,24 @@ struct pcmuio_private {
	struct pcmuio_subdev_private *sprivs;
	struct pcmuio_subdev_private *sprivs;
};
};


static void pcmuio_write(struct comedi_device *dev, unsigned int val,
			 int asic, int page, int port)
{
	unsigned long iobase = dev->iobase + (asic * ASIC_IOSIZE);

	if (page == 0) {
		/* Port registers are valid for any page */
		outb(val & 0xff, iobase + PCMUIO_PORT_REG(port + 0));
		outb((val >> 8) & 0xff, iobase + PCMUIO_PORT_REG(port + 1));
		outb((val >> 16) & 0xff, iobase + PCMUIO_PORT_REG(port + 2));
	} else {
		outb(PCMUIO_PAGE(page), iobase + PCMUIO_PAGE_LOCK_REG);
		outb(val & 0xff, iobase + PCMUIO_PAGE_REG(0));
		outb((val >> 8) & 0xff, iobase + PCMUIO_PAGE_REG(1));
		outb((val >> 16) & 0xff, iobase + PCMUIO_PAGE_REG(2));
	}
}

static int pcmuio_dio_insn_bits(struct comedi_device *dev,
static int pcmuio_dio_insn_bits(struct comedi_device *dev,
				struct comedi_subdevice *s,
				struct comedi_subdevice *s,
				struct comedi_insn *insn, unsigned int *data)
				struct comedi_insn *insn, unsigned int *data)
@@ -315,42 +331,27 @@ static void switch_page(struct comedi_device *dev, int asic, int page)
}
}


static void init_asics(struct comedi_device *dev)
static void init_asics(struct comedi_device *dev)
{				/* sets up an
{
				   ASIC chip to defaults */
	const struct pcmuio_board *board = comedi_board(dev);
	const struct pcmuio_board *board = comedi_board(dev);
	int asic;
	int asic;


	for (asic = 0; asic < board->num_asics; ++asic) {
	for (asic = 0; asic < board->num_asics; ++asic) {
		int port, page;
		unsigned long baseaddr = dev->iobase + asic * ASIC_IOSIZE;

		switch_page(dev, asic, 0);	/* switch back to page 0 */

		/* first, clear all the DIO port bits */
		/* first, clear all the DIO port bits */
		for (port = 0; port < PORTS_PER_ASIC; ++port)
		pcmuio_write(dev, 0, asic, 0, 0);
			outb(0, baseaddr + PCMUIO_PORT_REG(port));
		pcmuio_write(dev, 0, asic, 0, 3);


		/* Next, clear all the paged registers for each page */
		/* Next, clear all the paged registers for each page */
		for (page = 1; page < NUM_PAGES; ++page) {
		pcmuio_write(dev, 0, asic, PCMUIO_PAGE_POL, 0);
			int reg;
		pcmuio_write(dev, 0, asic, PCMUIO_PAGE_ENAB, 0);
			/* now clear all the paged registers */
		pcmuio_write(dev, 0, asic, PCMUIO_PAGE_INT_ID, 0);
			switch_page(dev, asic, page);
			for (reg = FIRST_PAGED_REG;
			     reg < FIRST_PAGED_REG + NUM_PAGED_REGS; ++reg)
				outb(0, baseaddr + reg);
		}

		/* switch back to default page 0 */
		switch_page(dev, asic, 0);
	}
	}
}
}


static void pcmuio_stop_intr(struct comedi_device *dev,
static void pcmuio_stop_intr(struct comedi_device *dev,
			     struct comedi_subdevice *s)
			     struct comedi_subdevice *s)
{
{
	struct pcmuio_private *devpriv = dev->private;
	struct pcmuio_subdev_private *subpriv = s->private;
	struct pcmuio_subdev_private *subpriv = s->private;
	int nports, firstport, asic, port;
	int asic;


	asic = subpriv->intr.asic;
	asic = subpriv->intr.asic;
	if (asic < 0)
	if (asic < 0)
@@ -359,13 +360,9 @@ static void pcmuio_stop_intr(struct comedi_device *dev,
	subpriv->intr.enabled_mask = 0;
	subpriv->intr.enabled_mask = 0;
	subpriv->intr.active = 0;
	subpriv->intr.active = 0;
	s->async->inttrig = NULL;
	s->async->inttrig = NULL;
	nports = subpriv->intr.num_asic_chans / CHANS_PER_PORT;

	firstport = subpriv->intr.asic_chan / CHANS_PER_PORT;
	switch_page(dev, asic, PCMUIO_PAGE_ENAB);
	for (port = firstport; port < firstport + nports; ++port) {
	/* disable all intrs for this subdev.. */
	/* disable all intrs for this subdev.. */
		outb(0, devpriv->asics[asic].iobase + PCMUIO_PAGE_REG(port));
	pcmuio_write(dev, 0, asic, PCMUIO_PAGE_ENAB, 0);
	}
}
}


static void pcmuio_handle_intr_subdev(struct comedi_device *dev,
static void pcmuio_handle_intr_subdev(struct comedi_device *dev,
@@ -503,7 +500,6 @@ static irqreturn_t interrupt_pcmuio(int irq, void *d)
static int pcmuio_start_intr(struct comedi_device *dev,
static int pcmuio_start_intr(struct comedi_device *dev,
			     struct comedi_subdevice *s)
			     struct comedi_subdevice *s)
{
{
	struct pcmuio_private *devpriv = dev->private;
	struct pcmuio_subdev_private *subpriv = s->private;
	struct pcmuio_subdev_private *subpriv = s->private;


	if (!subpriv->intr.continuous && subpriv->intr.stop_count == 0) {
	if (!subpriv->intr.continuous && subpriv->intr.stop_count == 0) {
@@ -513,7 +509,7 @@ static int pcmuio_start_intr(struct comedi_device *dev,
		return 1;
		return 1;
	} else {
	} else {
		unsigned bits = 0, pol_bits = 0, n;
		unsigned bits = 0, pol_bits = 0, n;
		int nports, firstport, asic, port;
		int asic;
		struct comedi_cmd *cmd = &s->async->cmd;
		struct comedi_cmd *cmd = &s->async->cmd;


		asic = subpriv->intr.asic;
		asic = subpriv->intr.asic;
@@ -522,8 +518,6 @@ static int pcmuio_start_intr(struct comedi_device *dev,
					   subdev */
					   subdev */
		subpriv->intr.enabled_mask = 0;
		subpriv->intr.enabled_mask = 0;
		subpriv->intr.active = 1;
		subpriv->intr.active = 1;
		nports = subpriv->intr.num_asic_chans / CHANS_PER_PORT;
		firstport = subpriv->intr.asic_chan / CHANS_PER_PORT;
		if (cmd->chanlist) {
		if (cmd->chanlist) {
			for (n = 0; n < cmd->chanlist_len; n++) {
			for (n = 0; n < cmd->chanlist_len; n++) {
				bits |= (1U << CR_CHAN(cmd->chanlist[n]));
				bits |= (1U << CR_CHAN(cmd->chanlist[n]));
@@ -537,21 +531,9 @@ static int pcmuio_start_intr(struct comedi_device *dev,
			 1) << subpriv->intr.first_chan;
			 1) << subpriv->intr.first_chan;
		subpriv->intr.enabled_mask = bits;
		subpriv->intr.enabled_mask = bits;


		switch_page(dev, asic, PCMUIO_PAGE_ENAB);
		/* set pol and enab intrs for this subdev.. */
		for (port = firstport; port < firstport + nports; ++port) {
		pcmuio_write(dev, pol_bits, asic, PCMUIO_PAGE_POL, 0);
			unsigned enab =
		pcmuio_write(dev, bits, asic, PCMUIO_PAGE_ENAB, 0);
			    bits >> (subpriv->intr.first_chan + (port -
								 firstport) *
				     8) & 0xff, pol =
			    pol_bits >> (subpriv->intr.first_chan +
					 (port - firstport) * 8) & 0xff;
			/* set enab intrs for this subdev.. */
			outb(enab,
			     devpriv->asics[asic].iobase + PCMUIO_PAGE_REG(port));
			switch_page(dev, asic, PCMUIO_PAGE_POL);
			outb(pol,
			     devpriv->asics[asic].iobase + PCMUIO_PAGE_REG(port));
		}
	}
	}
	return 0;
	return 0;
}
}