Commit | Line | Data |
---|---|---|
3124dd1c DS |
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 | ||
6555be0a BP |
41 | struct mpc8260cpm_private { |
42 | ||
3124dd1c DS |
43 | int data; |
44 | ||
6555be0a BP |
45 | }; |
46 | ||
47 | #define devpriv ((struct mpc8260cpm_private *)dev->private) | |
3124dd1c | 48 | |
0a85b6f0 MT |
49 | static int mpc8260cpm_attach(struct comedi_device *dev, |
50 | struct comedi_devconfig *it); | |
da91b269 | 51 | static int mpc8260cpm_detach(struct comedi_device *dev); |
139dfbdf | 52 | static struct comedi_driver driver_mpc8260cpm = { |
68c3dbff BP |
53 | .driver_name = "mpc8260cpm", |
54 | .module = THIS_MODULE, | |
55 | .attach = mpc8260cpm_attach, | |
56 | .detach = mpc8260cpm_detach, | |
3124dd1c DS |
57 | }; |
58 | ||
7114a280 AT |
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); | |
3124dd1c | 71 | |
0a85b6f0 MT |
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); | |
3124dd1c | 78 | |
0a85b6f0 MT |
79 | static int mpc8260cpm_attach(struct comedi_device *dev, |
80 | struct comedi_devconfig *it) | |
3124dd1c | 81 | { |
34c43922 | 82 | struct comedi_subdevice *s; |
3124dd1c DS |
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 | ||
6555be0a | 91 | if (alloc_private(dev, sizeof(struct mpc8260cpm_private)) < 0) |
3124dd1c DS |
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 | ||
da91b269 | 111 | static int mpc8260cpm_detach(struct comedi_device *dev) |
3124dd1c DS |
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 | ||
0a85b6f0 MT |
132 | static int mpc8260cpm_dio_config(struct comedi_device *dev, |
133 | struct comedi_subdevice *s, | |
134 | struct comedi_insn *insn, unsigned int *data) | |
3124dd1c DS |
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 | ||
0a85b6f0 MT |
176 | static int mpc8260cpm_dio_bits(struct comedi_device *dev, |
177 | struct comedi_subdevice *s, | |
178 | struct comedi_insn *insn, unsigned int *data) | |
3124dd1c DS |
179 | { |
180 | int port; | |
181 | unsigned long *p; | |
182 | ||
183 | p = cpm_pdat((int)s->private); | |
184 | ||
185 | return 2; | |
186 | } |