• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * @file me4600_dio.c
3  *
4  * @brief ME-4000 digital input/output subdevice instance.
5  * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
6  * @author Guenter Gebhardt
7  * @author Krzysztof Gantzke	(k.gantzke@meilhaus.de)
8  */
9 
10 /*
11  * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
12  *
13  * This file is free software; you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License as published by
15  * the Free Software Foundation; either version 2 of the License, or
16  * (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26  */
27 
28 #ifndef __KERNEL__
29 #  define __KERNEL__
30 #endif
31 
32 /*
33  * Includes
34  */
35 #include <linux/module.h>
36 
37 #include <linux/slab.h>
38 #include <linux/spinlock.h>
39 #include <asm/io.h>
40 #include <linux/types.h>
41 
42 #include "medefines.h"
43 #include "meinternal.h"
44 #include "meerror.h"
45 
46 #include "medebug.h"
47 #include "me4600_dio_reg.h"
48 #include "me4600_dio.h"
49 
50 /*
51  * Defines
52  */
53 
54 /*
55  * Functions
56  */
57 
me4600_dio_io_reset_subdevice(struct me_subdevice * subdevice,struct file * filep,int flags)58 static int me4600_dio_io_reset_subdevice(struct me_subdevice *subdevice,
59 					 struct file *filep, int flags)
60 {
61 	me4600_dio_subdevice_t *instance;
62 	uint32_t mode;
63 
64 	PDEBUG("executed.\n");
65 
66 	instance = (me4600_dio_subdevice_t *) subdevice;
67 
68 	if (flags) {
69 		PERROR("Invalid flag specified.\n");
70 		return ME_ERRNO_INVALID_FLAGS;
71 	}
72 
73 	ME_SUBDEVICE_ENTER;
74 
75 	/* Set port to input mode */
76 	spin_lock(&instance->subdevice_lock);
77 	spin_lock(instance->ctrl_reg_lock);
78 	mode = inl(instance->ctrl_reg);
79 	mode &=
80 	    ~((ME4600_DIO_CTRL_BIT_MODE_0 | ME4600_DIO_CTRL_BIT_MODE_1) <<
81 	      (instance->dio_idx * 2));
82 	outl(mode, instance->ctrl_reg);
83 	PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
84 		   instance->ctrl_reg - instance->reg_base, mode);
85 	spin_unlock(instance->ctrl_reg_lock);
86 
87 	outl(0, instance->port_reg);
88 	PDEBUG_REG("port_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
89 		   instance->port_reg - instance->reg_base, 0);
90 	spin_unlock(&instance->subdevice_lock);
91 
92 	ME_SUBDEVICE_EXIT;
93 
94 	return ME_ERRNO_SUCCESS;
95 }
96 
me4600_dio_io_single_config(me_subdevice_t * subdevice,struct file * filep,int channel,int single_config,int ref,int trig_chan,int trig_type,int trig_edge,int flags)97 static int me4600_dio_io_single_config(me_subdevice_t * subdevice,
98 				       struct file *filep,
99 				       int channel,
100 				       int single_config,
101 				       int ref,
102 				       int trig_chan,
103 				       int trig_type, int trig_edge, int flags)
104 {
105 	me4600_dio_subdevice_t *instance;
106 	int err = ME_ERRNO_SUCCESS;
107 	uint32_t mode;
108 	uint32_t size =
109 	    flags & (ME_IO_SINGLE_CONFIG_DIO_BIT | ME_IO_SINGLE_CONFIG_DIO_BYTE
110 		     | ME_IO_SINGLE_CONFIG_DIO_WORD |
111 		     ME_IO_SINGLE_CONFIG_DIO_DWORD);
112 	uint32_t mask;
113 
114 	PDEBUG("executed.\n");
115 
116 	instance = (me4600_dio_subdevice_t *) subdevice;
117 
118 	ME_SUBDEVICE_ENTER spin_lock(&instance->subdevice_lock);
119 	spin_lock(instance->ctrl_reg_lock);
120 	mode = inl(instance->ctrl_reg);
121 	switch (size) {
122 	case ME_IO_SINGLE_CONFIG_NO_FLAGS:
123 	case ME_IO_SINGLE_CONFIG_DIO_BYTE:
124 		if (channel == 0) {
125 			if (single_config == ME_SINGLE_CONFIG_DIO_INPUT) {
126 				mode &=
127 				    ~((ME4600_DIO_CTRL_BIT_MODE_0 |
128 				       ME4600_DIO_CTRL_BIT_MODE_1) <<
129 				      (instance->dio_idx * 2));
130 			} else if (single_config == ME_SINGLE_CONFIG_DIO_OUTPUT) {
131 				mode &=
132 				    ~((ME4600_DIO_CTRL_BIT_MODE_0 |
133 				       ME4600_DIO_CTRL_BIT_MODE_1) <<
134 				      (instance->dio_idx * 2));
135 				mode |=
136 				    ME4600_DIO_CTRL_BIT_MODE_0 << (instance->
137 								   dio_idx * 2);
138 			} else if (single_config == ME_SINGLE_CONFIG_DIO_MUX32M) {
139 				mask =
140 				    (ME4600_DIO_CTRL_BIT_MODE_0 |
141 				     ME4600_DIO_CTRL_BIT_MODE_1) << (instance->
142 								     dio_idx *
143 								     2);
144 				mask |=
145 				    ME4600_DIO_CTRL_BIT_FUNCTION_0 |
146 				    ME4600_DIO_CTRL_BIT_FUNCTION_1;
147 				mask |=
148 				    ME4600_DIO_CTRL_BIT_FIFO_HIGH_0 <<
149 				    instance->dio_idx;
150 				mode &= ~mask;
151 
152 				if (ref == ME_REF_DIO_FIFO_LOW) {
153 					mode |=
154 					    (ME4600_DIO_CTRL_BIT_MODE_0 |
155 					     ME4600_DIO_CTRL_BIT_MODE_1) <<
156 					    (instance->dio_idx * 2);
157 					mode |= ME4600_DIO_CTRL_BIT_FUNCTION_1;
158 				} else if (ref == ME_REF_DIO_FIFO_HIGH) {
159 					mode |=
160 					    (ME4600_DIO_CTRL_BIT_MODE_0 |
161 					     ME4600_DIO_CTRL_BIT_MODE_1) <<
162 					    (instance->dio_idx * 2);
163 					mode |= ME4600_DIO_CTRL_BIT_FUNCTION_1;
164 					mode |=
165 					    ME4600_DIO_CTRL_BIT_FIFO_HIGH_0 <<
166 					    instance->dio_idx;
167 				} else {
168 					PERROR
169 					    ("Invalid port reference specified.\n");
170 					err = ME_ERRNO_INVALID_SINGLE_CONFIG;
171 				}
172 			} else if (single_config ==
173 				   ME_SINGLE_CONFIG_DIO_DEMUX32) {
174 				mask =
175 				    (ME4600_DIO_CTRL_BIT_MODE_0 |
176 				     ME4600_DIO_CTRL_BIT_MODE_1) << (instance->
177 								     dio_idx *
178 								     2);
179 				mask |=
180 				    ME4600_DIO_CTRL_BIT_FUNCTION_0 |
181 				    ME4600_DIO_CTRL_BIT_FUNCTION_1;
182 				mask |=
183 				    ME4600_DIO_CTRL_BIT_FIFO_HIGH_0 <<
184 				    instance->dio_idx;
185 				mode &= ~mask;
186 
187 				if (ref == ME_REF_DIO_FIFO_LOW) {
188 					mode |=
189 					    (ME4600_DIO_CTRL_BIT_MODE_0 |
190 					     ME4600_DIO_CTRL_BIT_MODE_1) <<
191 					    (instance->dio_idx * 2);
192 					mode |= ME4600_DIO_CTRL_BIT_FUNCTION_0;
193 				} else if (ref == ME_REF_DIO_FIFO_HIGH) {
194 					mode |=
195 					    (ME4600_DIO_CTRL_BIT_MODE_0 |
196 					     ME4600_DIO_CTRL_BIT_MODE_1) <<
197 					    (instance->dio_idx * 2);
198 					mode |= ME4600_DIO_CTRL_BIT_FUNCTION_0;
199 					mode |=
200 					    ME4600_DIO_CTRL_BIT_FIFO_HIGH_0 <<
201 					    instance->dio_idx;
202 				} else {
203 					PERROR
204 					    ("Invalid port reference specified.\n");
205 					err = ME_ERRNO_INVALID_SINGLE_CONFIG;
206 				}
207 			} else if (single_config ==
208 				   ME_SINGLE_CONFIG_DIO_BIT_PATTERN) {
209 				mask =
210 				    (ME4600_DIO_CTRL_BIT_MODE_0 |
211 				     ME4600_DIO_CTRL_BIT_MODE_1) << (instance->
212 								     dio_idx *
213 								     2);
214 				mask |=
215 				    ME4600_DIO_CTRL_BIT_FUNCTION_0 |
216 				    ME4600_DIO_CTRL_BIT_FUNCTION_1;
217 				mask |=
218 				    ME4600_DIO_CTRL_BIT_FIFO_HIGH_0 <<
219 				    instance->dio_idx;
220 				mode &= ~mask;
221 
222 				if (ref == ME_REF_DIO_FIFO_LOW) {
223 					mode |=
224 					    (ME4600_DIO_CTRL_BIT_MODE_0 |
225 					     ME4600_DIO_CTRL_BIT_MODE_1) <<
226 					    (instance->dio_idx * 2);
227 				} else if (ref == ME_REF_DIO_FIFO_HIGH) {
228 					mode |=
229 					    (ME4600_DIO_CTRL_BIT_MODE_0 |
230 					     ME4600_DIO_CTRL_BIT_MODE_1) <<
231 					    (instance->dio_idx * 2);
232 					mode |=
233 					    ME4600_DIO_CTRL_BIT_FIFO_HIGH_0 <<
234 					    instance->dio_idx;
235 				} else {
236 					PERROR
237 					    ("Invalid port reference specified.\n");
238 					err = ME_ERRNO_INVALID_SINGLE_CONFIG;
239 				}
240 			} else {
241 				PERROR
242 				    ("Invalid port configuration specified.\n");
243 				err = ME_ERRNO_INVALID_SINGLE_CONFIG;
244 			}
245 		} else {
246 			PERROR("Invalid channel number.\n");
247 			err = ME_ERRNO_INVALID_CHANNEL;
248 		}
249 
250 		break;
251 
252 	default:
253 		PERROR("Invalid flags.\n");
254 		err = ME_ERRNO_INVALID_FLAGS;
255 	}
256 
257 	if (!err) {
258 		outl(mode, instance->ctrl_reg);
259 		PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n",
260 			   instance->reg_base,
261 			   instance->ctrl_reg - instance->reg_base, mode);
262 	}
263 	spin_unlock(instance->ctrl_reg_lock);
264 	spin_unlock(&instance->subdevice_lock);
265 
266 	ME_SUBDEVICE_EXIT;
267 
268 	return err;
269 }
270 
me4600_dio_io_single_read(me_subdevice_t * subdevice,struct file * filep,int channel,int * value,int time_out,int flags)271 static int me4600_dio_io_single_read(me_subdevice_t * subdevice,
272 				     struct file *filep,
273 				     int channel,
274 				     int *value, int time_out, int flags)
275 {
276 	me4600_dio_subdevice_t *instance;
277 	int err = ME_ERRNO_SUCCESS;
278 	uint32_t mode;
279 
280 	PDEBUG("executed.\n");
281 
282 	instance = (me4600_dio_subdevice_t *) subdevice;
283 
284 	ME_SUBDEVICE_ENTER;
285 
286 	spin_lock(&instance->subdevice_lock);
287 	spin_lock(instance->ctrl_reg_lock);
288 	switch (flags) {
289 	case ME_IO_SINGLE_TYPE_DIO_BIT:
290 		if ((channel >= 0) && (channel < 8)) {
291 			mode =
292 			    inl(instance->
293 				ctrl_reg) & ((ME4600_DIO_CTRL_BIT_MODE_0 |
294 					      ME4600_DIO_CTRL_BIT_MODE_1) <<
295 					     (instance->dio_idx * 2));
296 			if ((mode ==
297 			     (ME4600_DIO_CTRL_BIT_MODE_0 <<
298 			      (instance->dio_idx * 2))) || !mode) {
299 				*value =
300 				    inl(instance->port_reg) & (0x1 << channel);
301 			} else {
302 				PERROR("Port not in output or input mode.\n");
303 				err = ME_ERRNO_PREVIOUS_CONFIG;
304 			}
305 		} else {
306 			PERROR("Invalid bit number specified.\n");
307 			err = ME_ERRNO_INVALID_CHANNEL;
308 		}
309 		break;
310 
311 	case ME_IO_SINGLE_NO_FLAGS:
312 	case ME_IO_SINGLE_TYPE_DIO_BYTE:
313 		if (channel == 0) {
314 			mode =
315 			    inl(instance->
316 				ctrl_reg) & ((ME4600_DIO_CTRL_BIT_MODE_0 |
317 					      ME4600_DIO_CTRL_BIT_MODE_1) <<
318 					     (instance->dio_idx * 2));
319 			if ((mode ==
320 			     (ME4600_DIO_CTRL_BIT_MODE_0 <<
321 			      (instance->dio_idx * 2))) || !mode) {
322 				*value = inl(instance->port_reg) & 0xFF;
323 			} else {
324 				PERROR("Port not in output or input mode.\n");
325 				err = ME_ERRNO_PREVIOUS_CONFIG;
326 			}
327 		} else {
328 			PERROR("Invalid byte number specified.\n");
329 			err = ME_ERRNO_INVALID_CHANNEL;
330 		}
331 		break;
332 
333 	default:
334 		PERROR("Invalid flags specified.\n");
335 		err = ME_ERRNO_INVALID_FLAGS;
336 	}
337 	spin_unlock(instance->ctrl_reg_lock);
338 	spin_unlock(&instance->subdevice_lock);
339 
340 	ME_SUBDEVICE_EXIT;
341 
342 	return err;
343 }
344 
me4600_dio_io_single_write(me_subdevice_t * subdevice,struct file * filep,int channel,int value,int time_out,int flags)345 static int me4600_dio_io_single_write(me_subdevice_t * subdevice,
346 				      struct file *filep,
347 				      int channel,
348 				      int value, int time_out, int flags)
349 {
350 	me4600_dio_subdevice_t *instance;
351 	int err = ME_ERRNO_SUCCESS;
352 	uint32_t mode;
353 	uint32_t byte;
354 
355 	PDEBUG("executed.\n");
356 
357 	instance = (me4600_dio_subdevice_t *) subdevice;
358 
359 	ME_SUBDEVICE_ENTER;
360 
361 	spin_lock(&instance->subdevice_lock);
362 	spin_lock(instance->ctrl_reg_lock);
363 	switch (flags) {
364 	case ME_IO_SINGLE_TYPE_DIO_BIT:
365 		if ((channel >= 0) && (channel < 8)) {
366 			mode =
367 			    inl(instance->
368 				ctrl_reg) & ((ME4600_DIO_CTRL_BIT_MODE_0 |
369 					      ME4600_DIO_CTRL_BIT_MODE_1) <<
370 					     (instance->dio_idx * 2));
371 
372 			if (mode ==
373 			    (ME4600_DIO_CTRL_BIT_MODE_0 <<
374 			     (instance->dio_idx * 2))) {
375 				byte = inl(instance->port_reg) & 0xFF;
376 
377 				if (value)
378 					byte |= 0x1 << channel;
379 				else
380 					byte &= ~(0x1 << channel);
381 
382 				outl(byte, instance->port_reg);
383 			} else {
384 				PERROR("Port not in output or input mode.\n");
385 				err = ME_ERRNO_PREVIOUS_CONFIG;
386 			}
387 		} else {
388 			PERROR("Invalid bit number specified.\n");
389 			err = ME_ERRNO_INVALID_CHANNEL;
390 		}
391 		break;
392 
393 	case ME_IO_SINGLE_NO_FLAGS:
394 	case ME_IO_SINGLE_TYPE_DIO_BYTE:
395 		if (channel == 0) {
396 			mode =
397 			    inl(instance->
398 				ctrl_reg) & ((ME4600_DIO_CTRL_BIT_MODE_0 |
399 					      ME4600_DIO_CTRL_BIT_MODE_1) <<
400 					     (instance->dio_idx * 2));
401 
402 			if (mode ==
403 			    (ME4600_DIO_CTRL_BIT_MODE_0 <<
404 			     (instance->dio_idx * 2))) {
405 				outl(value, instance->port_reg);
406 			} else {
407 				PERROR("Port not in output or input mode.\n");
408 				err = ME_ERRNO_PREVIOUS_CONFIG;
409 			}
410 		} else {
411 			PERROR("Invalid byte number specified.\n");
412 			err = ME_ERRNO_INVALID_CHANNEL;
413 		}
414 		break;
415 
416 	default:
417 		PERROR("Invalid flags specified.\n");
418 		err = ME_ERRNO_INVALID_FLAGS;
419 	}
420 	spin_unlock(instance->ctrl_reg_lock);
421 	spin_unlock(&instance->subdevice_lock);
422 
423 	ME_SUBDEVICE_EXIT;
424 
425 	return err;
426 }
427 
me4600_dio_query_number_channels(me_subdevice_t * subdevice,int * number)428 static int me4600_dio_query_number_channels(me_subdevice_t * subdevice,
429 					    int *number)
430 {
431 	PDEBUG("executed.\n");
432 	*number = 8;
433 	return ME_ERRNO_SUCCESS;
434 }
435 
me4600_dio_query_subdevice_type(me_subdevice_t * subdevice,int * type,int * subtype)436 static int me4600_dio_query_subdevice_type(me_subdevice_t * subdevice,
437 					   int *type, int *subtype)
438 {
439 	PDEBUG("executed.\n");
440 	*type = ME_TYPE_DIO;
441 	*subtype = ME_SUBTYPE_SINGLE;
442 	return ME_ERRNO_SUCCESS;
443 }
444 
me4600_dio_query_subdevice_caps(me_subdevice_t * subdevice,int * caps)445 static int me4600_dio_query_subdevice_caps(me_subdevice_t * subdevice,
446 					   int *caps)
447 {
448 	PDEBUG("executed.\n");
449 	*caps = ME_CAPS_DIO_DIR_BYTE;
450 	return ME_ERRNO_SUCCESS;
451 }
452 
me4600_dio_constructor(uint32_t reg_base,unsigned int dio_idx,spinlock_t * ctrl_reg_lock)453 me4600_dio_subdevice_t *me4600_dio_constructor(uint32_t reg_base,
454 					       unsigned int dio_idx,
455 					       spinlock_t * ctrl_reg_lock)
456 {
457 	me4600_dio_subdevice_t *subdevice;
458 	int err;
459 
460 	PDEBUG("executed.\n");
461 
462 	/* Allocate memory for subdevice instance */
463 	subdevice = kmalloc(sizeof(me4600_dio_subdevice_t), GFP_KERNEL);
464 
465 	if (!subdevice) {
466 		PERROR("Cannot get memory for subdevice instance.\n");
467 		return NULL;
468 	}
469 
470 	memset(subdevice, 0, sizeof(me4600_dio_subdevice_t));
471 
472 	/* Initialize subdevice base class */
473 	err = me_subdevice_init(&subdevice->base);
474 
475 	if (err) {
476 		PERROR("Cannot initialize subdevice base class instance.\n");
477 		kfree(subdevice);
478 		return NULL;
479 	}
480 	// Initialize spin locks.
481 	spin_lock_init(&subdevice->subdevice_lock);
482 	subdevice->ctrl_reg_lock = ctrl_reg_lock;
483 
484 	/* Save digital i/o index */
485 	subdevice->dio_idx = dio_idx;
486 
487 	/* Save the subdevice index */
488 	subdevice->ctrl_reg = reg_base + ME4600_DIO_CTRL_REG;
489 	subdevice->port_reg = reg_base + ME4600_DIO_PORT_REG + (dio_idx * 4);
490 #ifdef MEDEBUG_DEBUG_REG
491 	subdevice->reg_base = reg_base;
492 #endif
493 
494 	/* Overload base class methods. */
495 	subdevice->base.me_subdevice_io_reset_subdevice =
496 	    me4600_dio_io_reset_subdevice;
497 	subdevice->base.me_subdevice_io_single_config =
498 	    me4600_dio_io_single_config;
499 	subdevice->base.me_subdevice_io_single_read = me4600_dio_io_single_read;
500 	subdevice->base.me_subdevice_io_single_write =
501 	    me4600_dio_io_single_write;
502 	subdevice->base.me_subdevice_query_number_channels =
503 	    me4600_dio_query_number_channels;
504 	subdevice->base.me_subdevice_query_subdevice_type =
505 	    me4600_dio_query_subdevice_type;
506 	subdevice->base.me_subdevice_query_subdevice_caps =
507 	    me4600_dio_query_subdevice_caps;
508 
509 	return subdevice;
510 }
511