1 /*
2  * IR port driver for the Cirrus Logic EP7211 processor.
3  *
4  * Copyright 2001, Blue Mug Inc.  All rights reserved.
5  */
6 
7 #include <linux/module.h>
8 #include <linux/delay.h>
9 #include <linux/tty.h>
10 #include <linux/sched.h>
11 #include <linux/init.h>
12 
13 #include <net/irda/irda.h>
14 #include <net/irda/irmod.h>
15 #include <net/irda/irda_device.h>
16 
17 #include <asm/io.h>
18 #include <asm/hardware.h>
19 
20 #define MIN_DELAY 25      /* 15 us, but wait a little more to be sure */
21 #define MAX_DELAY 10000   /* 1 ms */
22 
23 static void ep7211_ir_open(dongle_t *self, struct qos_info *qos);
24 static void ep7211_ir_close(dongle_t *self);
25 static int  ep7211_ir_change_speed(struct irda_task *task);
26 static int  ep7211_ir_reset(struct irda_task *task);
27 
28 static struct dongle_reg dongle = {
29 	Q_NULL,
30 	IRDA_EP7211_IR,
31 	ep7211_ir_open,
32 	ep7211_ir_close,
33 	ep7211_ir_reset,
34 	ep7211_ir_change_speed,
35 };
36 
ep7211_ir_open(dongle_t * self,struct qos_info * qos)37 static void ep7211_ir_open(dongle_t *self, struct qos_info *qos)
38 {
39 	unsigned int syscon1, flags;
40 
41 	save_flags(flags); cli();
42 
43 	/* Turn on the SIR encoder. */
44 	syscon1 = clps_readl(SYSCON1);
45 	syscon1 |= SYSCON1_SIREN;
46 	clps_writel(syscon1, SYSCON1);
47 
48 	/* XXX: We should disable modem status interrupts on the first
49 		UART (interrupt #14). */
50 
51 	restore_flags(flags);
52 
53 	MOD_INC_USE_COUNT;
54 }
55 
ep7211_ir_close(dongle_t * self)56 static void ep7211_ir_close(dongle_t *self)
57 {
58 	unsigned int syscon1, flags;
59 
60 	save_flags(flags); cli();
61 
62 	/* Turn off the SIR encoder. */
63 	syscon1 = clps_readl(SYSCON1);
64 	syscon1 &= ~SYSCON1_SIREN;
65 	clps_writel(syscon1, SYSCON1);
66 
67 	/* XXX: If we've disabled the modem status interrupts, we should
68 		reset them back to their original state. */
69 
70 	restore_flags(flags);
71 
72 	MOD_DEC_USE_COUNT;
73 }
74 
75 /*
76  * Function ep7211_ir_change_speed (task)
77  *
78  *    Change speed of the EP7211 I/R port. We don't really have to do anything
79  *    for the EP7211 as long as the rate is being changed at the serial port
80  *    level.
81  */
ep7211_ir_change_speed(struct irda_task * task)82 static int ep7211_ir_change_speed(struct irda_task *task)
83 {
84 	irda_task_next_state(task, IRDA_TASK_DONE);
85 	return 0;
86 }
87 
88 /*
89  * Function ep7211_ir_reset (task)
90  *
91  *      Reset the EP7211 I/R. We don't really have to do anything.
92  *
93  */
ep7211_ir_reset(struct irda_task * task)94 static int ep7211_ir_reset(struct irda_task *task)
95 {
96 	irda_task_next_state(task, IRDA_TASK_DONE);
97 	return 0;
98 }
99 
100 /*
101  * Function ep7211_ir_init(void)
102  *
103  *    Initialize EP7211 I/R module
104  *
105  */
ep7211_ir_init(void)106 int __init ep7211_ir_init(void)
107 {
108 	return irda_device_register_dongle(&dongle);
109 }
110 
111 /*
112  * Function ep7211_ir_cleanup(void)
113  *
114  *    Cleanup EP7211 I/R module
115  *
116  */
ep7211_ir_cleanup(void)117 static void __exit ep7211_ir_cleanup(void)
118 {
119 	irda_device_unregister_dongle(&dongle);
120 }
121 
122 MODULE_AUTHOR("Jon McClintock <jonm@bluemug.com>");
123 MODULE_DESCRIPTION("EP7211 I/R driver");
124 MODULE_LICENSE("GPL");
125 
126 #ifdef MODULE
127 module_init(ep7211_ir_init);
128 #endif /* MODULE */
129 module_exit(ep7211_ir_cleanup);
130