Lines 48-53
Link Here
|
48 |
* Steve Davies <steve@daviesfam.org> July 2001 |
48 |
* Steve Davies <steve@daviesfam.org> July 2001 |
49 |
*/ |
49 |
*/ |
50 |
|
50 |
|
|
|
51 |
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
52 |
|
51 |
#include <linux/module.h> |
53 |
#include <linux/module.h> |
52 |
#include <linux/errno.h> |
54 |
#include <linux/errno.h> |
53 |
#include <linux/signal.h> |
55 |
#include <linux/signal.h> |
Lines 65-97
Link Here
|
65 |
#include <linux/delay.h> |
67 |
#include <linux/delay.h> |
66 |
#include <linux/poll.h> |
68 |
#include <linux/poll.h> |
67 |
#include <linux/platform_device.h> |
69 |
#include <linux/platform_device.h> |
68 |
|
70 |
#include <linux/gpio.h> |
69 |
#include "drivers/kcompat.h" |
|
|
70 |
#if LINUX_VERSION_CODE > KERNEL_VERSION(3, 3, 0) |
71 |
#include <asm/switch_to.h> |
72 |
#else |
73 |
#include <asm/system.h> |
74 |
#endif |
75 |
#include <linux/io.h> |
71 |
#include <linux/io.h> |
76 |
#include <linux/irq.h> |
72 |
#include <linux/irq.h> |
77 |
#include <linux/fcntl.h> |
73 |
#include <linux/fcntl.h> |
78 |
#include <linux/spinlock.h> |
74 |
#include <linux/spinlock.h> |
79 |
|
75 |
|
80 |
#ifdef CONFIG_LIRC_SERIAL_NSLU2 |
|
|
81 |
#include <asm/hardware.h> |
82 |
#endif |
83 |
/* From Intel IXP42X Developer's Manual (#252480-005): */ |
76 |
/* From Intel IXP42X Developer's Manual (#252480-005): */ |
84 |
/* ftp://download.intel.com/design/network/manuals/25248005.pdf */ |
77 |
/* ftp://download.intel.com/design/network/manuals/25248005.pdf */ |
85 |
#define UART_IE_IXP42X_UUE 0x40 /* IXP42X UART Unit enable */ |
78 |
#define UART_IE_IXP42X_UUE 0x40 /* IXP42X UART Unit enable */ |
86 |
#define UART_IE_IXP42X_RTOIE 0x10 /* IXP42X Receiver Data Timeout int.enable */ |
79 |
#define UART_IE_IXP42X_RTOIE 0x10 /* IXP42X Receiver Data Timeout int.enable */ |
87 |
|
80 |
|
88 |
#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 35) |
|
|
89 |
#include <media/lirc.h> |
81 |
#include <media/lirc.h> |
90 |
#include <media/lirc_dev.h> |
82 |
#include <media/lirc_dev.h> |
91 |
#else |
|
|
92 |
#include "drivers/lirc.h" |
93 |
#include "drivers/lirc_dev/lirc_dev.h" |
94 |
#endif |
95 |
|
83 |
|
96 |
#define LIRC_DRIVER_NAME "lirc_serial" |
84 |
#define LIRC_DRIVER_NAME "lirc_serial" |
97 |
|
85 |
|
Lines 117-129
Link Here
|
117 |
static int type; |
105 |
static int type; |
118 |
static int io; |
106 |
static int io; |
119 |
static int irq; |
107 |
static int irq; |
120 |
static int iommap; |
108 |
static bool iommap; |
121 |
static int ioshift; |
109 |
static int ioshift; |
122 |
static int softcarrier = 1; |
110 |
static bool softcarrier = true; |
123 |
static int share_irq; |
111 |
static bool share_irq; |
124 |
static int debug; |
112 |
static bool debug; |
125 |
static int sense = -1; /* -1 = auto, 0 = active high, 1 = active low */ |
113 |
static int sense = -1; /* -1 = auto, 0 = active high, 1 = active low */ |
126 |
static int txsense; /* 0 = active high, 1 = active low */ |
114 |
static bool txsense; /* 0 = active high, 1 = active low */ |
127 |
|
115 |
|
128 |
#define dprintk(fmt, args...) \ |
116 |
#define dprintk(fmt, args...) \ |
129 |
do { \ |
117 |
do { \ |
Lines 140-145
Link Here
|
140 |
|
128 |
|
141 |
static struct lirc_serial hardware[] = { |
129 |
static struct lirc_serial hardware[] = { |
142 |
[LIRC_HOMEBREW] = { |
130 |
[LIRC_HOMEBREW] = { |
|
|
131 |
.lock = __SPIN_LOCK_UNLOCKED(hardware[LIRC_HOMEBREW].lock), |
143 |
.signal_pin = UART_MSR_DCD, |
132 |
.signal_pin = UART_MSR_DCD, |
144 |
.signal_pin_change = UART_MSR_DDCD, |
133 |
.signal_pin_change = UART_MSR_DDCD, |
145 |
.on = (UART_MCR_RTS | UART_MCR_OUT2 | UART_MCR_DTR), |
134 |
.on = (UART_MCR_RTS | UART_MCR_OUT2 | UART_MCR_DTR), |
Lines 156-161
Link Here
|
156 |
}, |
145 |
}, |
157 |
|
146 |
|
158 |
[LIRC_IRDEO] = { |
147 |
[LIRC_IRDEO] = { |
|
|
148 |
.lock = __SPIN_LOCK_UNLOCKED(hardware[LIRC_IRDEO].lock), |
159 |
.signal_pin = UART_MSR_DSR, |
149 |
.signal_pin = UART_MSR_DSR, |
160 |
.signal_pin_change = UART_MSR_DDSR, |
150 |
.signal_pin_change = UART_MSR_DDSR, |
161 |
.on = UART_MCR_OUT2, |
151 |
.on = UART_MCR_OUT2, |
Lines 167-172
Link Here
|
167 |
}, |
157 |
}, |
168 |
|
158 |
|
169 |
[LIRC_IRDEO_REMOTE] = { |
159 |
[LIRC_IRDEO_REMOTE] = { |
|
|
160 |
.lock = __SPIN_LOCK_UNLOCKED(hardware[LIRC_IRDEO_REMOTE].lock), |
170 |
.signal_pin = UART_MSR_DSR, |
161 |
.signal_pin = UART_MSR_DSR, |
171 |
.signal_pin_change = UART_MSR_DDSR, |
162 |
.signal_pin_change = UART_MSR_DDSR, |
172 |
.on = (UART_MCR_RTS | UART_MCR_DTR | UART_MCR_OUT2), |
163 |
.on = (UART_MCR_RTS | UART_MCR_DTR | UART_MCR_OUT2), |
Lines 178-183
Link Here
|
178 |
}, |
169 |
}, |
179 |
|
170 |
|
180 |
[LIRC_ANIMAX] = { |
171 |
[LIRC_ANIMAX] = { |
|
|
172 |
.lock = __SPIN_LOCK_UNLOCKED(hardware[LIRC_ANIMAX].lock), |
181 |
.signal_pin = UART_MSR_DCD, |
173 |
.signal_pin = UART_MSR_DCD, |
182 |
.signal_pin_change = UART_MSR_DDCD, |
174 |
.signal_pin_change = UART_MSR_DDCD, |
183 |
.on = 0, |
175 |
.on = 0, |
Lines 188-193
Link Here
|
188 |
}, |
180 |
}, |
189 |
|
181 |
|
190 |
[LIRC_IGOR] = { |
182 |
[LIRC_IGOR] = { |
|
|
183 |
.lock = __SPIN_LOCK_UNLOCKED(hardware[LIRC_IGOR].lock), |
191 |
.signal_pin = UART_MSR_DSR, |
184 |
.signal_pin = UART_MSR_DSR, |
192 |
.signal_pin_change = UART_MSR_DDSR, |
185 |
.signal_pin_change = UART_MSR_DDSR, |
193 |
.on = (UART_MCR_RTS | UART_MCR_OUT2 | UART_MCR_DTR), |
186 |
.on = (UART_MCR_RTS | UART_MCR_OUT2 | UART_MCR_DTR), |
Lines 202-233
Link Here
|
202 |
.features = LIRC_CAN_REC_MODE2 |
195 |
.features = LIRC_CAN_REC_MODE2 |
203 |
#endif |
196 |
#endif |
204 |
}, |
197 |
}, |
205 |
|
|
|
206 |
#ifdef CONFIG_LIRC_SERIAL_NSLU2 |
207 |
/* |
208 |
* Modified Linksys Network Storage Link USB 2.0 (NSLU2): |
209 |
* We receive on CTS of the 2nd serial port (R142,LHS), we |
210 |
* transmit with a IR diode between GPIO[1] (green status LED), |
211 |
* and ground (Matthias Goebl <matthias.goebl@goebl.net>). |
212 |
* See also http://www.nslu2-linux.org for this device |
213 |
*/ |
214 |
[LIRC_NSLU2] = { |
215 |
.signal_pin = UART_MSR_CTS, |
216 |
.signal_pin_change = UART_MSR_DCTS, |
217 |
.on = (UART_MCR_RTS | UART_MCR_OUT2 | UART_MCR_DTR), |
218 |
.off = (UART_MCR_RTS | UART_MCR_OUT2), |
219 |
.send_pulse = send_pulse_homebrew, |
220 |
.send_space = send_space_homebrew, |
221 |
#ifdef CONFIG_LIRC_SERIAL_TRANSMITTER |
222 |
.features = (LIRC_CAN_SET_SEND_DUTY_CYCLE | |
223 |
LIRC_CAN_SET_SEND_CARRIER | |
224 |
LIRC_CAN_SEND_PULSE | LIRC_CAN_REC_MODE2) |
225 |
#else |
226 |
.features = LIRC_CAN_REC_MODE2 |
227 |
#endif |
228 |
}, |
229 |
#endif |
230 |
|
231 |
}; |
198 |
}; |
232 |
|
199 |
|
233 |
#define RS_ISR_PASS_LIMIT 256 |
200 |
#define RS_ISR_PASS_LIMIT 256 |
Lines 299-305
Link Here
|
299 |
/* fetch serial input packet (1 byte) from register offset */ |
266 |
/* fetch serial input packet (1 byte) from register offset */ |
300 |
static u8 sinp(int offset) |
267 |
static u8 sinp(int offset) |
301 |
{ |
268 |
{ |
302 |
if (iommap != 0) |
269 |
if (iommap) |
303 |
/* the register is memory-mapped */ |
270 |
/* the register is memory-mapped */ |
304 |
offset <<= ioshift; |
271 |
offset <<= ioshift; |
305 |
|
272 |
|
Lines 309-315
Link Here
|
309 |
/* write serial output packet (1 byte) of value to register offset */ |
276 |
/* write serial output packet (1 byte) of value to register offset */ |
310 |
static void soutp(int offset, u8 value) |
277 |
static void soutp(int offset, u8 value) |
311 |
{ |
278 |
{ |
312 |
if (iommap != 0) |
279 |
if (iommap) |
313 |
/* the register is memory-mapped */ |
280 |
/* the register is memory-mapped */ |
314 |
offset <<= ioshift; |
281 |
offset <<= ioshift; |
315 |
|
282 |
|
Lines 318-333
Link Here
|
318 |
|
285 |
|
319 |
static void on(void) |
286 |
static void on(void) |
320 |
{ |
287 |
{ |
321 |
#ifdef CONFIG_LIRC_SERIAL_NSLU2 |
|
|
322 |
/* |
323 |
* On NSLU2, we put the transmit diode between the output of the green |
324 |
* status LED and ground |
325 |
*/ |
326 |
if (type == LIRC_NSLU2) { |
327 |
gpio_line_set(NSLU2_LED_GRN, IXP4XX_GPIO_LOW); |
328 |
return; |
329 |
} |
330 |
#endif |
331 |
if (txsense) |
288 |
if (txsense) |
332 |
soutp(UART_MCR, hardware[type].off); |
289 |
soutp(UART_MCR, hardware[type].off); |
333 |
else |
290 |
else |
Lines 336-347
Link Here
|
336 |
|
293 |
|
337 |
static void off(void) |
294 |
static void off(void) |
338 |
{ |
295 |
{ |
339 |
#ifdef CONFIG_LIRC_SERIAL_NSLU2 |
|
|
340 |
if (type == LIRC_NSLU2) { |
341 |
gpio_line_set(NSLU2_LED_GRN, IXP4XX_GPIO_HIGH); |
342 |
return; |
343 |
} |
344 |
#endif |
345 |
if (txsense) |
296 |
if (txsense) |
346 |
soutp(UART_MCR, hardware[type].on); |
297 |
soutp(UART_MCR, hardware[type].on); |
347 |
else |
298 |
else |
Lines 387-399
Link Here
|
387 |
duty_cycle = new_duty_cycle; |
338 |
duty_cycle = new_duty_cycle; |
388 |
freq = new_freq; |
339 |
freq = new_freq; |
389 |
|
340 |
|
390 |
loops_per_sec = current_cpu_data.loops_per_jiffy; |
341 |
loops_per_sec = __this_cpu_read(cpu.info.loops_per_jiffy); |
391 |
loops_per_sec *= HZ; |
342 |
loops_per_sec *= HZ; |
392 |
|
343 |
|
393 |
/* How many clocks in a microsecond?, avoiding long long divide */ |
344 |
/* How many clocks in a microsecond?, avoiding long long divide */ |
394 |
work = loops_per_sec; |
345 |
work = loops_per_sec; |
395 |
work *= 4295; /* 4295 = 2^32 / 1e6 */ |
346 |
work *= 4295; /* 4295 = 2^32 / 1e6 */ |
396 |
conv_us_to_clocks = (work >> 32); |
347 |
conv_us_to_clocks = work >> 32; |
397 |
|
348 |
|
398 |
/* |
349 |
/* |
399 |
* Carrier period in clocks, approach good up to 32GHz clock, |
350 |
* Carrier period in clocks, approach good up to 32GHz clock, |
Lines 408-414
Link Here
|
408 |
dprintk("in init_timing_params, freq=%d, duty_cycle=%d, " |
359 |
dprintk("in init_timing_params, freq=%d, duty_cycle=%d, " |
409 |
"clk/jiffy=%ld, pulse=%ld, space=%ld, " |
360 |
"clk/jiffy=%ld, pulse=%ld, space=%ld, " |
410 |
"conv_us_to_clocks=%ld\n", |
361 |
"conv_us_to_clocks=%ld\n", |
411 |
freq, duty_cycle, current_cpu_data.loops_per_jiffy, |
362 |
freq, duty_cycle, __this_cpu_read(cpu_info.loops_per_jiffy), |
412 |
pulse_width, space_width, conv_us_to_clocks); |
363 |
pulse_width, space_width, conv_us_to_clocks); |
413 |
return 0; |
364 |
return 0; |
414 |
} |
365 |
} |
Lines 431-438
Link Here
|
431 |
period = 256 * 1000000L / freq; |
382 |
period = 256 * 1000000L / freq; |
432 |
pulse_width = period * duty_cycle / 100; |
383 |
pulse_width = period * duty_cycle / 100; |
433 |
space_width = period - pulse_width; |
384 |
space_width = period - pulse_width; |
434 |
dprintk("in init_timing_params, freq=%d pulse=%ld, " |
385 |
dprintk("in init_timing_params, freq=%d pulse=%ld, space=%ld\n", |
435 |
"space=%ld\n", freq, pulse_width, space_width); |
386 |
freq, pulse_width, space_width); |
436 |
return 0; |
387 |
return 0; |
437 |
} |
388 |
} |
438 |
#endif /* USE_RDTSC */ |
389 |
#endif /* USE_RDTSC */ |
Lines 545-550
Link Here
|
545 |
{ |
496 |
{ |
546 |
int flag; |
497 |
int flag; |
547 |
unsigned long actual, target, d; |
498 |
unsigned long actual, target, d; |
|
|
499 |
|
548 |
length <<= 8; |
500 |
length <<= 8; |
549 |
|
501 |
|
550 |
actual = 0; target = 0; flag = 0; |
502 |
actual = 0; target = 0; flag = 0; |
Lines 577-587
Link Here
|
577 |
|
529 |
|
578 |
if (softcarrier) |
530 |
if (softcarrier) |
579 |
return send_pulse_homebrew_softcarrier(length); |
531 |
return send_pulse_homebrew_softcarrier(length); |
580 |
else { |
532 |
|
581 |
on(); |
533 |
on(); |
582 |
safe_udelay(length); |
534 |
safe_udelay(length); |
583 |
return 0; |
535 |
return 0; |
584 |
} |
|
|
585 |
} |
536 |
} |
586 |
|
537 |
|
587 |
static void send_space_irdeo(long length) |
538 |
static void send_space_irdeo(long length) |
Lines 653-663
Link Here
|
653 |
rbwrite(l); |
604 |
rbwrite(l); |
654 |
} |
605 |
} |
655 |
|
606 |
|
656 |
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) |
607 |
static irqreturn_t lirc_irq_handler(int i, void *blah) |
657 |
static irqreturn_t irq_handler(int i, void *blah) |
|
|
658 |
#else |
659 |
static irqreturn_t irq_handler(int i, void *blah, struct pt_regs *regs) |
660 |
#endif |
661 |
{ |
608 |
{ |
662 |
struct timeval tv; |
609 |
struct timeval tv; |
663 |
int counter, dcd; |
610 |
int counter, dcd; |
Lines 676-683
Link Here
|
676 |
counter++; |
623 |
counter++; |
677 |
status = sinp(UART_MSR); |
624 |
status = sinp(UART_MSR); |
678 |
if (counter > RS_ISR_PASS_LIMIT) { |
625 |
if (counter > RS_ISR_PASS_LIMIT) { |
679 |
printk(KERN_WARNING LIRC_DRIVER_NAME ": AIEEEE: " |
626 |
pr_warn("AIEEEE: We're caught!\n"); |
680 |
"We're caught!\n"); |
|
|
681 |
break; |
627 |
break; |
682 |
} |
628 |
} |
683 |
if ((status & hardware[type].signal_pin_change) |
629 |
if ((status & hardware[type].signal_pin_change) |
Lines 712-722
Link Here
|
712 |
dcd = (status & hardware[type].signal_pin) ? 1 : 0; |
658 |
dcd = (status & hardware[type].signal_pin) ? 1 : 0; |
713 |
|
659 |
|
714 |
if (dcd == last_dcd) { |
660 |
if (dcd == last_dcd) { |
715 |
printk(KERN_WARNING LIRC_DRIVER_NAME |
661 |
pr_warn("ignoring spike: %d %d %lx %lx %lx %lx\n", |
716 |
": ignoring spike: %d %d %lx %lx %lx %lx\n", |
662 |
dcd, sense, |
717 |
dcd, sense, |
663 |
tv.tv_sec, lasttv.tv_sec, |
718 |
tv.tv_sec, lasttv.tv_sec, |
664 |
(unsigned long)tv.tv_usec, |
719 |
tv.tv_usec, lasttv.tv_usec); |
665 |
(unsigned long)lasttv.tv_usec); |
720 |
continue; |
666 |
continue; |
721 |
} |
667 |
} |
722 |
|
668 |
|
Lines 724-748
Link Here
|
724 |
if (tv.tv_sec < lasttv.tv_sec || |
670 |
if (tv.tv_sec < lasttv.tv_sec || |
725 |
(tv.tv_sec == lasttv.tv_sec && |
671 |
(tv.tv_sec == lasttv.tv_sec && |
726 |
tv.tv_usec < lasttv.tv_usec)) { |
672 |
tv.tv_usec < lasttv.tv_usec)) { |
727 |
printk(KERN_WARNING LIRC_DRIVER_NAME |
673 |
pr_warn("AIEEEE: your clock just jumped backwards\n"); |
728 |
": AIEEEE: your clock just jumped " |
674 |
pr_warn("%d %d %lx %lx %lx %lx\n", |
729 |
"backwards\n"); |
675 |
dcd, sense, |
730 |
printk(KERN_WARNING LIRC_DRIVER_NAME |
676 |
tv.tv_sec, lasttv.tv_sec, |
731 |
": %d %d %lx %lx %lx %lx\n", |
677 |
(unsigned long)tv.tv_usec, |
732 |
dcd, sense, |
678 |
(unsigned long)lasttv.tv_usec); |
733 |
tv.tv_sec, lasttv.tv_sec, |
|
|
734 |
tv.tv_usec, lasttv.tv_usec); |
735 |
data = PULSE_MASK; |
679 |
data = PULSE_MASK; |
736 |
} else if (deltv > 15) { |
680 |
} else if (deltv > 15) { |
737 |
data = PULSE_MASK; /* really long time */ |
681 |
data = PULSE_MASK; /* really long time */ |
738 |
if (!(dcd^sense)) { |
682 |
if (!(dcd^sense)) { |
739 |
/* sanity check */ |
683 |
/* sanity check */ |
740 |
printk(KERN_WARNING LIRC_DRIVER_NAME |
684 |
pr_warn("AIEEEE: %d %d %lx %lx %lx %lx\n", |
741 |
": AIEEEE: " |
685 |
dcd, sense, |
742 |
"%d %d %lx %lx %lx %lx\n", |
686 |
tv.tv_sec, lasttv.tv_sec, |
743 |
dcd, sense, |
687 |
(unsigned long)tv.tv_usec, |
744 |
tv.tv_sec, lasttv.tv_sec, |
688 |
(unsigned long)lasttv.tv_usec); |
745 |
tv.tv_usec, lasttv.tv_usec); |
|
|
746 |
/* |
689 |
/* |
747 |
* detecting pulse while this |
690 |
* detecting pulse while this |
748 |
* MUST be a space! |
691 |
* MUST be a space! |
Lines 785-793
Link Here
|
785 |
soutp(UART_IER, scratch); |
728 |
soutp(UART_IER, scratch); |
786 |
if (scratch2 != 0 || scratch3 != 0x0f) { |
729 |
if (scratch2 != 0 || scratch3 != 0x0f) { |
787 |
/* we fail, there's nothing here */ |
730 |
/* we fail, there's nothing here */ |
788 |
printk(KERN_ERR LIRC_DRIVER_NAME ": port existence test " |
731 |
pr_err("port existence test failed, cannot continue\n"); |
789 |
"failed, cannot continue\n"); |
732 |
return -ENODEV; |
790 |
return -EINVAL; |
|
|
791 |
} |
733 |
} |
792 |
|
734 |
|
793 |
|
735 |
|
Lines 805-824
Link Here
|
805 |
sinp(UART_IIR); |
747 |
sinp(UART_IIR); |
806 |
sinp(UART_MSR); |
748 |
sinp(UART_MSR); |
807 |
|
749 |
|
808 |
#ifdef CONFIG_LIRC_SERIAL_NSLU2 |
|
|
809 |
if (type == LIRC_NSLU2) { |
810 |
/* Setup NSLU2 UART */ |
811 |
|
812 |
/* Enable UART */ |
813 |
soutp(UART_IER, sinp(UART_IER) | UART_IE_IXP42X_UUE); |
814 |
/* Disable Receiver data Time out interrupt */ |
815 |
soutp(UART_IER, sinp(UART_IER) & ~UART_IE_IXP42X_RTOIE); |
816 |
/* set out2 = interrupt unmask; off() doesn't set MCR |
817 |
on NSLU2 */ |
818 |
soutp(UART_MCR, UART_MCR_RTS|UART_MCR_OUT2); |
819 |
} |
820 |
#endif |
821 |
|
822 |
/* Set line for power source */ |
750 |
/* Set line for power source */ |
823 |
off(); |
751 |
off(); |
824 |
|
752 |
|
Lines 850-858
Link Here
|
850 |
return 0; |
778 |
return 0; |
851 |
} |
779 |
} |
852 |
|
780 |
|
853 |
static int init_port(void) |
781 |
static int lirc_serial_probe(struct platform_device *dev) |
854 |
{ |
782 |
{ |
855 |
int i, nlow, nhigh; |
783 |
int i, nlow, nhigh, result; |
|
|
784 |
|
785 |
result = devm_request_irq(&dev->dev, irq, lirc_irq_handler, |
786 |
(share_irq ? IRQF_SHARED : 0), |
787 |
LIRC_DRIVER_NAME, &hardware); |
788 |
if (result < 0) { |
789 |
if (result == -EBUSY) |
790 |
dev_err(&dev->dev, "IRQ %d busy\n", irq); |
791 |
else if (result == -EINVAL) |
792 |
dev_err(&dev->dev, "Bad irq number or handler\n"); |
793 |
return result; |
794 |
} |
856 |
|
795 |
|
857 |
/* Reserve io region. */ |
796 |
/* Reserve io region. */ |
858 |
/* |
797 |
/* |
Lines 860-883
Link Here
|
860 |
* For memory mapped I/O you *might* need to use ioremap() first, |
799 |
* For memory mapped I/O you *might* need to use ioremap() first, |
861 |
* for the NSLU2 it's done in boot code. |
800 |
* for the NSLU2 it's done in boot code. |
862 |
*/ |
801 |
*/ |
863 |
if (((iommap != 0) |
802 |
if (((iommap) |
864 |
&& (request_mem_region(iommap, 8 << ioshift, |
803 |
&& (devm_request_mem_region(&dev->dev, iommap, 8 << ioshift, |
865 |
LIRC_DRIVER_NAME) == NULL)) |
804 |
LIRC_DRIVER_NAME) == NULL)) |
866 |
|| ((iommap == 0) |
805 |
|| ((!iommap) |
867 |
&& (request_region(io, 8, LIRC_DRIVER_NAME) == NULL))) { |
806 |
&& (devm_request_region(&dev->dev, io, 8, |
868 |
printk(KERN_ERR LIRC_DRIVER_NAME |
807 |
LIRC_DRIVER_NAME) == NULL))) { |
869 |
": port %04x already in use\n", io); |
808 |
dev_err(&dev->dev, "port %04x already in use\n", io); |
870 |
printk(KERN_WARNING LIRC_DRIVER_NAME |
809 |
dev_warn(&dev->dev, "use 'setserial /dev/ttySX uart none'\n"); |
871 |
": use 'setserial /dev/ttySX uart none'\n"); |
810 |
dev_warn(&dev->dev, |
872 |
printk(KERN_WARNING LIRC_DRIVER_NAME |
811 |
"or compile the serial port driver as module and\n"); |
873 |
": or compile the serial port driver as module and\n"); |
812 |
dev_warn(&dev->dev, "make sure this module is loaded first\n"); |
874 |
printk(KERN_WARNING LIRC_DRIVER_NAME |
|
|
875 |
": make sure this module is loaded first\n"); |
876 |
return -EBUSY; |
813 |
return -EBUSY; |
877 |
} |
814 |
} |
878 |
|
815 |
|
879 |
if (hardware_init_port() < 0) |
816 |
result = hardware_init_port(); |
880 |
return -EINVAL; |
817 |
if (result < 0) |
|
|
818 |
return result; |
881 |
|
819 |
|
882 |
/* Initialize pulse/space widths */ |
820 |
/* Initialize pulse/space widths */ |
883 |
init_timing_params(duty_cycle, freq); |
821 |
init_timing_params(duty_cycle, freq); |
Lines 900-940
Link Here
|
900 |
nhigh++; |
838 |
nhigh++; |
901 |
msleep(40); |
839 |
msleep(40); |
902 |
} |
840 |
} |
903 |
sense = (nlow >= nhigh ? 1 : 0); |
841 |
sense = nlow >= nhigh ? 1 : 0; |
904 |
printk(KERN_INFO LIRC_DRIVER_NAME ": auto-detected active " |
842 |
dev_info(&dev->dev, "auto-detected active %s receiver\n", |
905 |
"%s receiver\n", sense ? "low" : "high"); |
843 |
sense ? "low" : "high"); |
906 |
} else |
844 |
} else |
907 |
printk(KERN_INFO LIRC_DRIVER_NAME ": Manually using active " |
845 |
dev_info(&dev->dev, "Manually using active %s receiver\n", |
908 |
"%s receiver\n", sense ? "low" : "high"); |
846 |
sense ? "low" : "high"); |
909 |
|
847 |
|
|
|
848 |
dprintk("Interrupt %d, port %04x obtained\n", irq, io); |
910 |
return 0; |
849 |
return 0; |
911 |
} |
850 |
} |
912 |
|
851 |
|
913 |
static int set_use_inc(void *data) |
852 |
static int set_use_inc(void *data) |
914 |
{ |
853 |
{ |
915 |
int result; |
|
|
916 |
unsigned long flags; |
854 |
unsigned long flags; |
917 |
|
855 |
|
918 |
/* initialize timestamp */ |
856 |
/* initialize timestamp */ |
919 |
do_gettimeofday(&lasttv); |
857 |
do_gettimeofday(&lasttv); |
920 |
|
858 |
|
921 |
result = request_irq(irq, irq_handler, |
|
|
922 |
IRQF_DISABLED | (share_irq ? IRQF_SHARED : 0), |
923 |
LIRC_DRIVER_NAME, (void *)&hardware); |
924 |
|
925 |
switch (result) { |
926 |
case -EBUSY: |
927 |
printk(KERN_ERR LIRC_DRIVER_NAME ": IRQ %d busy\n", irq); |
928 |
return -EBUSY; |
929 |
case -EINVAL: |
930 |
printk(KERN_ERR LIRC_DRIVER_NAME |
931 |
": Bad irq number or handler\n"); |
932 |
return -EINVAL; |
933 |
default: |
934 |
dprintk("Interrupt %d, port %04x obtained\n", irq, io); |
935 |
break; |
936 |
}; |
937 |
|
938 |
spin_lock_irqsave(&hardware[type].lock, flags); |
859 |
spin_lock_irqsave(&hardware[type].lock, flags); |
939 |
|
860 |
|
940 |
/* Set DLAB 0. */ |
861 |
/* Set DLAB 0. */ |
Lines 959-971
Link Here
|
959 |
soutp(UART_IER, sinp(UART_IER) & |
880 |
soutp(UART_IER, sinp(UART_IER) & |
960 |
(~(UART_IER_MSI|UART_IER_RLSI|UART_IER_THRI|UART_IER_RDI))); |
881 |
(~(UART_IER_MSI|UART_IER_RLSI|UART_IER_THRI|UART_IER_RDI))); |
961 |
spin_unlock_irqrestore(&hardware[type].lock, flags); |
882 |
spin_unlock_irqrestore(&hardware[type].lock, flags); |
962 |
|
|
|
963 |
free_irq(irq, (void *)&hardware); |
964 |
|
965 |
dprintk("freed IRQ %d\n", irq); |
966 |
} |
883 |
} |
967 |
|
884 |
|
968 |
static ssize_t lirc_write(struct file *file, const char *buf, |
885 |
static ssize_t lirc_write(struct file *file, const char __user *buf, |
969 |
size_t n, loff_t *ppos) |
886 |
size_t n, loff_t *ppos) |
970 |
{ |
887 |
{ |
971 |
int i, count; |
888 |
int i, count; |
Lines 974-980
Link Here
|
974 |
int *wbuf; |
891 |
int *wbuf; |
975 |
|
892 |
|
976 |
if (!(hardware[type].features & LIRC_CAN_SEND_PULSE)) |
893 |
if (!(hardware[type].features & LIRC_CAN_SEND_PULSE)) |
977 |
return -EBADF; |
894 |
return -EPERM; |
978 |
|
895 |
|
979 |
count = n / sizeof(int); |
896 |
count = n / sizeof(int); |
980 |
if (n % sizeof(int) || count % 2 == 0) |
897 |
if (n % sizeof(int) || count % 2 == 0) |
Lines 999-1013
Link Here
|
999 |
return n; |
916 |
return n; |
1000 |
} |
917 |
} |
1001 |
|
918 |
|
1002 |
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35) |
|
|
1003 |
static int lirc_ioctl(struct inode *node, struct file *filep, unsigned int cmd, |
1004 |
unsigned long arg) |
1005 |
#else |
1006 |
static long lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) |
919 |
static long lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) |
1007 |
#endif |
|
|
1008 |
{ |
920 |
{ |
1009 |
int result; |
921 |
int result; |
1010 |
__u32 value; |
922 |
u32 __user *uptr = (u32 __user *)arg; |
|
|
923 |
u32 value; |
1011 |
|
924 |
|
1012 |
switch (cmd) { |
925 |
switch (cmd) { |
1013 |
case LIRC_GET_SEND_MODE: |
926 |
case LIRC_GET_SEND_MODE: |
Lines 1016-1022
Link Here
|
1016 |
|
929 |
|
1017 |
result = put_user(LIRC_SEND2MODE |
930 |
result = put_user(LIRC_SEND2MODE |
1018 |
(hardware[type].features&LIRC_CAN_SEND_MASK), |
931 |
(hardware[type].features&LIRC_CAN_SEND_MASK), |
1019 |
(__u32 *) arg); |
932 |
uptr); |
1020 |
if (result) |
933 |
if (result) |
1021 |
return result; |
934 |
return result; |
1022 |
break; |
935 |
break; |
Lines 1025-1074
Link Here
|
1025 |
if (!(hardware[type].features&LIRC_CAN_SEND_MASK)) |
938 |
if (!(hardware[type].features&LIRC_CAN_SEND_MASK)) |
1026 |
return -ENOIOCTLCMD; |
939 |
return -ENOIOCTLCMD; |
1027 |
|
940 |
|
1028 |
result = get_user(value, (__u32 *) arg); |
941 |
result = get_user(value, uptr); |
1029 |
if (result) |
942 |
if (result) |
1030 |
return result; |
943 |
return result; |
1031 |
/* only LIRC_MODE_PULSE supported */ |
944 |
/* only LIRC_MODE_PULSE supported */ |
1032 |
if (value != LIRC_MODE_PULSE) |
945 |
if (value != LIRC_MODE_PULSE) |
1033 |
return -ENOSYS; |
946 |
return -EINVAL; |
1034 |
break; |
947 |
break; |
1035 |
|
948 |
|
1036 |
case LIRC_GET_LENGTH: |
949 |
case LIRC_GET_LENGTH: |
1037 |
return -ENOSYS; |
950 |
return -ENOIOCTLCMD; |
1038 |
break; |
|
|
1039 |
|
951 |
|
1040 |
case LIRC_SET_SEND_DUTY_CYCLE: |
952 |
case LIRC_SET_SEND_DUTY_CYCLE: |
1041 |
dprintk("SET_SEND_DUTY_CYCLE\n"); |
953 |
dprintk("SET_SEND_DUTY_CYCLE\n"); |
1042 |
if (!(hardware[type].features&LIRC_CAN_SET_SEND_DUTY_CYCLE)) |
954 |
if (!(hardware[type].features&LIRC_CAN_SET_SEND_DUTY_CYCLE)) |
1043 |
return -ENOIOCTLCMD; |
955 |
return -ENOIOCTLCMD; |
1044 |
|
956 |
|
1045 |
result = get_user(value, (__u32 *) arg); |
957 |
result = get_user(value, uptr); |
1046 |
if (result) |
958 |
if (result) |
1047 |
return result; |
959 |
return result; |
1048 |
if (value <= 0 || value > 100) |
960 |
if (value <= 0 || value > 100) |
1049 |
return -EINVAL; |
961 |
return -EINVAL; |
1050 |
return init_timing_params(value, freq); |
962 |
return init_timing_params(value, freq); |
1051 |
break; |
|
|
1052 |
|
963 |
|
1053 |
case LIRC_SET_SEND_CARRIER: |
964 |
case LIRC_SET_SEND_CARRIER: |
1054 |
dprintk("SET_SEND_CARRIER\n"); |
965 |
dprintk("SET_SEND_CARRIER\n"); |
1055 |
if (!(hardware[type].features&LIRC_CAN_SET_SEND_CARRIER)) |
966 |
if (!(hardware[type].features&LIRC_CAN_SET_SEND_CARRIER)) |
1056 |
return -ENOIOCTLCMD; |
967 |
return -ENOIOCTLCMD; |
1057 |
|
968 |
|
1058 |
result = get_user(value, (__u32 *) arg); |
969 |
result = get_user(value, uptr); |
1059 |
if (result) |
970 |
if (result) |
1060 |
return result; |
971 |
return result; |
1061 |
if (value > 500000 || value < 20000) |
972 |
if (value > 500000 || value < 20000) |
1062 |
return -EINVAL; |
973 |
return -EINVAL; |
1063 |
return init_timing_params(duty_cycle, value); |
974 |
return init_timing_params(duty_cycle, value); |
1064 |
break; |
|
|
1065 |
|
975 |
|
1066 |
default: |
976 |
default: |
1067 |
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35) |
|
|
1068 |
return lirc_dev_fop_ioctl(node, filep, cmd, arg); |
1069 |
#else |
1070 |
return lirc_dev_fop_ioctl(filep, cmd, arg); |
977 |
return lirc_dev_fop_ioctl(filep, cmd, arg); |
1071 |
#endif |
|
|
1072 |
} |
978 |
} |
1073 |
return 0; |
979 |
return 0; |
1074 |
} |
980 |
} |
Lines 1076-1093
Link Here
|
1076 |
static const struct file_operations lirc_fops = { |
982 |
static const struct file_operations lirc_fops = { |
1077 |
.owner = THIS_MODULE, |
983 |
.owner = THIS_MODULE, |
1078 |
.write = lirc_write, |
984 |
.write = lirc_write, |
1079 |
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35) |
|
|
1080 |
.ioctl = lirc_ioctl, |
1081 |
#else |
1082 |
.unlocked_ioctl = lirc_ioctl, |
985 |
.unlocked_ioctl = lirc_ioctl, |
1083 |
#ifdef CONFIG_COMPAT |
986 |
#ifdef CONFIG_COMPAT |
1084 |
.compat_ioctl = lirc_ioctl, |
987 |
.compat_ioctl = lirc_ioctl, |
1085 |
#endif |
988 |
#endif |
1086 |
#endif |
|
|
1087 |
.read = lirc_dev_fop_read, |
989 |
.read = lirc_dev_fop_read, |
1088 |
.poll = lirc_dev_fop_poll, |
990 |
.poll = lirc_dev_fop_poll, |
1089 |
.open = lirc_dev_fop_open, |
991 |
.open = lirc_dev_fop_open, |
1090 |
.release = lirc_dev_fop_close, |
992 |
.release = lirc_dev_fop_close, |
|
|
993 |
.llseek = no_llseek, |
1091 |
}; |
994 |
}; |
1092 |
|
995 |
|
1093 |
static struct lirc_driver driver = { |
996 |
static struct lirc_driver driver = { |
Lines 1107-1122
Link Here
|
1107 |
|
1010 |
|
1108 |
static struct platform_device *lirc_serial_dev; |
1011 |
static struct platform_device *lirc_serial_dev; |
1109 |
|
1012 |
|
1110 |
static int lirc_serial_probe(struct platform_device *dev) |
|
|
1111 |
{ |
1112 |
return 0; |
1113 |
} |
1114 |
|
1115 |
static int lirc_serial_remove(struct platform_device *dev) |
1116 |
{ |
1117 |
return 0; |
1118 |
} |
1119 |
|
1120 |
static int lirc_serial_suspend(struct platform_device *dev, |
1013 |
static int lirc_serial_suspend(struct platform_device *dev, |
1121 |
pm_message_t state) |
1014 |
pm_message_t state) |
1122 |
{ |
1015 |
{ |
Lines 1142-1152
Link Here
|
1142 |
static int lirc_serial_resume(struct platform_device *dev) |
1035 |
static int lirc_serial_resume(struct platform_device *dev) |
1143 |
{ |
1036 |
{ |
1144 |
unsigned long flags; |
1037 |
unsigned long flags; |
|
|
1038 |
int result; |
1145 |
|
1039 |
|
1146 |
if (hardware_init_port() < 0) { |
1040 |
result = hardware_init_port(); |
1147 |
lirc_serial_exit(); |
1041 |
if (result < 0) |
1148 |
return -EINVAL; |
1042 |
return result; |
1149 |
} |
|
|
1150 |
|
1043 |
|
1151 |
spin_lock_irqsave(&hardware[type].lock, flags); |
1044 |
spin_lock_irqsave(&hardware[type].lock, flags); |
1152 |
/* Enable Interrupt */ |
1045 |
/* Enable Interrupt */ |
Lines 1163-1174
Link Here
|
1163 |
|
1056 |
|
1164 |
static struct platform_driver lirc_serial_driver = { |
1057 |
static struct platform_driver lirc_serial_driver = { |
1165 |
.probe = lirc_serial_probe, |
1058 |
.probe = lirc_serial_probe, |
1166 |
.remove = lirc_serial_remove, |
|
|
1167 |
.suspend = lirc_serial_suspend, |
1059 |
.suspend = lirc_serial_suspend, |
1168 |
.resume = lirc_serial_resume, |
1060 |
.resume = lirc_serial_resume, |
1169 |
.driver = { |
1061 |
.driver = { |
1170 |
.name = "lirc_serial", |
1062 |
.name = "lirc_serial", |
1171 |
.owner = THIS_MODULE, |
|
|
1172 |
}, |
1063 |
}, |
1173 |
}; |
1064 |
}; |
1174 |
|
1065 |
|
Lines 1179-1185
Link Here
|
1179 |
/* Init read buffer. */ |
1070 |
/* Init read buffer. */ |
1180 |
result = lirc_buffer_init(&rbuf, sizeof(int), RBUF_LEN); |
1071 |
result = lirc_buffer_init(&rbuf, sizeof(int), RBUF_LEN); |
1181 |
if (result < 0) |
1072 |
if (result < 0) |
1182 |
return -ENOMEM; |
1073 |
return result; |
1183 |
|
1074 |
|
1184 |
result = platform_driver_register(&lirc_serial_driver); |
1075 |
result = platform_driver_register(&lirc_serial_driver); |
1185 |
if (result) { |
1076 |
if (result) { |
Lines 1219-1228
Link Here
|
1219 |
{ |
1110 |
{ |
1220 |
int result; |
1111 |
int result; |
1221 |
|
1112 |
|
1222 |
result = lirc_serial_init(); |
|
|
1223 |
if (result) |
1224 |
return result; |
1225 |
|
1226 |
switch (type) { |
1113 |
switch (type) { |
1227 |
case LIRC_HOMEBREW: |
1114 |
case LIRC_HOMEBREW: |
1228 |
case LIRC_IRDEO: |
1115 |
case LIRC_IRDEO: |
Lines 1233-1257
Link Here
|
1233 |
io = io ? io : 0x3f8; |
1120 |
io = io ? io : 0x3f8; |
1234 |
irq = irq ? irq : 4; |
1121 |
irq = irq ? irq : 4; |
1235 |
break; |
1122 |
break; |
1236 |
#ifdef CONFIG_LIRC_SERIAL_NSLU2 |
|
|
1237 |
case LIRC_NSLU2: |
1238 |
io = io ? io : IRQ_IXP4XX_UART2; |
1239 |
irq = irq ? irq : (IXP4XX_UART2_BASE_VIRT + REG_OFFSET); |
1240 |
iommap = iommap ? iommap : IXP4XX_UART2_BASE_PHYS; |
1241 |
ioshift = ioshift ? ioshift : 2; |
1242 |
break; |
1243 |
#endif |
1244 |
default: |
1123 |
default: |
1245 |
result = -EINVAL; |
1124 |
return -EINVAL; |
1246 |
goto exit_serial_exit; |
|
|
1247 |
} |
1125 |
} |
1248 |
if (!softcarrier) { |
1126 |
if (!softcarrier) { |
1249 |
switch (type) { |
1127 |
switch (type) { |
1250 |
case LIRC_HOMEBREW: |
1128 |
case LIRC_HOMEBREW: |
1251 |
case LIRC_IGOR: |
1129 |
case LIRC_IGOR: |
1252 |
#ifdef CONFIG_LIRC_SERIAL_NSLU2 |
|
|
1253 |
case LIRC_NSLU2: |
1254 |
#endif |
1255 |
hardware[type].features &= |
1130 |
hardware[type].features &= |
1256 |
~(LIRC_CAN_SET_SEND_DUTY_CYCLE| |
1131 |
~(LIRC_CAN_SET_SEND_DUTY_CYCLE| |
1257 |
LIRC_CAN_SET_SEND_CARRIER); |
1132 |
LIRC_CAN_SET_SEND_CARRIER); |
Lines 1259-1292
Link Here
|
1259 |
} |
1134 |
} |
1260 |
} |
1135 |
} |
1261 |
|
1136 |
|
1262 |
result = init_port(); |
1137 |
/* make sure sense is either -1, 0, or 1 */ |
1263 |
if (result < 0) |
1138 |
if (sense != -1) |
1264 |
goto exit_serial_exit; |
1139 |
sense = !!sense; |
|
|
1140 |
|
1141 |
result = lirc_serial_init(); |
1142 |
if (result) |
1143 |
return result; |
1144 |
|
1265 |
driver.features = hardware[type].features; |
1145 |
driver.features = hardware[type].features; |
1266 |
driver.dev = &lirc_serial_dev->dev; |
1146 |
driver.dev = &lirc_serial_dev->dev; |
1267 |
driver.minor = lirc_register_driver(&driver); |
1147 |
driver.minor = lirc_register_driver(&driver); |
1268 |
if (driver.minor < 0) { |
1148 |
if (driver.minor < 0) { |
1269 |
printk(KERN_ERR LIRC_DRIVER_NAME |
1149 |
pr_err("register_chrdev failed!\n"); |
1270 |
": register_chrdev failed!\n"); |
1150 |
lirc_serial_exit(); |
1271 |
result = -EIO; |
1151 |
return driver.minor; |
1272 |
goto exit_release; |
|
|
1273 |
} |
1152 |
} |
1274 |
return 0; |
1153 |
return 0; |
1275 |
exit_release: |
|
|
1276 |
release_region(io, 8); |
1277 |
exit_serial_exit: |
1278 |
lirc_serial_exit(); |
1279 |
return result; |
1280 |
} |
1154 |
} |
1281 |
|
1155 |
|
1282 |
static void __exit lirc_serial_exit_module(void) |
1156 |
static void __exit lirc_serial_exit_module(void) |
1283 |
{ |
1157 |
{ |
1284 |
lirc_serial_exit(); |
|
|
1285 |
if (iommap != 0) |
1286 |
release_mem_region(iommap, 8 << ioshift); |
1287 |
else |
1288 |
release_region(io, 8); |
1289 |
lirc_unregister_driver(driver.minor); |
1158 |
lirc_unregister_driver(driver.minor); |
|
|
1159 |
lirc_serial_exit(); |
1290 |
dprintk("cleaned up module\n"); |
1160 |
dprintk("cleaned up module\n"); |
1291 |
} |
1161 |
} |
1292 |
|
1162 |
|
Lines 1315-1321
Link Here
|
1315 |
/* |
1185 |
/* |
1316 |
* some architectures (e.g. intel xscale) align the 8bit serial registers |
1186 |
* some architectures (e.g. intel xscale) align the 8bit serial registers |
1317 |
* on 32bit word boundaries. |
1187 |
* on 32bit word boundaries. |
1318 |
* See linux-kernel/serial/8250.c serial_in()/out() |
1188 |
* See linux-kernel/drivers/tty/serial/8250/8250.c serial_in()/out() |
1319 |
*/ |
1189 |
*/ |
1320 |
module_param(ioshift, int, S_IRUGO); |
1190 |
module_param(ioshift, int, S_IRUGO); |
1321 |
MODULE_PARM_DESC(ioshift, "shift I/O register offset (0 = no shift)"); |
1191 |
MODULE_PARM_DESC(ioshift, "shift I/O register offset (0 = no shift)"); |
Lines 1326-1332
Link Here
|
1326 |
module_param(share_irq, bool, S_IRUGO); |
1196 |
module_param(share_irq, bool, S_IRUGO); |
1327 |
MODULE_PARM_DESC(share_irq, "Share interrupts (0 = off, 1 = on)"); |
1197 |
MODULE_PARM_DESC(share_irq, "Share interrupts (0 = off, 1 = on)"); |
1328 |
|
1198 |
|
1329 |
module_param(sense, bool, S_IRUGO); |
1199 |
module_param(sense, int, S_IRUGO); |
1330 |
MODULE_PARM_DESC(sense, "Override autodetection of IR receiver circuit" |
1200 |
MODULE_PARM_DESC(sense, "Override autodetection of IR receiver circuit" |
1331 |
" (0 = active high, 1 = active low )"); |
1201 |
" (0 = active high, 1 = active low )"); |
1332 |
|
1202 |
|