diff options
author | Jarod Wilson <jarod@redhat.com> | 2010-07-26 19:30:02 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2010-08-02 15:43:26 -0400 |
commit | c147f9078a6fca5b43b6e9e4b7b6a99b50c6e2bb (patch) | |
tree | 220a3bbedd0256125c2f42cb61d324d3803d4327 /drivers | |
parent | 85cb01afc844f7b4e65df04a96b0c3729db59eba (diff) |
V4L/DVB: staging/lirc: add lirc_it87 driver
Signed-off-by: Jarod Wilson <jarod@redhat.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/staging/lirc/lirc_it87.c | 1019 | ||||
-rw-r--r-- | drivers/staging/lirc/lirc_it87.h | 116 |
2 files changed, 1135 insertions, 0 deletions
diff --git a/drivers/staging/lirc/lirc_it87.c b/drivers/staging/lirc/lirc_it87.c new file mode 100644 index 000000000000..781abc306c27 --- /dev/null +++ b/drivers/staging/lirc/lirc_it87.c | |||
@@ -0,0 +1,1019 @@ | |||
1 | /* | ||
2 | * LIRC driver for ITE IT8712/IT8705 CIR port | ||
3 | * | ||
4 | * Copyright (C) 2001 Hans-Gunter Lutke Uphues <hg_lu@web.de> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License as | ||
8 | * published by the Free Software Foundation; either version 2 of the | ||
9 | * License, or (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but | ||
12 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | * General Public License for more details. | ||
15 | |||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 | ||
19 | * USA | ||
20 | * | ||
21 | * ITE IT8705 and IT8712(not tested) and IT8720 CIR-port support for lirc based | ||
22 | * via cut and paste from lirc_sir.c (C) 2000 Milan Pikula | ||
23 | * | ||
24 | * Attention: Sendmode only tested with debugging logs | ||
25 | * | ||
26 | * 2001/02/27 Christoph Bartelmus <lirc@bartelmus.de> : | ||
27 | * reimplemented read function | ||
28 | * 2005/06/05 Andrew Calkin implemented support for Asus Digimatrix, | ||
29 | * based on work of the following member of the Outertrack Digimatrix | ||
30 | * Forum: Art103 <r_tay@hotmail.com> | ||
31 | * 2009/12/24 James Edwards <jimbo-lirc@edwardsclan.net> implemeted support | ||
32 | * for ITE8704/ITE8718, on my machine, the DSDT reports 8704, but the | ||
33 | * chip identifies as 18. | ||
34 | */ | ||
35 | |||
36 | #include <linux/module.h> | ||
37 | #include <linux/sched.h> | ||
38 | #include <linux/errno.h> | ||
39 | #include <linux/signal.h> | ||
40 | #include <linux/fs.h> | ||
41 | #include <linux/interrupt.h> | ||
42 | #include <linux/ioport.h> | ||
43 | #include <linux/kernel.h> | ||
44 | #include <linux/time.h> | ||
45 | #include <linux/string.h> | ||
46 | #include <linux/types.h> | ||
47 | #include <linux/wait.h> | ||
48 | #include <linux/mm.h> | ||
49 | #include <linux/delay.h> | ||
50 | #include <linux/poll.h> | ||
51 | #include <asm/system.h> | ||
52 | #include <linux/io.h> | ||
53 | #include <linux/irq.h> | ||
54 | #include <linux/fcntl.h> | ||
55 | |||
56 | #include <linux/timer.h> | ||
57 | #include <linux/pnp.h> | ||
58 | |||
59 | #include <media/lirc.h> | ||
60 | #include <media/lirc_dev.h> | ||
61 | |||
62 | #include "lirc_it87.h" | ||
63 | |||
64 | #ifdef LIRC_IT87_DIGIMATRIX | ||
65 | static int digimatrix = 1; | ||
66 | static int it87_freq = 36; /* kHz */ | ||
67 | static int irq = 9; | ||
68 | #else | ||
69 | static int digimatrix; | ||
70 | static int it87_freq = 38; /* kHz */ | ||
71 | static int irq = IT87_CIR_DEFAULT_IRQ; | ||
72 | #endif | ||
73 | |||
74 | static unsigned long it87_bits_in_byte_out; | ||
75 | static unsigned long it87_send_counter; | ||
76 | static unsigned char it87_RXEN_mask = IT87_CIR_RCR_RXEN; | ||
77 | |||
78 | #define RBUF_LEN 1024 | ||
79 | |||
80 | #define LIRC_DRIVER_NAME "lirc_it87" | ||
81 | |||
82 | /* timeout for sequences in jiffies (=5/100s) */ | ||
83 | /* must be longer than TIME_CONST */ | ||
84 | #define IT87_TIMEOUT (HZ*5/100) | ||
85 | |||
86 | /* module parameters */ | ||
87 | static int debug; | ||
88 | #define dprintk(fmt, args...) \ | ||
89 | do { \ | ||
90 | if (debug) \ | ||
91 | printk(KERN_DEBUG LIRC_DRIVER_NAME ": " \ | ||
92 | fmt, ## args); \ | ||
93 | } while (0) | ||
94 | |||
95 | static int io = IT87_CIR_DEFAULT_IOBASE; | ||
96 | /* receiver demodulator default: off */ | ||
97 | static int it87_enable_demodulator; | ||
98 | |||
99 | static int timer_enabled; | ||
100 | static DEFINE_SPINLOCK(timer_lock); | ||
101 | static struct timer_list timerlist; | ||
102 | /* time of last signal change detected */ | ||
103 | static struct timeval last_tv = {0, 0}; | ||
104 | /* time of last UART data ready interrupt */ | ||
105 | static struct timeval last_intr_tv = {0, 0}; | ||
106 | static int last_value; | ||
107 | |||
108 | static DECLARE_WAIT_QUEUE_HEAD(lirc_read_queue); | ||
109 | |||
110 | static DEFINE_SPINLOCK(hardware_lock); | ||
111 | static DEFINE_SPINLOCK(dev_lock); | ||
112 | |||
113 | static int rx_buf[RBUF_LEN]; | ||
114 | unsigned int rx_tail, rx_head; | ||
115 | |||
116 | static struct pnp_driver it87_pnp_driver; | ||
117 | |||
118 | /* SECTION: Prototypes */ | ||
119 | |||
120 | /* Communication with user-space */ | ||
121 | static int lirc_open(struct inode *inode, struct file *file); | ||
122 | static int lirc_close(struct inode *inode, struct file *file); | ||
123 | static unsigned int lirc_poll(struct file *file, poll_table *wait); | ||
124 | static ssize_t lirc_read(struct file *file, char *buf, | ||
125 | size_t count, loff_t *ppos); | ||
126 | static ssize_t lirc_write(struct file *file, const char *buf, | ||
127 | size_t n, loff_t *pos); | ||
128 | static long lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long arg); | ||
129 | static void add_read_queue(int flag, unsigned long val); | ||
130 | static int init_chrdev(void); | ||
131 | static void drop_chrdev(void); | ||
132 | /* Hardware */ | ||
133 | static irqreturn_t it87_interrupt(int irq, void *dev_id); | ||
134 | static void send_space(unsigned long len); | ||
135 | static void send_pulse(unsigned long len); | ||
136 | static void init_send(void); | ||
137 | static void terminate_send(unsigned long len); | ||
138 | static int init_hardware(void); | ||
139 | static void drop_hardware(void); | ||
140 | /* Initialisation */ | ||
141 | static int init_port(void); | ||
142 | static void drop_port(void); | ||
143 | |||
144 | |||
145 | /* SECTION: Communication with user-space */ | ||
146 | |||
147 | static int lirc_open(struct inode *inode, struct file *file) | ||
148 | { | ||
149 | spin_lock(&dev_lock); | ||
150 | if (module_refcount(THIS_MODULE)) { | ||
151 | spin_unlock(&dev_lock); | ||
152 | return -EBUSY; | ||
153 | } | ||
154 | spin_unlock(&dev_lock); | ||
155 | return 0; | ||
156 | } | ||
157 | |||
158 | |||
159 | static int lirc_close(struct inode *inode, struct file *file) | ||
160 | { | ||
161 | return 0; | ||
162 | } | ||
163 | |||
164 | |||
165 | static unsigned int lirc_poll(struct file *file, poll_table *wait) | ||
166 | { | ||
167 | poll_wait(file, &lirc_read_queue, wait); | ||
168 | if (rx_head != rx_tail) | ||
169 | return POLLIN | POLLRDNORM; | ||
170 | return 0; | ||
171 | } | ||
172 | |||
173 | |||
174 | static ssize_t lirc_read(struct file *file, char *buf, | ||
175 | size_t count, loff_t *ppos) | ||
176 | { | ||
177 | int n = 0; | ||
178 | int retval = 0; | ||
179 | |||
180 | while (n < count) { | ||
181 | if (file->f_flags & O_NONBLOCK && rx_head == rx_tail) { | ||
182 | retval = -EAGAIN; | ||
183 | break; | ||
184 | } | ||
185 | retval = wait_event_interruptible(lirc_read_queue, | ||
186 | rx_head != rx_tail); | ||
187 | if (retval) | ||
188 | break; | ||
189 | |||
190 | if (copy_to_user((void *) buf + n, (void *) (rx_buf + rx_head), | ||
191 | sizeof(int))) { | ||
192 | retval = -EFAULT; | ||
193 | break; | ||
194 | } | ||
195 | rx_head = (rx_head + 1) & (RBUF_LEN - 1); | ||
196 | n += sizeof(int); | ||
197 | } | ||
198 | if (n) | ||
199 | return n; | ||
200 | return retval; | ||
201 | } | ||
202 | |||
203 | |||
204 | static ssize_t lirc_write(struct file *file, const char *buf, | ||
205 | size_t n, loff_t *pos) | ||
206 | { | ||
207 | int i = 0; | ||
208 | int *tx_buf; | ||
209 | |||
210 | if (n % sizeof(int)) | ||
211 | return -EINVAL; | ||
212 | tx_buf = memdup_user(buf, n); | ||
213 | if (IS_ERR(tx_buf)) | ||
214 | return PTR_ERR(tx_buf); | ||
215 | n /= sizeof(int); | ||
216 | init_send(); | ||
217 | while (1) { | ||
218 | if (i >= n) | ||
219 | break; | ||
220 | if (tx_buf[i]) | ||
221 | send_pulse(tx_buf[i]); | ||
222 | i++; | ||
223 | if (i >= n) | ||
224 | break; | ||
225 | if (tx_buf[i]) | ||
226 | send_space(tx_buf[i]); | ||
227 | i++; | ||
228 | } | ||
229 | terminate_send(tx_buf[i - 1]); | ||
230 | return n; | ||
231 | } | ||
232 | |||
233 | |||
234 | static long lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) | ||
235 | { | ||
236 | int retval = 0; | ||
237 | unsigned long value = 0; | ||
238 | unsigned int ivalue; | ||
239 | unsigned long hw_flags; | ||
240 | |||
241 | if (cmd == LIRC_GET_FEATURES) | ||
242 | value = LIRC_CAN_SEND_PULSE | | ||
243 | LIRC_CAN_SET_SEND_CARRIER | | ||
244 | LIRC_CAN_REC_MODE2; | ||
245 | else if (cmd == LIRC_GET_SEND_MODE) | ||
246 | value = LIRC_MODE_PULSE; | ||
247 | else if (cmd == LIRC_GET_REC_MODE) | ||
248 | value = LIRC_MODE_MODE2; | ||
249 | |||
250 | switch (cmd) { | ||
251 | case LIRC_GET_FEATURES: | ||
252 | case LIRC_GET_SEND_MODE: | ||
253 | case LIRC_GET_REC_MODE: | ||
254 | retval = put_user(value, (unsigned long *) arg); | ||
255 | break; | ||
256 | |||
257 | case LIRC_SET_SEND_MODE: | ||
258 | case LIRC_SET_REC_MODE: | ||
259 | retval = get_user(value, (unsigned long *) arg); | ||
260 | break; | ||
261 | |||
262 | case LIRC_SET_SEND_CARRIER: | ||
263 | retval = get_user(ivalue, (unsigned int *) arg); | ||
264 | if (retval) | ||
265 | return retval; | ||
266 | ivalue /= 1000; | ||
267 | if (ivalue > IT87_CIR_FREQ_MAX || | ||
268 | ivalue < IT87_CIR_FREQ_MIN) | ||
269 | return -EINVAL; | ||
270 | |||
271 | it87_freq = ivalue; | ||
272 | |||
273 | spin_lock_irqsave(&hardware_lock, hw_flags); | ||
274 | outb(((inb(io + IT87_CIR_TCR2) & IT87_CIR_TCR2_TXMPW) | | ||
275 | (it87_freq - IT87_CIR_FREQ_MIN) << 3), | ||
276 | io + IT87_CIR_TCR2); | ||
277 | spin_unlock_irqrestore(&hardware_lock, hw_flags); | ||
278 | dprintk("demodulation frequency: %d kHz\n", it87_freq); | ||
279 | |||
280 | break; | ||
281 | |||
282 | default: | ||
283 | retval = -EINVAL; | ||
284 | } | ||
285 | |||
286 | if (retval) | ||
287 | return retval; | ||
288 | |||
289 | if (cmd == LIRC_SET_REC_MODE) { | ||
290 | if (value != LIRC_MODE_MODE2) | ||
291 | retval = -ENOSYS; | ||
292 | } else if (cmd == LIRC_SET_SEND_MODE) { | ||
293 | if (value != LIRC_MODE_PULSE) | ||
294 | retval = -ENOSYS; | ||
295 | } | ||
296 | return retval; | ||
297 | } | ||
298 | |||
299 | static void add_read_queue(int flag, unsigned long val) | ||
300 | { | ||
301 | unsigned int new_rx_tail; | ||
302 | int newval; | ||
303 | |||
304 | dprintk("add flag %d with val %lu\n", flag, val); | ||
305 | |||
306 | newval = val & PULSE_MASK; | ||
307 | |||
308 | /* | ||
309 | * statistically, pulses are ~TIME_CONST/2 too long. we could | ||
310 | * maybe make this more exact, but this is good enough | ||
311 | */ | ||
312 | if (flag) { | ||
313 | /* pulse */ | ||
314 | if (newval > TIME_CONST / 2) | ||
315 | newval -= TIME_CONST / 2; | ||
316 | else /* should not ever happen */ | ||
317 | newval = 1; | ||
318 | newval |= PULSE_BIT; | ||
319 | } else | ||
320 | newval += TIME_CONST / 2; | ||
321 | new_rx_tail = (rx_tail + 1) & (RBUF_LEN - 1); | ||
322 | if (new_rx_tail == rx_head) { | ||
323 | dprintk("Buffer overrun.\n"); | ||
324 | return; | ||
325 | } | ||
326 | rx_buf[rx_tail] = newval; | ||
327 | rx_tail = new_rx_tail; | ||
328 | wake_up_interruptible(&lirc_read_queue); | ||
329 | } | ||
330 | |||
331 | |||
332 | static struct file_operations lirc_fops = { | ||
333 | .owner = THIS_MODULE, | ||
334 | .read = lirc_read, | ||
335 | .write = lirc_write, | ||
336 | .poll = lirc_poll, | ||
337 | .unlocked_ioctl = lirc_ioctl, | ||
338 | .open = lirc_open, | ||
339 | .release = lirc_close, | ||
340 | }; | ||
341 | |||
342 | static int set_use_inc(void *data) | ||
343 | { | ||
344 | return 0; | ||
345 | } | ||
346 | |||
347 | static void set_use_dec(void *data) | ||
348 | { | ||
349 | } | ||
350 | |||
351 | static struct lirc_driver driver = { | ||
352 | .name = LIRC_DRIVER_NAME, | ||
353 | .minor = -1, | ||
354 | .code_length = 1, | ||
355 | .sample_rate = 0, | ||
356 | .data = NULL, | ||
357 | .add_to_buf = NULL, | ||
358 | .set_use_inc = set_use_inc, | ||
359 | .set_use_dec = set_use_dec, | ||
360 | .fops = &lirc_fops, | ||
361 | .dev = NULL, | ||
362 | .owner = THIS_MODULE, | ||
363 | }; | ||
364 | |||
365 | |||
366 | #ifdef MODULE | ||
367 | static int init_chrdev(void) | ||
368 | { | ||
369 | driver.minor = lirc_register_driver(&driver); | ||
370 | |||
371 | if (driver.minor < 0) { | ||
372 | printk(KERN_ERR LIRC_DRIVER_NAME ": init_chrdev() failed.\n"); | ||
373 | return -EIO; | ||
374 | } | ||
375 | return 0; | ||
376 | } | ||
377 | |||
378 | |||
379 | static void drop_chrdev(void) | ||
380 | { | ||
381 | lirc_unregister_driver(driver.minor); | ||
382 | } | ||
383 | #endif | ||
384 | |||
385 | |||
386 | /* SECTION: Hardware */ | ||
387 | static long delta(struct timeval *tv1, struct timeval *tv2) | ||
388 | { | ||
389 | unsigned long deltv; | ||
390 | |||
391 | deltv = tv2->tv_sec - tv1->tv_sec; | ||
392 | if (deltv > 15) | ||
393 | deltv = 0xFFFFFF; | ||
394 | else | ||
395 | deltv = deltv*1000000 + tv2->tv_usec - tv1->tv_usec; | ||
396 | return deltv; | ||
397 | } | ||
398 | |||
399 | static void it87_timeout(unsigned long data) | ||
400 | { | ||
401 | unsigned long flags; | ||
402 | |||
403 | /* avoid interference with interrupt */ | ||
404 | spin_lock_irqsave(&timer_lock, flags); | ||
405 | |||
406 | if (digimatrix) { | ||
407 | /* We have timed out. Disable the RX mechanism. */ | ||
408 | |||
409 | outb((inb(io + IT87_CIR_RCR) & ~IT87_CIR_RCR_RXEN) | | ||
410 | IT87_CIR_RCR_RXACT, io + IT87_CIR_RCR); | ||
411 | if (it87_RXEN_mask) | ||
412 | outb(inb(io + IT87_CIR_RCR) | IT87_CIR_RCR_RXEN, | ||
413 | io + IT87_CIR_RCR); | ||
414 | dprintk(" TIMEOUT\n"); | ||
415 | timer_enabled = 0; | ||
416 | |||
417 | /* fifo clear */ | ||
418 | outb(inb(io + IT87_CIR_TCR1) | IT87_CIR_TCR1_FIFOCLR, | ||
419 | io+IT87_CIR_TCR1); | ||
420 | |||
421 | } else { | ||
422 | /* | ||
423 | * if last received signal was a pulse, but receiving stopped | ||
424 | * within the 9 bit frame, we need to finish this pulse and | ||
425 | * simulate a signal change to from pulse to space. Otherwise | ||
426 | * upper layers will receive two sequences next time. | ||
427 | */ | ||
428 | |||
429 | if (last_value) { | ||
430 | unsigned long pulse_end; | ||
431 | |||
432 | /* determine 'virtual' pulse end: */ | ||
433 | pulse_end = delta(&last_tv, &last_intr_tv); | ||
434 | dprintk("timeout add %d for %lu usec\n", | ||
435 | last_value, pulse_end); | ||
436 | add_read_queue(last_value, pulse_end); | ||
437 | last_value = 0; | ||
438 | last_tv = last_intr_tv; | ||
439 | } | ||
440 | } | ||
441 | spin_unlock_irqrestore(&timer_lock, flags); | ||
442 | } | ||
443 | |||
444 | static irqreturn_t it87_interrupt(int irq, void *dev_id) | ||
445 | { | ||
446 | unsigned char data; | ||
447 | struct timeval curr_tv; | ||
448 | static unsigned long deltv; | ||
449 | unsigned long deltintrtv; | ||
450 | unsigned long flags, hw_flags; | ||
451 | int iir, lsr; | ||
452 | int fifo = 0; | ||
453 | static char lastbit; | ||
454 | char bit; | ||
455 | |||
456 | /* Bit duration in microseconds */ | ||
457 | const unsigned long bit_duration = 1000000ul / | ||
458 | (115200 / IT87_CIR_BAUDRATE_DIVISOR); | ||
459 | |||
460 | |||
461 | iir = inb(io + IT87_CIR_IIR); | ||
462 | |||
463 | switch (iir & IT87_CIR_IIR_IID) { | ||
464 | case 0x4: | ||
465 | case 0x6: | ||
466 | lsr = inb(io + IT87_CIR_RSR) & (IT87_CIR_RSR_RXFTO | | ||
467 | IT87_CIR_RSR_RXFBC); | ||
468 | fifo = lsr & IT87_CIR_RSR_RXFBC; | ||
469 | dprintk("iir: 0x%x fifo: 0x%x\n", iir, lsr); | ||
470 | |||
471 | /* avoid interference with timer */ | ||
472 | spin_lock_irqsave(&timer_lock, flags); | ||
473 | spin_lock_irqsave(&hardware_lock, hw_flags); | ||
474 | if (digimatrix) { | ||
475 | static unsigned long acc_pulse; | ||
476 | static unsigned long acc_space; | ||
477 | |||
478 | do { | ||
479 | data = inb(io + IT87_CIR_DR); | ||
480 | data = ~data; | ||
481 | fifo--; | ||
482 | if (data != 0x00) { | ||
483 | if (timer_enabled) | ||
484 | del_timer(&timerlist); | ||
485 | /* | ||
486 | * start timer for end of | ||
487 | * sequence detection | ||
488 | */ | ||
489 | timerlist.expires = jiffies + | ||
490 | IT87_TIMEOUT; | ||
491 | add_timer(&timerlist); | ||
492 | timer_enabled = 1; | ||
493 | } | ||
494 | /* Loop through */ | ||
495 | for (bit = 0; bit < 8; ++bit) { | ||
496 | if ((data >> bit) & 1) { | ||
497 | ++acc_pulse; | ||
498 | if (lastbit == 0) { | ||
499 | add_read_queue(0, | ||
500 | acc_space * | ||
501 | bit_duration); | ||
502 | acc_space = 0; | ||
503 | } | ||
504 | } else { | ||
505 | ++acc_space; | ||
506 | if (lastbit == 1) { | ||
507 | add_read_queue(1, | ||
508 | acc_pulse * | ||
509 | bit_duration); | ||
510 | acc_pulse = 0; | ||
511 | } | ||
512 | } | ||
513 | lastbit = (data >> bit) & 1; | ||
514 | } | ||
515 | |||
516 | } while (fifo != 0); | ||
517 | } else { /* Normal Operation */ | ||
518 | do { | ||
519 | del_timer(&timerlist); | ||
520 | data = inb(io + IT87_CIR_DR); | ||
521 | |||
522 | dprintk("data=%02x\n", data); | ||
523 | do_gettimeofday(&curr_tv); | ||
524 | deltv = delta(&last_tv, &curr_tv); | ||
525 | deltintrtv = delta(&last_intr_tv, &curr_tv); | ||
526 | |||
527 | dprintk("t %lu , d %d\n", | ||
528 | deltintrtv, (int)data); | ||
529 | |||
530 | /* | ||
531 | * if nothing came in last 2 cycles, | ||
532 | * it was gap | ||
533 | */ | ||
534 | if (deltintrtv > TIME_CONST * 2) { | ||
535 | if (last_value) { | ||
536 | dprintk("GAP\n"); | ||
537 | |||
538 | /* simulate signal change */ | ||
539 | add_read_queue(last_value, | ||
540 | deltv - | ||
541 | deltintrtv); | ||
542 | last_value = 0; | ||
543 | last_tv.tv_sec = | ||
544 | last_intr_tv.tv_sec; | ||
545 | last_tv.tv_usec = | ||
546 | last_intr_tv.tv_usec; | ||
547 | deltv = deltintrtv; | ||
548 | } | ||
549 | } | ||
550 | data = 1; | ||
551 | if (data ^ last_value) { | ||
552 | /* | ||
553 | * deltintrtv > 2*TIME_CONST, | ||
554 | * remember ? the other case is | ||
555 | * timeout | ||
556 | */ | ||
557 | add_read_queue(last_value, | ||
558 | deltv-TIME_CONST); | ||
559 | last_value = data; | ||
560 | last_tv = curr_tv; | ||
561 | if (last_tv.tv_usec >= TIME_CONST) | ||
562 | last_tv.tv_usec -= TIME_CONST; | ||
563 | else { | ||
564 | last_tv.tv_sec--; | ||
565 | last_tv.tv_usec += 1000000 - | ||
566 | TIME_CONST; | ||
567 | } | ||
568 | } | ||
569 | last_intr_tv = curr_tv; | ||
570 | if (data) { | ||
571 | /* | ||
572 | * start timer for end of | ||
573 | * sequence detection | ||
574 | */ | ||
575 | timerlist.expires = | ||
576 | jiffies + IT87_TIMEOUT; | ||
577 | add_timer(&timerlist); | ||
578 | } | ||
579 | outb((inb(io + IT87_CIR_RCR) & | ||
580 | ~IT87_CIR_RCR_RXEN) | | ||
581 | IT87_CIR_RCR_RXACT, | ||
582 | io + IT87_CIR_RCR); | ||
583 | if (it87_RXEN_mask) | ||
584 | outb(inb(io + IT87_CIR_RCR) | | ||
585 | IT87_CIR_RCR_RXEN, | ||
586 | io + IT87_CIR_RCR); | ||
587 | fifo--; | ||
588 | } while (fifo != 0); | ||
589 | } | ||
590 | spin_unlock_irqrestore(&hardware_lock, hw_flags); | ||
591 | spin_unlock_irqrestore(&timer_lock, flags); | ||
592 | |||
593 | return IRQ_RETVAL(IRQ_HANDLED); | ||
594 | |||
595 | default: | ||
596 | /* not our irq */ | ||
597 | dprintk("unknown IRQ (shouldn't happen) !!\n"); | ||
598 | return IRQ_RETVAL(IRQ_NONE); | ||
599 | } | ||
600 | } | ||
601 | |||
602 | |||
603 | static void send_it87(unsigned long len, unsigned long stime, | ||
604 | unsigned char send_byte, unsigned int count_bits) | ||
605 | { | ||
606 | long count = len / stime; | ||
607 | long time_left = 0; | ||
608 | static unsigned char byte_out; | ||
609 | unsigned long hw_flags; | ||
610 | |||
611 | dprintk("%s: len=%ld, sb=%d\n", __func__, len, send_byte); | ||
612 | |||
613 | time_left = (long)len - (long)count * (long)stime; | ||
614 | count += ((2 * time_left) / stime); | ||
615 | while (count) { | ||
616 | long i = 0; | ||
617 | for (i = 0; i < count_bits; i++) { | ||
618 | byte_out = (byte_out << 1) | (send_byte & 1); | ||
619 | it87_bits_in_byte_out++; | ||
620 | } | ||
621 | if (it87_bits_in_byte_out == 8) { | ||
622 | dprintk("out=0x%x, tsr_txfbc: 0x%x\n", | ||
623 | byte_out, | ||
624 | inb(io + IT87_CIR_TSR) & | ||
625 | IT87_CIR_TSR_TXFBC); | ||
626 | |||
627 | while ((inb(io + IT87_CIR_TSR) & | ||
628 | IT87_CIR_TSR_TXFBC) >= IT87_CIR_FIFO_SIZE) | ||
629 | ; | ||
630 | |||
631 | spin_lock_irqsave(&hardware_lock, hw_flags); | ||
632 | outb(byte_out, io + IT87_CIR_DR); | ||
633 | spin_unlock_irqrestore(&hardware_lock, hw_flags); | ||
634 | |||
635 | it87_bits_in_byte_out = 0; | ||
636 | it87_send_counter++; | ||
637 | byte_out = 0; | ||
638 | } | ||
639 | count--; | ||
640 | } | ||
641 | } | ||
642 | |||
643 | |||
644 | /*TODO: maybe exchange space and pulse because it8705 only modulates 0-bits */ | ||
645 | |||
646 | static void send_space(unsigned long len) | ||
647 | { | ||
648 | send_it87(len, TIME_CONST, IT87_CIR_SPACE, IT87_CIR_BAUDRATE_DIVISOR); | ||
649 | } | ||
650 | |||
651 | static void send_pulse(unsigned long len) | ||
652 | { | ||
653 | send_it87(len, TIME_CONST, IT87_CIR_PULSE, IT87_CIR_BAUDRATE_DIVISOR); | ||
654 | } | ||
655 | |||
656 | |||
657 | static void init_send() | ||
658 | { | ||
659 | unsigned long flags; | ||
660 | |||
661 | spin_lock_irqsave(&hardware_lock, flags); | ||
662 | /* RXEN=0: receiver disable */ | ||
663 | it87_RXEN_mask = 0; | ||
664 | outb(inb(io + IT87_CIR_RCR) & ~IT87_CIR_RCR_RXEN, | ||
665 | io + IT87_CIR_RCR); | ||
666 | spin_unlock_irqrestore(&hardware_lock, flags); | ||
667 | it87_bits_in_byte_out = 0; | ||
668 | it87_send_counter = 0; | ||
669 | } | ||
670 | |||
671 | |||
672 | static void terminate_send(unsigned long len) | ||
673 | { | ||
674 | unsigned long flags; | ||
675 | unsigned long last = 0; | ||
676 | |||
677 | last = it87_send_counter; | ||
678 | /* make sure all necessary data has been sent */ | ||
679 | while (last == it87_send_counter) | ||
680 | send_space(len); | ||
681 | /* wait until all data sent */ | ||
682 | while ((inb(io + IT87_CIR_TSR) & IT87_CIR_TSR_TXFBC) != 0) | ||
683 | ; | ||
684 | /* then re-enable receiver */ | ||
685 | spin_lock_irqsave(&hardware_lock, flags); | ||
686 | it87_RXEN_mask = IT87_CIR_RCR_RXEN; | ||
687 | outb(inb(io + IT87_CIR_RCR) | IT87_CIR_RCR_RXEN, | ||
688 | io + IT87_CIR_RCR); | ||
689 | spin_unlock_irqrestore(&hardware_lock, flags); | ||
690 | } | ||
691 | |||
692 | |||
693 | static int init_hardware(void) | ||
694 | { | ||
695 | unsigned long flags; | ||
696 | unsigned char it87_rcr = 0; | ||
697 | |||
698 | spin_lock_irqsave(&hardware_lock, flags); | ||
699 | /* init cir-port */ | ||
700 | /* enable r/w-access to Baudrate-Register */ | ||
701 | outb(IT87_CIR_IER_BR, io + IT87_CIR_IER); | ||
702 | outb(IT87_CIR_BAUDRATE_DIVISOR % 0x100, io+IT87_CIR_BDLR); | ||
703 | outb(IT87_CIR_BAUDRATE_DIVISOR / 0x100, io+IT87_CIR_BDHR); | ||
704 | /* Baudrate Register off, define IRQs: Input only */ | ||
705 | if (digimatrix) { | ||
706 | outb(IT87_CIR_IER_IEC | IT87_CIR_IER_RFOIE, io + IT87_CIR_IER); | ||
707 | /* RX: HCFS=0, RXDCR = 001b (33,75..38,25 kHz), RXEN=1 */ | ||
708 | } else { | ||
709 | outb(IT87_CIR_IER_IEC | IT87_CIR_IER_RDAIE, io + IT87_CIR_IER); | ||
710 | /* RX: HCFS=0, RXDCR = 001b (35,6..40,3 kHz), RXEN=1 */ | ||
711 | } | ||
712 | it87_rcr = (IT87_CIR_RCR_RXEN & it87_RXEN_mask) | 0x1; | ||
713 | if (it87_enable_demodulator) | ||
714 | it87_rcr |= IT87_CIR_RCR_RXEND; | ||
715 | outb(it87_rcr, io + IT87_CIR_RCR); | ||
716 | if (digimatrix) { | ||
717 | /* Set FIFO depth to 1 byte, and disable TX */ | ||
718 | outb(inb(io + IT87_CIR_TCR1) | 0x00, | ||
719 | io + IT87_CIR_TCR1); | ||
720 | |||
721 | /* | ||
722 | * TX: it87_freq (36kHz), 'reserved' sensitivity | ||
723 | * setting (0x00) | ||
724 | */ | ||
725 | outb(((it87_freq - IT87_CIR_FREQ_MIN) << 3) | 0x00, | ||
726 | io + IT87_CIR_TCR2); | ||
727 | } else { | ||
728 | /* TX: 38kHz, 13,3us (pulse-width) */ | ||
729 | outb(((it87_freq - IT87_CIR_FREQ_MIN) << 3) | 0x06, | ||
730 | io + IT87_CIR_TCR2); | ||
731 | } | ||
732 | spin_unlock_irqrestore(&hardware_lock, flags); | ||
733 | return 0; | ||
734 | } | ||
735 | |||
736 | |||
737 | static void drop_hardware(void) | ||
738 | { | ||
739 | unsigned long flags; | ||
740 | |||
741 | spin_lock_irqsave(&hardware_lock, flags); | ||
742 | disable_irq(irq); | ||
743 | /* receiver disable */ | ||
744 | it87_RXEN_mask = 0; | ||
745 | outb(0x1, io + IT87_CIR_RCR); | ||
746 | /* turn off irqs */ | ||
747 | outb(0, io + IT87_CIR_IER); | ||
748 | /* fifo clear */ | ||
749 | outb(IT87_CIR_TCR1_FIFOCLR, io+IT87_CIR_TCR1); | ||
750 | /* reset */ | ||
751 | outb(IT87_CIR_IER_RESET, io+IT87_CIR_IER); | ||
752 | enable_irq(irq); | ||
753 | spin_unlock_irqrestore(&hardware_lock, flags); | ||
754 | } | ||
755 | |||
756 | |||
757 | static unsigned char it87_read(unsigned char port) | ||
758 | { | ||
759 | outb(port, IT87_ADRPORT); | ||
760 | return inb(IT87_DATAPORT); | ||
761 | } | ||
762 | |||
763 | |||
764 | static void it87_write(unsigned char port, unsigned char data) | ||
765 | { | ||
766 | outb(port, IT87_ADRPORT); | ||
767 | outb(data, IT87_DATAPORT); | ||
768 | } | ||
769 | |||
770 | |||
771 | /* SECTION: Initialisation */ | ||
772 | |||
773 | static int init_port(void) | ||
774 | { | ||
775 | unsigned long hw_flags; | ||
776 | int retval = 0; | ||
777 | |||
778 | unsigned char init_bytes[4] = IT87_INIT; | ||
779 | unsigned char it87_chipid = 0; | ||
780 | unsigned char ldn = 0; | ||
781 | unsigned int it87_io = 0; | ||
782 | unsigned int it87_irq = 0; | ||
783 | |||
784 | /* Enter MB PnP Mode */ | ||
785 | outb(init_bytes[0], IT87_ADRPORT); | ||
786 | outb(init_bytes[1], IT87_ADRPORT); | ||
787 | outb(init_bytes[2], IT87_ADRPORT); | ||
788 | outb(init_bytes[3], IT87_ADRPORT); | ||
789 | |||
790 | /* 8712 or 8705 ? */ | ||
791 | it87_chipid = it87_read(IT87_CHIP_ID1); | ||
792 | if (it87_chipid != 0x87) { | ||
793 | retval = -ENXIO; | ||
794 | return retval; | ||
795 | } | ||
796 | it87_chipid = it87_read(IT87_CHIP_ID2); | ||
797 | if ((it87_chipid != 0x05) && | ||
798 | (it87_chipid != 0x12) && | ||
799 | (it87_chipid != 0x18) && | ||
800 | (it87_chipid != 0x20)) { | ||
801 | printk(KERN_INFO LIRC_DRIVER_NAME | ||
802 | ": no IT8704/05/12/18/20 found (claimed IT87%02x), " | ||
803 | "exiting..\n", it87_chipid); | ||
804 | retval = -ENXIO; | ||
805 | return retval; | ||
806 | } | ||
807 | printk(KERN_INFO LIRC_DRIVER_NAME | ||
808 | ": found IT87%02x.\n", | ||
809 | it87_chipid); | ||
810 | |||
811 | /* get I/O-Port and IRQ */ | ||
812 | if (it87_chipid == 0x12 || it87_chipid == 0x18) | ||
813 | ldn = IT8712_CIR_LDN; | ||
814 | else | ||
815 | ldn = IT8705_CIR_LDN; | ||
816 | it87_write(IT87_LDN, ldn); | ||
817 | |||
818 | it87_io = it87_read(IT87_CIR_BASE_MSB) * 256 + | ||
819 | it87_read(IT87_CIR_BASE_LSB); | ||
820 | if (it87_io == 0) { | ||
821 | if (io == 0) | ||
822 | io = IT87_CIR_DEFAULT_IOBASE; | ||
823 | printk(KERN_INFO LIRC_DRIVER_NAME | ||
824 | ": set default io 0x%x\n", | ||
825 | io); | ||
826 | it87_write(IT87_CIR_BASE_MSB, io / 0x100); | ||
827 | it87_write(IT87_CIR_BASE_LSB, io % 0x100); | ||
828 | } else | ||
829 | io = it87_io; | ||
830 | |||
831 | it87_irq = it87_read(IT87_CIR_IRQ); | ||
832 | if (digimatrix || it87_irq == 0) { | ||
833 | if (irq == 0) | ||
834 | irq = IT87_CIR_DEFAULT_IRQ; | ||
835 | printk(KERN_INFO LIRC_DRIVER_NAME | ||
836 | ": set default irq 0x%x\n", | ||
837 | irq); | ||
838 | it87_write(IT87_CIR_IRQ, irq); | ||
839 | } else | ||
840 | irq = it87_irq; | ||
841 | |||
842 | spin_lock_irqsave(&hardware_lock, hw_flags); | ||
843 | /* reset */ | ||
844 | outb(IT87_CIR_IER_RESET, io+IT87_CIR_IER); | ||
845 | /* fifo clear */ | ||
846 | outb(IT87_CIR_TCR1_FIFOCLR | | ||
847 | /* IT87_CIR_TCR1_ILE | */ | ||
848 | IT87_CIR_TCR1_TXRLE | | ||
849 | IT87_CIR_TCR1_TXENDF, io+IT87_CIR_TCR1); | ||
850 | spin_unlock_irqrestore(&hardware_lock, hw_flags); | ||
851 | |||
852 | /* get I/O port access and IRQ line */ | ||
853 | if (request_region(io, 8, LIRC_DRIVER_NAME) == NULL) { | ||
854 | printk(KERN_ERR LIRC_DRIVER_NAME | ||
855 | ": i/o port 0x%.4x already in use.\n", io); | ||
856 | /* Leaving MB PnP Mode */ | ||
857 | it87_write(IT87_CFGCTRL, 0x2); | ||
858 | return -EBUSY; | ||
859 | } | ||
860 | |||
861 | /* activate CIR-Device */ | ||
862 | it87_write(IT87_CIR_ACT, 0x1); | ||
863 | |||
864 | /* Leaving MB PnP Mode */ | ||
865 | it87_write(IT87_CFGCTRL, 0x2); | ||
866 | |||
867 | retval = request_irq(irq, it87_interrupt, 0 /*IRQF_DISABLED*/, | ||
868 | LIRC_DRIVER_NAME, NULL); | ||
869 | if (retval < 0) { | ||
870 | printk(KERN_ERR LIRC_DRIVER_NAME | ||
871 | ": IRQ %d already in use.\n", | ||
872 | irq); | ||
873 | release_region(io, 8); | ||
874 | return retval; | ||
875 | } | ||
876 | |||
877 | printk(KERN_INFO LIRC_DRIVER_NAME | ||
878 | ": I/O port 0x%.4x, IRQ %d.\n", io, irq); | ||
879 | |||
880 | init_timer(&timerlist); | ||
881 | timerlist.function = it87_timeout; | ||
882 | timerlist.data = 0xabadcafe; | ||
883 | |||
884 | return 0; | ||
885 | } | ||
886 | |||
887 | |||
888 | static void drop_port(void) | ||
889 | { | ||
890 | #if 0 | ||
891 | unsigned char init_bytes[4] = IT87_INIT; | ||
892 | |||
893 | /* Enter MB PnP Mode */ | ||
894 | outb(init_bytes[0], IT87_ADRPORT); | ||
895 | outb(init_bytes[1], IT87_ADRPORT); | ||
896 | outb(init_bytes[2], IT87_ADRPORT); | ||
897 | outb(init_bytes[3], IT87_ADRPORT); | ||
898 | |||
899 | /* deactivate CIR-Device */ | ||
900 | it87_write(IT87_CIR_ACT, 0x0); | ||
901 | |||
902 | /* Leaving MB PnP Mode */ | ||
903 | it87_write(IT87_CFGCTRL, 0x2); | ||
904 | #endif | ||
905 | |||
906 | del_timer_sync(&timerlist); | ||
907 | free_irq(irq, NULL); | ||
908 | release_region(io, 8); | ||
909 | } | ||
910 | |||
911 | |||
912 | static int init_lirc_it87(void) | ||
913 | { | ||
914 | int retval; | ||
915 | |||
916 | init_waitqueue_head(&lirc_read_queue); | ||
917 | retval = init_port(); | ||
918 | if (retval < 0) | ||
919 | return retval; | ||
920 | init_hardware(); | ||
921 | printk(KERN_INFO LIRC_DRIVER_NAME ": Installed.\n"); | ||
922 | return 0; | ||
923 | } | ||
924 | |||
925 | static int it87_probe(struct pnp_dev *pnp_dev, | ||
926 | const struct pnp_device_id *dev_id) | ||
927 | { | ||
928 | int retval; | ||
929 | |||
930 | driver.dev = &pnp_dev->dev; | ||
931 | |||
932 | retval = init_chrdev(); | ||
933 | if (retval < 0) | ||
934 | return retval; | ||
935 | |||
936 | retval = init_lirc_it87(); | ||
937 | if (retval) | ||
938 | goto init_lirc_it87_failed; | ||
939 | |||
940 | return 0; | ||
941 | |||
942 | init_lirc_it87_failed: | ||
943 | drop_chrdev(); | ||
944 | |||
945 | return retval; | ||
946 | } | ||
947 | |||
948 | static int __init lirc_it87_init(void) | ||
949 | { | ||
950 | return pnp_register_driver(&it87_pnp_driver); | ||
951 | } | ||
952 | |||
953 | |||
954 | static void __exit lirc_it87_exit(void) | ||
955 | { | ||
956 | drop_hardware(); | ||
957 | drop_chrdev(); | ||
958 | drop_port(); | ||
959 | pnp_unregister_driver(&it87_pnp_driver); | ||
960 | printk(KERN_INFO LIRC_DRIVER_NAME ": Uninstalled.\n"); | ||
961 | } | ||
962 | |||
963 | /* SECTION: PNP for ITE8704/18 */ | ||
964 | |||
965 | static const struct pnp_device_id pnp_dev_table[] = { | ||
966 | {"ITE8704", 0}, | ||
967 | {} | ||
968 | }; | ||
969 | |||
970 | MODULE_DEVICE_TABLE(pnp, pnp_dev_table); | ||
971 | |||
972 | static struct pnp_driver it87_pnp_driver = { | ||
973 | .name = LIRC_DRIVER_NAME, | ||
974 | .id_table = pnp_dev_table, | ||
975 | .probe = it87_probe, | ||
976 | }; | ||
977 | |||
978 | module_init(lirc_it87_init); | ||
979 | module_exit(lirc_it87_exit); | ||
980 | |||
981 | MODULE_DESCRIPTION("LIRC driver for ITE IT8704/05/12/18/20 CIR port"); | ||
982 | MODULE_AUTHOR("Hans-Gunter Lutke Uphues"); | ||
983 | MODULE_LICENSE("GPL"); | ||
984 | |||
985 | module_param(io, int, S_IRUGO); | ||
986 | MODULE_PARM_DESC(io, "I/O base address (default: 0x310)"); | ||
987 | |||
988 | module_param(irq, int, S_IRUGO); | ||
989 | #ifdef LIRC_IT87_DIGIMATRIX | ||
990 | MODULE_PARM_DESC(irq, "Interrupt (1,3-12) (default: 9)"); | ||
991 | #else | ||
992 | MODULE_PARM_DESC(irq, "Interrupt (1,3-12) (default: 7)"); | ||
993 | #endif | ||
994 | |||
995 | module_param(it87_enable_demodulator, bool, S_IRUGO); | ||
996 | MODULE_PARM_DESC(it87_enable_demodulator, | ||
997 | "Receiver demodulator enable/disable (1/0), default: 0"); | ||
998 | |||
999 | module_param(debug, bool, S_IRUGO | S_IWUSR); | ||
1000 | MODULE_PARM_DESC(debug, "Enable debugging messages"); | ||
1001 | |||
1002 | module_param(digimatrix, bool, S_IRUGO | S_IWUSR); | ||
1003 | #ifdef LIRC_IT87_DIGIMATRIX | ||
1004 | MODULE_PARM_DESC(digimatrix, | ||
1005 | "Asus Digimatrix it87 compat. enable/disable (1/0), default: 1"); | ||
1006 | #else | ||
1007 | MODULE_PARM_DESC(digimatrix, | ||
1008 | "Asus Digimatrix it87 compat. enable/disable (1/0), default: 0"); | ||
1009 | #endif | ||
1010 | |||
1011 | |||
1012 | module_param(it87_freq, int, S_IRUGO); | ||
1013 | #ifdef LIRC_IT87_DIGIMATRIX | ||
1014 | MODULE_PARM_DESC(it87_freq, | ||
1015 | "Carrier demodulator frequency (kHz), (default: 36)"); | ||
1016 | #else | ||
1017 | MODULE_PARM_DESC(it87_freq, | ||
1018 | "Carrier demodulator frequency (kHz), (default: 38)"); | ||
1019 | #endif | ||
diff --git a/drivers/staging/lirc/lirc_it87.h b/drivers/staging/lirc/lirc_it87.h new file mode 100644 index 000000000000..cf021c893a35 --- /dev/null +++ b/drivers/staging/lirc/lirc_it87.h | |||
@@ -0,0 +1,116 @@ | |||
1 | /* lirc_it87.h */ | ||
2 | /* SECTION: Definitions */ | ||
3 | |||
4 | /********************************* ITE IT87xx ************************/ | ||
5 | |||
6 | /* based on the following documentation from ITE: | ||
7 | a) IT8712F Preliminary CIR Programming Guide V0.1 | ||
8 | b) IT8705F Simple LPC I/O Preliminary Specification V0.3 | ||
9 | c) IT8712F EC-LPC I/O Preliminary Specification V0.5 | ||
10 | */ | ||
11 | |||
12 | /* IT8712/05 Ports: */ | ||
13 | #define IT87_ADRPORT 0x2e | ||
14 | #define IT87_DATAPORT 0x2f | ||
15 | #define IT87_INIT {0x87, 0x01, 0x55, 0x55} | ||
16 | |||
17 | /* alternate Ports: */ | ||
18 | /* | ||
19 | #define IT87_ADRPORT 0x4e | ||
20 | #define IT87_DATAPORT 0x4f | ||
21 | #define IT87_INIT {0x87, 0x01, 0x55, 0xaa} | ||
22 | */ | ||
23 | |||
24 | /* IT8712/05 Registers */ | ||
25 | #define IT87_CFGCTRL 0x2 | ||
26 | #define IT87_LDN 0x7 | ||
27 | #define IT87_CHIP_ID1 0x20 | ||
28 | #define IT87_CHIP_ID2 0x21 | ||
29 | #define IT87_CFG_VERSION 0x22 | ||
30 | #define IT87_SWSUSPEND 0x23 | ||
31 | |||
32 | #define IT8712_CIR_LDN 0xa | ||
33 | #define IT8705_CIR_LDN 0x7 | ||
34 | |||
35 | /* CIR Configuration Registers: */ | ||
36 | #define IT87_CIR_ACT 0x30 | ||
37 | #define IT87_CIR_BASE_MSB 0x60 | ||
38 | #define IT87_CIR_BASE_LSB 0x61 | ||
39 | #define IT87_CIR_IRQ 0x70 | ||
40 | #define IT87_CIR_CONFIG 0xf0 | ||
41 | |||
42 | /* List of IT87_CIR registers: offset to BaseAddr */ | ||
43 | #define IT87_CIR_DR 0 | ||
44 | #define IT87_CIR_IER 1 | ||
45 | #define IT87_CIR_RCR 2 | ||
46 | #define IT87_CIR_TCR1 3 | ||
47 | #define IT87_CIR_TCR2 4 | ||
48 | #define IT87_CIR_TSR 5 | ||
49 | #define IT87_CIR_RSR 6 | ||
50 | #define IT87_CIR_BDLR 5 | ||
51 | #define IT87_CIR_BDHR 6 | ||
52 | #define IT87_CIR_IIR 7 | ||
53 | |||
54 | /* Bit Definition */ | ||
55 | /* IER: */ | ||
56 | #define IT87_CIR_IER_TM_EN 0x80 | ||
57 | #define IT87_CIR_IER_RESEVED 0x40 | ||
58 | #define IT87_CIR_IER_RESET 0x20 | ||
59 | #define IT87_CIR_IER_BR 0x10 | ||
60 | #define IT87_CIR_IER_IEC 0x8 | ||
61 | #define IT87_CIR_IER_RFOIE 0x4 | ||
62 | #define IT87_CIR_IER_RDAIE 0x2 | ||
63 | #define IT87_CIR_IER_TLDLIE 0x1 | ||
64 | |||
65 | /* RCR: */ | ||
66 | #define IT87_CIR_RCR_RDWOS 0x80 | ||
67 | #define IT87_CIR_RCR_HCFS 0x40 | ||
68 | #define IT87_CIR_RCR_RXEN 0x20 | ||
69 | #define IT87_CIR_RCR_RXEND 0x10 | ||
70 | #define IT87_CIR_RCR_RXACT 0x8 | ||
71 | #define IT87_CIR_RCR_RXDCR 0x7 | ||
72 | |||
73 | /* TCR1: */ | ||
74 | #define IT87_CIR_TCR1_FIFOCLR 0x80 | ||
75 | #define IT87_CIR_TCR1_ILE 0x40 | ||
76 | #define IT87_CIR_TCR1_FIFOTL 0x30 | ||
77 | #define IT87_CIR_TCR1_TXRLE 0x8 | ||
78 | #define IT87_CIR_TCR1_TXENDF 0x4 | ||
79 | #define IT87_CIR_TCR1_TXMPM 0x3 | ||
80 | |||
81 | /* TCR2: */ | ||
82 | #define IT87_CIR_TCR2_CFQ 0xf8 | ||
83 | #define IT87_CIR_TCR2_TXMPW 0x7 | ||
84 | |||
85 | /* TSR: */ | ||
86 | #define IT87_CIR_TSR_RESERVED 0xc0 | ||
87 | #define IT87_CIR_TSR_TXFBC 0x3f | ||
88 | |||
89 | /* RSR: */ | ||
90 | #define IT87_CIR_RSR_RXFTO 0x80 | ||
91 | #define IT87_CIR_RSR_RESERVED 0x40 | ||
92 | #define IT87_CIR_RSR_RXFBC 0x3f | ||
93 | |||
94 | /* IIR: */ | ||
95 | #define IT87_CIR_IIR_RESERVED 0xf8 | ||
96 | #define IT87_CIR_IIR_IID 0x6 | ||
97 | #define IT87_CIR_IIR_IIP 0x1 | ||
98 | |||
99 | /* TM: */ | ||
100 | #define IT87_CIR_TM_IL_SEL 0x80 | ||
101 | #define IT87_CIR_TM_RESERVED 0x40 | ||
102 | #define IT87_CIR_TM_TM_REG 0x3f | ||
103 | |||
104 | #define IT87_CIR_FIFO_SIZE 32 | ||
105 | |||
106 | /* Baudratedivisor for IT87: power of 2: only 1,2,4 or 8) */ | ||
107 | #define IT87_CIR_BAUDRATE_DIVISOR 0x1 | ||
108 | #define IT87_CIR_DEFAULT_IOBASE 0x310 | ||
109 | #define IT87_CIR_DEFAULT_IRQ 0x7 | ||
110 | #define IT87_CIR_SPACE 0x00 | ||
111 | #define IT87_CIR_PULSE 0xff | ||
112 | #define IT87_CIR_FREQ_MIN 27 | ||
113 | #define IT87_CIR_FREQ_MAX 58 | ||
114 | #define TIME_CONST (IT87_CIR_BAUDRATE_DIVISOR * 8000000ul / 115200ul) | ||
115 | |||
116 | /********************************* ITE IT87xx ************************/ | ||