13124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef/*
23124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef    comedi/drivers/mpc8260.c
33124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef    driver for digital I/O pins on the MPC 8260 CPM module
43124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef
53124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef    COMEDI - Linux Control and Measurement Device Interface
63124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef    Copyright (C) 2000,2001 David A. Schleef <ds@schleef.org>
73124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef
83124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef    This program is free software; you can redistribute it and/or modify
93124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef    it under the terms of the GNU General Public License as published by
103124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef    the Free Software Foundation; either version 2 of the License, or
113124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef    (at your option) any later version.
123124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef
133124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef    This program is distributed in the hope that it will be useful,
143124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef    but WITHOUT ANY WARRANTY; without even the implied warranty of
153124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
163124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef    GNU General Public License for more details.
173124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef
183124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef    You should have received a copy of the GNU General Public License
193124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef    along with this program; if not, write to the Free Software
203124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
213124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef
223124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef*/
233124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef/*
243124dd1cba314da1482540bc805d2054b449ce4bDavid SchleefDriver: mpc8260cpm
253124dd1cba314da1482540bc805d2054b449ce4bDavid SchleefDescription: MPC8260 CPM module generic digital I/O lines
263124dd1cba314da1482540bc805d2054b449ce4bDavid SchleefDevices: [Motorola] MPC8260 CPM (mpc8260cpm)
273124dd1cba314da1482540bc805d2054b449ce4bDavid SchleefAuthor: ds
283124dd1cba314da1482540bc805d2054b449ce4bDavid SchleefStatus: experimental
293124dd1cba314da1482540bc805d2054b449ce4bDavid SchleefUpdated: Sat, 16 Mar 2002 17:34:48 -0800
303124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef
313124dd1cba314da1482540bc805d2054b449ce4bDavid SchleefThis driver is specific to the Motorola MPC8260 processor, allowing
323124dd1cba314da1482540bc805d2054b449ce4bDavid Schleefyou to access the processor's generic digital I/O lines.
333124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef
343124dd1cba314da1482540bc805d2054b449ce4bDavid SchleefIt is apparently missing some code.
353124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef*/
363124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef
373124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef#include "../comedidev.h"
383124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef
393124dd1cba314da1482540bc805d2054b449ce4bDavid Schleefextern unsigned long mpc8260_dio_reserved[4];
403124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef
416555be0a1c25576be6270bb43f1bd444df7d86f8Bill Pembertonstruct mpc8260cpm_private {
426555be0a1c25576be6270bb43f1bd444df7d86f8Bill Pemberton
433124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef	int data;
443124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef
456555be0a1c25576be6270bb43f1bd444df7d86f8Bill Pemberton};
466555be0a1c25576be6270bb43f1bd444df7d86f8Bill Pemberton
476555be0a1c25576be6270bb43f1bd444df7d86f8Bill Pemberton#define devpriv ((struct mpc8260cpm_private *)dev->private)
483124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef
490a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int mpc8260cpm_attach(struct comedi_device *dev,
500a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     struct comedi_devconfig *it);
51da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int mpc8260cpm_detach(struct comedi_device *dev);
52139dfbdfacb02e3ef3df936d2fabd1ad5f14ea88Bill Pembertonstatic struct comedi_driver driver_mpc8260cpm = {
5368c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.driver_name = "mpc8260cpm",
5468c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.module = THIS_MODULE,
5568c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.attach = mpc8260cpm_attach,
5668c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.detach = mpc8260cpm_detach,
573124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef};
583124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef
597114a28011f9d5f3d981731ad341177c21f9d948Arun Thomasstatic int __init driver_mpc8260cpm_init_module(void)
607114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas{
617114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas	return comedi_driver_register(&driver_mpc8260cpm);
627114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas}
637114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas
647114a28011f9d5f3d981731ad341177c21f9d948Arun Thomasstatic void __exit driver_mpc8260cpm_cleanup_module(void)
657114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas{
667114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas	comedi_driver_unregister(&driver_mpc8260cpm);
677114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas}
687114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas
697114a28011f9d5f3d981731ad341177c21f9d948Arun Thomasmodule_init(driver_mpc8260cpm_init_module);
707114a28011f9d5f3d981731ad341177c21f9d948Arun Thomasmodule_exit(driver_mpc8260cpm_cleanup_module);
713124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef
720a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int mpc8260cpm_dio_config(struct comedi_device *dev,
730a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				 struct comedi_subdevice *s,
740a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				 struct comedi_insn *insn, unsigned int *data);
750a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int mpc8260cpm_dio_bits(struct comedi_device *dev,
760a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			       struct comedi_subdevice *s,
770a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			       struct comedi_insn *insn, unsigned int *data);
783124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef
790a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int mpc8260cpm_attach(struct comedi_device *dev,
800a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     struct comedi_devconfig *it)
813124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef{
8234c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton	struct comedi_subdevice *s;
833124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef	int i;
843124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef
853124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef	printk("comedi%d: mpc8260cpm: ", dev->minor);
863124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef
873124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef	dev->board_ptr = mpc8260cpm_boards + dev->board;
883124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef
893124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef	dev->board_name = thisboard->name;
903124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef
916555be0a1c25576be6270bb43f1bd444df7d86f8Bill Pemberton	if (alloc_private(dev, sizeof(struct mpc8260cpm_private)) < 0)
923124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef		return -ENOMEM;
933124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef
943124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef	if (alloc_subdevices(dev, 4) < 0)
953124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef		return -ENOMEM;
963124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef
973124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef	for (i = 0; i < 4; i++) {
983124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef		s = dev->subdevices + i;
993124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef		s->type = COMEDI_SUBD_DIO;
1003124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef		s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
1013124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef		s->n_chan = 32;
1023124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef		s->maxdata = 1;
1033124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef		s->range_table = &range_digital;
1043124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef		s->insn_config = mpc8260cpm_dio_config;
1053124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef		s->insn_bits = mpc8260cpm_dio_bits;
1063124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef	}
1073124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef
1083124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef	return 1;
1093124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef}
1103124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef
111da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int mpc8260cpm_detach(struct comedi_device *dev)
1123124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef{
1133124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef	printk("comedi%d: mpc8260cpm: remove\n", dev->minor);
1143124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef
1153124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef	return 0;
1163124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef}
1173124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef
1183124dd1cba314da1482540bc805d2054b449ce4bDavid Schleefstatic unsigned long *cpm_pdat(int port)
1193124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef{
1203124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef	switch (port) {
1213124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef	case 0:
1223124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef		return &io->iop_pdata;
1233124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef	case 1:
1243124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef		return &io->iop_pdatb;
1253124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef	case 2:
1263124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef		return &io->iop_pdatc;
1273124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef	case 3:
1283124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef		return &io->iop_pdatd;
1293124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef	}
1303124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef}
1313124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef
1320a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int mpc8260cpm_dio_config(struct comedi_device *dev,
1330a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				 struct comedi_subdevice *s,
1340a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				 struct comedi_insn *insn, unsigned int *data)
1353124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef{
1363124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef	int n;
1373124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef	unsigned int d;
1383124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef	unsigned int mask;
1393124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef	int port;
1403124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef
1413124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef	port = (int)s->private;
1423124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef	mask = 1 << CR_CHAN(insn->chanspec);
1433124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef	if (mask & cpm_reserved_bits[port]) {
1443124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef		return -EINVAL;
1453124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef	}
1463124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef
1473124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef	switch (data[0]) {
1483124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef	case INSN_CONFIG_DIO_OUTPUT:
1493124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef		s->io_bits |= mask;
1503124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef		break;
1513124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef	case INSN_CONFIG_DIO_INPUT:
1523124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef		s->io_bits &= ~mask;
1533124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef		break;
1543124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef	case INSN_CONFIG_DIO_QUERY:
1553124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef		data[1] = (s->io_bits & mask) ? COMEDI_OUTPUT : COMEDI_INPUT;
1563124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef		return insn->n;
1573124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef		break;
1583124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef	default:
1593124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef		return -EINVAL;
1603124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef	}
1613124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef
1623124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef	switch (port) {
1633124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef	case 0:
1643124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef		return &io->iop_pdira;
1653124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef	case 1:
1663124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef		return &io->iop_pdirb;
1673124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef	case 2:
1683124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef		return &io->iop_pdirc;
1693124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef	case 3:
1703124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef		return &io->iop_pdird;
1713124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef	}
1723124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef
1733124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef	return 1;
1743124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef}
1753124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef
1760a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int mpc8260cpm_dio_bits(struct comedi_device *dev,
1770a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			       struct comedi_subdevice *s,
1780a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			       struct comedi_insn *insn, unsigned int *data)
1793124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef{
1803124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef	int port;
1813124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef	unsigned long *p;
1823124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef
1833124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef	p = cpm_pdat((int)s->private);
1843124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef
1853124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef	return 2;
1863124dd1cba314da1482540bc805d2054b449ce4bDavid Schleef}
187