ar71xx: fix inline attribute location
[openwrt.git] / target / linux / coldfire / patches / 076-mcfv4e_irda.patch
1 From 5f645d0668b469c4738fe1e9d3994287a519d0f3 Mon Sep 17 00:00:00 2001
2 From: Kurt Mahan <kmahan@freescale.com>
3 Date: Tue, 8 Jul 2008 15:57:47 -0600
4 Subject: [PATCH] Add Coldfire IRDA support in serial driver.
5
6 LTIBName: mcfv4e-irda
7 Signed-off-by: Kurt Mahan <kmahan@freescale.com>
8 Signed-off-by: Huan, Wang <b18965@freescale.com>
9 ---
10  drivers/serial/Kconfig     |    6 ++
11  drivers/serial/mcfserial.c |  110 ++++++++++++++++++++++++++++++++++++++++++--
12  net/irda/irlap.c           |    2 +-
13  3 files changed, 113 insertions(+), 5 deletions(-)
14
15 --- a/drivers/serial/Kconfig
16 +++ b/drivers/serial/Kconfig
17 @@ -979,6 +979,12 @@ config SERIAL_COLDFIRE
18           This driver supports the built-in serial ports of the Motorola ColdFire
19           family of CPUs.
20  
21 +config SERIAL_COLDFIRE_IRDA
22 +       bool "ColdFire IRDA support"
23 +       depends on SERIAL_COLDFIRE
24 +       help
25 +         This driver supports IRDA on the Motorola ColdFire.
26 +
27  config SERIAL_MCF
28         bool "Coldfire serial support (new style driver)"
29         depends on COLDFIRE
30 --- a/drivers/serial/mcfserial.c
31 +++ b/drivers/serial/mcfserial.c
32 @@ -109,6 +109,10 @@ static struct tty_driver *mcfrs_serial_d
33  #define        IRQBASE 73
34  #endif
35  
36 +#ifdef CONFIG_SERIAL_COLDFIRE_IRDA
37 +#define SERIAL_IRDA_LINE (2)
38 +#endif
39 +
40  /*
41   *     Configuration table, UARTs to look for at startup.
42   */
43 @@ -393,6 +397,9 @@ static inline void receive_chars(struct 
44  static inline void transmit_chars(struct mcf_serial *info)
45  {
46         volatile unsigned char  *uartp;
47 +#ifdef CONFIG_SERIAL_COLDFIRE_IRDA
48 +       int i;
49 +#endif
50  
51         uartp = info->addr;
52  
53 @@ -404,13 +411,36 @@ static inline void transmit_chars(struct
54         }
55  
56         if ((info->xmit_cnt <= 0) || info->tty->stopped) {
57 +#ifdef CONFIG_SERIAL_COLDFIRE_IRDA
58 +               if (info->line == SERIAL_IRDA_LINE) {
59 +                       /* Enable receiver for IRDA */
60 +                       uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETRX;
61 +                       /* reset RX */
62 +                       uartp[MCFUART_UCR] = MCFUART_UCR_TXENABLE | MCFUART_UCR_RXENABLE;
63 +               }
64 +#endif
65                 info->imr &= ~MCFUART_UIR_TXREADY;
66                 uartp[MCFUART_UIMR] = info->imr;
67                 return;
68         }
69  
70         while (uartp[MCFUART_USR] & MCFUART_USR_TXREADY) {
71 +#ifdef CONFIG_SERIAL_COLDFIRE_IRDA
72 +               if (info->line == SERIAL_IRDA_LINE) {
73 +                       while (!(uartp[MCFUART_USR] & MCFUART_USR_TXEMPTY));
74 +                       i = 0;
75 +                       /* delay for settle */
76 +#if defined(CONFIG_M548X)
77 +                       udelay(1);
78 +#elif defined(CONFIG_M547X)
79 +                       udelay(2);
80 +#else
81 +                       while (i++ < 25000) udelay(1);
82 +#endif
83 +               }
84 +#endif
85                 uartp[MCFUART_UTB] = info->xmit_buf[info->xmit_tail++];
86 +
87                 info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1);
88                 info->stats.tx++;
89                 if (--info->xmit_cnt <= 0)
90 @@ -567,6 +597,28 @@ static int startup(struct mcf_serial * i
91          */
92         mcfrs_change_speed(info);
93  
94 +#ifdef CONFIG_SERIAL_COLDFIRE_IRDA
95 +       if (info->line == SERIAL_IRDA_LINE) {
96 +               /* Put PSC in IrDA mode */
97 +               MCF_PSC_SICR(info->line) = MCF_PSC_SICR_SIM_SIR;
98 +
99 +               /* Set pulse width to 1.6 uS */
100 +               MCF_PSC_IRSDR(info->line) = (uint8_t)
101 +                                           (16 * (CONFIG_MCFCLK / 10000000));
102 +               MCF_PSC_IRCR1(info->line) = MCF_PSC_IRCR1_SPUL;
103 +               MCF_PSC_IRCR2(info->line) = 0;
104 +
105 +               /* Enable RTS to send */
106 +               MCF_PSC_OPSET(info->line) = MCF_PSC_OPSET_RTS;
107 +
108 +               /* Setup FIFO Alarms */
109 +               MCF_PSC_RFAR(info->line) = MCF_PSC_RFAR_ALARM(248);
110 +               MCF_PSC_TFAR(info->line) = MCF_PSC_TFAR_ALARM(248);
111 +
112 +               MCF_PSC_RFCR(info->line) = MCF_PSC_RFCR_FRMEN | MCF_PSC_RFCR_GR(4);
113 +               MCF_PSC_TFCR(info->line) = MCF_PSC_TFCR_FRMEN | MCF_PSC_RFCR_GR(4);
114 +       }
115 +#endif
116         /*
117          * Lastly enable the UART transmitter and receiver, and
118          * interrupt enables.
119 @@ -588,10 +640,20 @@ static void shutdown(struct mcf_serial *
120  {
121         volatile unsigned char  *uartp;
122         unsigned long           flags;
123 +#ifdef CONFIG_SERIAL_COLDFIRE_IRDA
124 +       unsigned long           delay_counter = 0;
125 +#endif
126  
127         if (!(info->flags & ASYNC_INITIALIZED))
128                 return;
129 -
130 +#ifdef CONFIG_SERIAL_COLDFIRE_IRDA
131 +       uartp = (volatile unsigned char *) info->addr;
132 +       while (!(uartp[MCFUART_USR] & MCFUART_USR_TXEMPTY)) {
133 +               if(delay_counter++ > 25000)
134 +                       break;
135 +               udelay(10);
136 +       }
137 +#endif
138  #ifdef SERIAL_DEBUG_OPEN
139         printk("Shutting down serial port %d (irq %d)....\n", info->line,
140                info->irq);
141 @@ -820,10 +882,19 @@ static int mcfrs_write(struct tty_struct
142  
143         local_irq_disable();
144         uartp = info->addr;
145 +
146 +#ifdef CONFIG_SERIAL_COLDFIRE_IRDA
147 +       if (info->line == SERIAL_IRDA_LINE) {
148 +               /* Disable IRDA receiver*/
149 +               uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETRX;    /* reset RX */
150 +               uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETTX;    /* reset TX */
151 +
152 +               uartp[MCFUART_UCR] = MCFUART_UCR_TXENABLE;
153 +       }
154 +#endif
155         info->imr |= MCFUART_UIR_TXREADY;
156         uartp[MCFUART_UIMR] = info->imr;
157         local_irq_restore(flags);
158 -
159         return total;
160  }
161  
162 @@ -884,9 +955,21 @@ static void mcfrs_throttle(struct tty_st
163  
164         if (serial_paranoia_check(info, tty->name, "mcfrs_throttle"))
165                 return;
166 -       
167 +#ifdef CONFIG_SERIAL_COLDFIRE_IRDA
168 +       if (I_IXOFF(tty)) {
169 +               /* Force STOP_CHAR (xoff) out */
170 +               volatile unsigned char  *uartp;
171 +               unsigned long           flags;
172 +               uartp = (volatile unsigned char *) info->addr;
173 +               local_irq_save(flags);
174 +               info->imr |= MCFUART_UIR_TXREADY;
175 +               uartp[MCFUART_UIMR] = info->imr;
176 +               local_irq_restore(flags);
177 +       }
178 +#else
179         if (I_IXOFF(tty))
180                 info->x_char = STOP_CHAR(tty);
181 +#endif
182  
183         /* Turn off RTS line (do this atomic) */
184  }
185 @@ -907,8 +990,22 @@ static void mcfrs_unthrottle(struct tty_
186         if (I_IXOFF(tty)) {
187                 if (info->x_char)
188                         info->x_char = 0;
189 +#ifdef CONFIG_SERIAL_COLDFIRE_IRDA
190 +               else {
191 +                       /* Force START_CHAR (xon) out */
192 +                       volatile unsigned char  *uartp;
193 +                       unsigned long           flags;
194 +                       info->x_char = START_CHAR(tty);
195 +                       uartp = (volatile unsigned char *) info->addr;
196 +                       local_irq_save(flags);
197 +                       info->imr |= MCFUART_UIR_TXREADY;
198 +                       uartp[MCFUART_UIMR] = info->imr;
199 +                       local_irq_restore(flags);
200 +               }
201 +#else
202                 else
203                         info->x_char = START_CHAR(tty);
204 +#endif
205         }
206  
207         /* Assert RTS line (do this atomic) */
208 @@ -1156,12 +1253,17 @@ static int mcfrs_ioctl(struct tty_struct
209  static void mcfrs_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
210  {
211         struct mcf_serial *info = (struct mcf_serial *)tty->driver_data;
212 +#ifdef CONFIG_SERIAL_COLDFIRE_IRDA
213 +       int i = 0;      /* hush GCC */
214 +#endif
215  
216         if (tty->termios->c_cflag == old_termios->c_cflag)
217                 return;
218  
219 +#ifdef CONFIG_SERIAL_COLDFIRE_IRDA
220 +       while (i++ < 35000) udelay(1);
221 +#endif
222         mcfrs_change_speed(info);
223 -
224         if ((old_termios->c_cflag & CRTSCTS) &&
225             !(tty->termios->c_cflag & CRTSCTS)) {
226                 tty->hw_stopped = 0;
227 --- a/net/irda/irlap.c
228 +++ b/net/irda/irlap.c
229 @@ -627,7 +627,7 @@ void irlap_status_indication(struct irla
230  {
231         switch (quality_of_link) {
232         case STATUS_NO_ACTIVITY:
233 -               IRDA_MESSAGE("IrLAP, no activity on link!\n");
234 +               /* IRDA_MESSAGE("IrLAP, no activity on link!\n"); */
235                 break;
236         case STATUS_NOISY:
237                 IRDA_MESSAGE("IrLAP, noisy link!\n");