upload tizen1.0 source
[kernel/linux-2.6.36.git] / drivers / staging / comedi / drivers / mpc8260cpm.c
1 /*
2     comedi/drivers/mpc8260.c
3     driver for digital I/O pins on the MPC 8260 CPM module
4
5     COMEDI - Linux Control and Measurement Device Interface
6     Copyright (C) 2000,2001 David A. Schleef <ds@schleef.org>
7
8     This program is free software; you can redistribute it and/or modify
9     it under the terms of the GNU General Public License as published by
10     the Free Software Foundation; either version 2 of the License, or
11     (at your option) any later version.
12
13     This program is distributed in the hope that it will be useful,
14     but WITHOUT ANY WARRANTY; without even the implied warranty of
15     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16     GNU General Public License for more details.
17
18     You should have received a copy of the GNU General Public License
19     along with this program; if not, write to the Free Software
20     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21
22 */
23 /*
24 Driver: mpc8260cpm
25 Description: MPC8260 CPM module generic digital I/O lines
26 Devices: [Motorola] MPC8260 CPM (mpc8260cpm)
27 Author: ds
28 Status: experimental
29 Updated: Sat, 16 Mar 2002 17:34:48 -0800
30
31 This driver is specific to the Motorola MPC8260 processor, allowing
32 you to access the processor's generic digital I/O lines.
33
34 It is apparently missing some code.
35 */
36
37 #include "../comedidev.h"
38
39 extern unsigned long mpc8260_dio_reserved[4];
40
41 struct mpc8260cpm_private {
42
43         int data;
44
45 };
46
47 #define devpriv ((struct mpc8260cpm_private *)dev->private)
48
49 static int mpc8260cpm_attach(struct comedi_device *dev,
50                              struct comedi_devconfig *it);
51 static int mpc8260cpm_detach(struct comedi_device *dev);
52 static struct comedi_driver driver_mpc8260cpm = {
53         .driver_name = "mpc8260cpm",
54         .module = THIS_MODULE,
55         .attach = mpc8260cpm_attach,
56         .detach = mpc8260cpm_detach,
57 };
58
59 static int __init driver_mpc8260cpm_init_module(void)
60 {
61         return comedi_driver_register(&driver_mpc8260cpm);
62 }
63
64 static void __exit driver_mpc8260cpm_cleanup_module(void)
65 {
66         comedi_driver_unregister(&driver_mpc8260cpm);
67 }
68
69 module_init(driver_mpc8260cpm_init_module);
70 module_exit(driver_mpc8260cpm_cleanup_module);
71
72 static int mpc8260cpm_dio_config(struct comedi_device *dev,
73                                  struct comedi_subdevice *s,
74                                  struct comedi_insn *insn, unsigned int *data);
75 static int mpc8260cpm_dio_bits(struct comedi_device *dev,
76                                struct comedi_subdevice *s,
77                                struct comedi_insn *insn, unsigned int *data);
78
79 static int mpc8260cpm_attach(struct comedi_device *dev,
80                              struct comedi_devconfig *it)
81 {
82         struct comedi_subdevice *s;
83         int i;
84
85         printk("comedi%d: mpc8260cpm: ", dev->minor);
86
87         dev->board_ptr = mpc8260cpm_boards + dev->board;
88
89         dev->board_name = thisboard->name;
90
91         if (alloc_private(dev, sizeof(struct mpc8260cpm_private)) < 0)
92                 return -ENOMEM;
93
94         if (alloc_subdevices(dev, 4) < 0)
95                 return -ENOMEM;
96
97         for (i = 0; i < 4; i++) {
98                 s = dev->subdevices + i;
99                 s->type = COMEDI_SUBD_DIO;
100                 s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
101                 s->n_chan = 32;
102                 s->maxdata = 1;
103                 s->range_table = &range_digital;
104                 s->insn_config = mpc8260cpm_dio_config;
105                 s->insn_bits = mpc8260cpm_dio_bits;
106         }
107
108         return 1;
109 }
110
111 static int mpc8260cpm_detach(struct comedi_device *dev)
112 {
113         printk("comedi%d: mpc8260cpm: remove\n", dev->minor);
114
115         return 0;
116 }
117
118 static unsigned long *cpm_pdat(int port)
119 {
120         switch (port) {
121         case 0:
122                 return &io->iop_pdata;
123         case 1:
124                 return &io->iop_pdatb;
125         case 2:
126                 return &io->iop_pdatc;
127         case 3:
128                 return &io->iop_pdatd;
129         }
130 }
131
132 static int mpc8260cpm_dio_config(struct comedi_device *dev,
133                                  struct comedi_subdevice *s,
134                                  struct comedi_insn *insn, unsigned int *data)
135 {
136         int n;
137         unsigned int d;
138         unsigned int mask;
139         int port;
140
141         port = (int)s->private;
142         mask = 1 << CR_CHAN(insn->chanspec);
143         if (mask & cpm_reserved_bits[port]) {
144                 return -EINVAL;
145         }
146
147         switch (data[0]) {
148         case INSN_CONFIG_DIO_OUTPUT:
149                 s->io_bits |= mask;
150                 break;
151         case INSN_CONFIG_DIO_INPUT:
152                 s->io_bits &= ~mask;
153                 break;
154         case INSN_CONFIG_DIO_QUERY:
155                 data[1] = (s->io_bits & mask) ? COMEDI_OUTPUT : COMEDI_INPUT;
156                 return insn->n;
157                 break;
158         default:
159                 return -EINVAL;
160         }
161
162         switch (port) {
163         case 0:
164                 return &io->iop_pdira;
165         case 1:
166                 return &io->iop_pdirb;
167         case 2:
168                 return &io->iop_pdirc;
169         case 3:
170                 return &io->iop_pdird;
171         }
172
173         return 1;
174 }
175
176 static int mpc8260cpm_dio_bits(struct comedi_device *dev,
177                                struct comedi_subdevice *s,
178                                struct comedi_insn *insn, unsigned int *data)
179 {
180         int port;
181         unsigned long *p;
182
183         p = cpm_pdat((int)s->private);
184
185         return 2;
186 }