Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris...
[sfrench/cifs-2.6.git] / drivers / staging / meilhaus / me8255.c
1 /**
2  * @file me8255.c
3  *
4  * @brief 8255 subdevice instance.
5  * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
6  * @author Guenter Gebhardt
7  */
8
9 /*
10  * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
11  *
12  * This file is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2 of the License, or
15  * (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25  */
26
27 #ifndef __KERNEL__
28 #  define __KERNEL__
29 #endif
30
31 /*
32  * Includes
33  */
34 #include <linux/module.h>
35
36 #include <linux/slab.h>
37 #include <linux/spinlock.h>
38 #include <asm/io.h>
39 #include <linux/types.h>
40
41 #include "medefines.h"
42 #include "meinternal.h"
43 #include "meerror.h"
44 #include "medebug.h"
45
46 #include "me8255_reg.h"
47 #include "me8255.h"
48
49 /*
50  * Defines
51  */
52
53 /*
54  * Functions
55  */
56
57 static uint8_t get_mode_from_mirror(uint32_t mirror)
58 {
59         PDEBUG("executed.\n");
60
61         if (mirror & ME8255_PORT_0_OUTPUT) {
62                 if (mirror & ME8255_PORT_1_OUTPUT) {
63                         if (mirror & ME8255_PORT_2_OUTPUT) {
64                                 return ME8255_MODE_OOO;
65                         } else {
66                                 return ME8255_MODE_IOO;
67                         }
68                 } else {
69                         if (mirror & ME8255_PORT_2_OUTPUT) {
70                                 return ME8255_MODE_OIO;
71                         } else {
72                                 return ME8255_MODE_IIO;
73                         }
74                 }
75         } else {
76                 if (mirror & ME8255_PORT_1_OUTPUT) {
77                         if (mirror & ME8255_PORT_2_OUTPUT) {
78                                 return ME8255_MODE_OOI;
79                         } else {
80                                 return ME8255_MODE_IOI;
81                         }
82                 } else {
83                         if (mirror & ME8255_PORT_2_OUTPUT) {
84                                 return ME8255_MODE_OII;
85                         } else {
86                                 return ME8255_MODE_III;
87                         }
88                 }
89         }
90 }
91
92 static int me8255_io_reset_subdevice(struct me_subdevice *subdevice,
93                                      struct file *filep, int flags)
94 {
95         me8255_subdevice_t *instance;
96
97         PDEBUG("executed.\n");
98
99         instance = (me8255_subdevice_t *) subdevice;
100
101         if (flags) {
102                 PERROR("Invalid flag specified.\n");
103                 return ME_ERRNO_INVALID_FLAGS;
104         }
105
106         ME_SUBDEVICE_ENTER;
107
108         spin_lock(&instance->subdevice_lock);
109         spin_lock(instance->ctrl_reg_lock);
110         *instance->ctrl_reg_mirror &=
111             ~(ME8255_PORT_0_OUTPUT << instance->dio_idx);
112         outb(get_mode_from_mirror(*instance->ctrl_reg_mirror),
113              instance->ctrl_reg);
114         spin_unlock(instance->ctrl_reg_lock);
115
116         outb(0, instance->port_reg);
117         spin_unlock(&instance->subdevice_lock);
118
119         ME_SUBDEVICE_EXIT;
120
121         return ME_ERRNO_SUCCESS;
122 }
123
124 static int me8255_io_single_config(struct me_subdevice *subdevice,
125                                    struct file *filep,
126                                    int channel,
127                                    int single_config,
128                                    int ref,
129                                    int trig_chan,
130                                    int trig_type, int trig_edge, int flags)
131 {
132         me8255_subdevice_t *instance;
133         int err = ME_ERRNO_SUCCESS;
134
135         PDEBUG("executed.\n");
136
137         instance = (me8255_subdevice_t *) subdevice;
138
139         if (flags & ~ME_IO_SINGLE_CONFIG_DIO_BYTE) {
140                 PERROR("Invalid flag specified.\n");
141                 return ME_ERRNO_INVALID_FLAGS;
142         }
143
144         if (channel) {
145                 PERROR("Invalid channel.\n");
146                 return ME_ERRNO_INVALID_CHANNEL;
147         }
148
149         ME_SUBDEVICE_ENTER;
150
151         spin_lock(&instance->subdevice_lock);
152         if (single_config == ME_SINGLE_CONFIG_DIO_INPUT) {
153                 spin_lock(instance->ctrl_reg_lock);
154                 *instance->ctrl_reg_mirror &=
155                     ~(ME8255_PORT_0_OUTPUT << instance->dio_idx);
156                 outb(get_mode_from_mirror(*instance->ctrl_reg_mirror),
157                      instance->ctrl_reg);
158                 spin_unlock(instance->ctrl_reg_lock);
159         } else if (single_config == ME_SINGLE_CONFIG_DIO_OUTPUT) {
160                 spin_lock(instance->ctrl_reg_lock);
161                 *instance->ctrl_reg_mirror |=
162                     (ME8255_PORT_0_OUTPUT << instance->dio_idx);
163                 outb(get_mode_from_mirror(*instance->ctrl_reg_mirror),
164                      instance->ctrl_reg);
165                 spin_unlock(instance->ctrl_reg_lock);
166         } else {
167                 PERROR("Invalid port direction.\n");
168                 err = ME_ERRNO_INVALID_SINGLE_CONFIG;
169         }
170         spin_unlock(&instance->subdevice_lock);
171
172         ME_SUBDEVICE_EXIT;
173
174         return err;
175 }
176
177 static int me8255_io_single_read(struct me_subdevice *subdevice,
178                                  struct file *filep,
179                                  int channel,
180                                  int *value, int time_out, int flags)
181 {
182         me8255_subdevice_t *instance;
183         int err = ME_ERRNO_SUCCESS;
184
185         PDEBUG("executed.\n");
186
187         instance = (me8255_subdevice_t *) subdevice;
188
189         ME_SUBDEVICE_ENTER;
190
191         spin_lock(&instance->subdevice_lock);
192         switch (flags) {
193         case ME_IO_SINGLE_TYPE_DIO_BIT:
194                 if ((channel >= 0) && (channel < 8)) {
195                         *value = inb(instance->port_reg) & (0x1 << channel);
196                 } else {
197                         PERROR("Invalid bit number.\n");
198                         err = ME_ERRNO_INVALID_CHANNEL;
199                 }
200                 break;
201
202         case ME_IO_SINGLE_NO_FLAGS:
203         case ME_IO_SINGLE_TYPE_DIO_BYTE:
204                 if (channel == 0) {
205                         *value = inb(instance->port_reg);
206                 } else {
207                         PERROR("Invalid byte number.\n");
208                         err = ME_ERRNO_INVALID_CHANNEL;
209                 }
210                 break;
211
212         default:
213                 PERROR("Invalid flags specified.\n");
214                 err = ME_ERRNO_INVALID_FLAGS;
215         }
216         spin_unlock(&instance->subdevice_lock);
217
218         ME_SUBDEVICE_EXIT;
219
220         return err;
221 }
222
223 static int me8255_io_single_write(struct me_subdevice *subdevice,
224                                   struct file *filep,
225                                   int channel,
226                                   int value, int time_out, int flags)
227 {
228         me8255_subdevice_t *instance;
229         uint8_t byte;
230         int err = ME_ERRNO_SUCCESS;
231
232         PDEBUG("executed.\n");
233
234         instance = (me8255_subdevice_t *) subdevice;
235
236         ME_SUBDEVICE_ENTER;
237
238         spin_lock(&instance->subdevice_lock);
239         switch (flags) {
240         case ME_IO_SINGLE_TYPE_DIO_BIT:
241                 if ((channel >= 0) && (channel < 8)) {
242                         if (*instance->
243                             ctrl_reg_mirror & (ME8255_PORT_0_OUTPUT <<
244                                                instance->dio_idx)) {
245                                 byte = inb(instance->port_reg);
246
247                                 if (value)
248                                         byte |= 0x1 << channel;
249                                 else
250                                         byte &= ~(0x1 << channel);
251
252                                 outb(byte, instance->port_reg);
253                         } else {
254                                 PERROR("Port not in output mode.\n");
255                                 err = ME_ERRNO_PREVIOUS_CONFIG;
256                         }
257                 } else {
258                         PERROR("Invalid bit number.\n");
259                         err = ME_ERRNO_INVALID_CHANNEL;
260                 }
261                 break;
262
263         case ME_IO_SINGLE_NO_FLAGS:
264         case ME_IO_SINGLE_TYPE_DIO_BYTE:
265                 if (channel == 0) {
266                         if (*instance->
267                             ctrl_reg_mirror & (ME8255_PORT_0_OUTPUT <<
268                                                instance->dio_idx)) {
269                                 outb(value, instance->port_reg);
270                         } else {
271                                 PERROR("Port not in output mode.\n");
272                                 err = ME_ERRNO_PREVIOUS_CONFIG;
273                         }
274                 } else {
275                         PERROR("Invalid byte number.\n");
276                         err = ME_ERRNO_INVALID_CHANNEL;
277                 }
278                 break;
279
280         default:
281                 PERROR("Invalid flags specified.\n");
282                 err = ME_ERRNO_INVALID_FLAGS;
283         }
284         spin_unlock(&instance->subdevice_lock);
285
286         ME_SUBDEVICE_EXIT;
287
288         return err;
289 }
290
291 static int me8255_query_number_channels(struct me_subdevice *subdevice,
292                                         int *number)
293 {
294         PDEBUG("executed.\n");
295         *number = ME8255_NUMBER_CHANNELS;
296         return ME_ERRNO_SUCCESS;
297 }
298
299 static int me8255_query_subdevice_type(struct me_subdevice *subdevice,
300                                        int *type, int *subtype)
301 {
302         PDEBUG("executed.\n");
303         *type = ME_TYPE_DIO;
304         *subtype = ME_SUBTYPE_SINGLE;
305         return ME_ERRNO_SUCCESS;
306 }
307
308 static int me8255_query_subdevice_caps(struct me_subdevice *subdevice,
309                                        int *caps)
310 {
311         PDEBUG("executed.\n");
312         *caps = ME_CAPS_DIO_DIR_BYTE;
313         return ME_ERRNO_SUCCESS;
314 }
315
316 me8255_subdevice_t *me8255_constructor(uint32_t device_id,
317                                        uint32_t reg_base,
318                                        unsigned int me8255_idx,
319                                        unsigned int dio_idx,
320                                        int *ctrl_reg_mirror,
321                                        spinlock_t * ctrl_reg_lock)
322 {
323         me8255_subdevice_t *subdevice;
324         int err;
325
326         PDEBUG("executed.\n");
327
328         /* Allocate memory for subdevice instance */
329         subdevice = kmalloc(sizeof(me8255_subdevice_t), GFP_KERNEL);
330
331         if (!subdevice) {
332                 PERROR("Cannot get memory for 8255 instance.\n");
333                 return NULL;
334         }
335
336         memset(subdevice, 0, sizeof(me8255_subdevice_t));
337
338         /* Check if counter index is out of range */
339
340         if (dio_idx > 2) {
341                 PERROR("DIO index is out of range.\n");
342                 kfree(subdevice);
343                 return NULL;
344         }
345
346         /* Initialize subdevice base class */
347         err = me_subdevice_init(&subdevice->base);
348
349         if (err) {
350                 PERROR("Cannot initialize subdevice base class instance.\n");
351                 kfree(subdevice);
352                 return NULL;
353         }
354         // Initialize spin locks.
355         spin_lock_init(&subdevice->subdevice_lock);
356
357         subdevice->ctrl_reg_lock = ctrl_reg_lock;
358
359         /* Save the pointer to global port settings */
360         subdevice->ctrl_reg_mirror = ctrl_reg_mirror;
361
362         /* Save type of Meilhaus device */
363         subdevice->device_id = device_id;
364
365         /* Save the indices */
366         subdevice->me8255_idx = me8255_idx;
367         subdevice->dio_idx = dio_idx;
368
369         /* Do device specific initialization */
370         switch (device_id) {
371         case PCI_DEVICE_ID_MEILHAUS_ME1400:
372         case PCI_DEVICE_ID_MEILHAUS_ME14E0:
373
374         case PCI_DEVICE_ID_MEILHAUS_ME140A:
375         case PCI_DEVICE_ID_MEILHAUS_ME14EA:
376                 /* Check if 8255 index is out of range */
377                 if (me8255_idx > 0) {
378                         PERROR("8255 index is out of range.\n");
379                         me_subdevice_deinit(&subdevice->base);
380                         kfree(subdevice);
381                         return NULL;
382                 }
383
384         case PCI_DEVICE_ID_MEILHAUS_ME140B:     /* Fall through */
385         case PCI_DEVICE_ID_MEILHAUS_ME14EB:
386                 /* Check if 8255 index is out of range */
387                 if (me8255_idx > 1) {
388                         PERROR("8255 index is out of range.\n");
389                         me_subdevice_deinit(&subdevice->base);
390                         kfree(subdevice);
391                         return NULL;
392                 }
393
394                 /* Get the registers */
395                 if (me8255_idx == 0) {
396                         subdevice->ctrl_reg = reg_base + ME1400AB_PORT_A_CTRL;
397                         subdevice->port_reg =
398                             reg_base + ME1400AB_PORT_A_0 + dio_idx;
399                 } else if (me8255_idx == 1) {
400                         subdevice->ctrl_reg = reg_base + ME1400AB_PORT_B_CTRL;
401                         subdevice->port_reg =
402                             reg_base + ME1400AB_PORT_B_0 + dio_idx;
403                 }
404
405                 break;
406
407         case PCI_DEVICE_ID_MEILHAUS_ME140C:
408                 /* Check if 8255 index is out of range */
409                 if (me8255_idx > 0) {
410                         PERROR("8255 index is out of range.\n");
411                         me_subdevice_deinit(&subdevice->base);
412                         kfree(subdevice);
413                         return NULL;
414                 }
415
416         case PCI_DEVICE_ID_MEILHAUS_ME140D:     /* Fall through */
417                 /* Check if 8255 index is out of range */
418                 if (me8255_idx > 1) {
419                         PERROR("8255 index is out of range.\n");
420                         me_subdevice_deinit(&subdevice->base);
421                         kfree(subdevice);
422                         return NULL;
423                 }
424
425                 /* Get the registers */
426                 if (me8255_idx == 0) {
427                         subdevice->ctrl_reg = reg_base + ME1400CD_PORT_A_CTRL;
428                         subdevice->port_reg =
429                             reg_base + ME1400CD_PORT_A_0 + dio_idx;
430                 } else if (me8255_idx == 1) {
431                         subdevice->ctrl_reg = reg_base + ME1400CD_PORT_B_CTRL;
432                         subdevice->port_reg =
433                             reg_base + ME1400CD_PORT_B_0 + dio_idx;
434                 }
435
436                 break;
437
438         default:
439                 PERROR("Unknown device type. dev ID: 0x%04x\n", device_id);
440
441                 me_subdevice_deinit(&subdevice->base);
442
443                 kfree(subdevice);
444
445                 return NULL;
446         }
447
448         /* Overload subdevice base class methods. */
449         subdevice->base.me_subdevice_io_reset_subdevice =
450             me8255_io_reset_subdevice;
451         subdevice->base.me_subdevice_io_single_config = me8255_io_single_config;
452         subdevice->base.me_subdevice_io_single_read = me8255_io_single_read;
453         subdevice->base.me_subdevice_io_single_write = me8255_io_single_write;
454         subdevice->base.me_subdevice_query_number_channels =
455             me8255_query_number_channels;
456         subdevice->base.me_subdevice_query_subdevice_type =
457             me8255_query_subdevice_type;
458         subdevice->base.me_subdevice_query_subdevice_caps =
459             me8255_query_subdevice_caps;
460
461         return subdevice;
462 }