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.
7 Signed-off-by: Kurt Mahan <kmahan@freescale.com>
8 Signed-off-by: Huan, Wang <b18965@freescale.com>
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(-)
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
21 +config SERIAL_COLDFIRE_IRDA
22 + bool "ColdFire IRDA support"
23 + depends on SERIAL_COLDFIRE
25 + This driver supports IRDA on the Motorola ColdFire.
28 bool "Coldfire serial support (new style driver)"
30 --- a/drivers/serial/mcfserial.c
31 +++ b/drivers/serial/mcfserial.c
32 @@ -109,6 +109,10 @@ static struct tty_driver *mcfrs_serial_d
36 +#ifdef CONFIG_SERIAL_COLDFIRE_IRDA
37 +#define SERIAL_IRDA_LINE (2)
41 * Configuration table, UARTs to look for at startup.
43 @@ -393,6 +397,9 @@ static inline void receive_chars(struct
44 static inline void transmit_chars(struct mcf_serial *info)
46 volatile unsigned char *uartp;
47 +#ifdef CONFIG_SERIAL_COLDFIRE_IRDA
53 @@ -404,13 +411,36 @@ static inline void transmit_chars(struct
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;
62 + uartp[MCFUART_UCR] = MCFUART_UCR_TXENABLE | MCFUART_UCR_RXENABLE;
65 info->imr &= ~MCFUART_UIR_TXREADY;
66 uartp[MCFUART_UIMR] = info->imr;
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));
75 + /* delay for settle */
76 +#if defined(CONFIG_M548X)
78 +#elif defined(CONFIG_M547X)
81 + while (i++ < 25000) udelay(1);
85 uartp[MCFUART_UTB] = info->xmit_buf[info->xmit_tail++];
87 info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1);
89 if (--info->xmit_cnt <= 0)
90 @@ -567,6 +597,28 @@ static int startup(struct mcf_serial * i
92 mcfrs_change_speed(info);
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;
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;
105 + /* Enable RTS to send */
106 + MCF_PSC_OPSET(info->line) = MCF_PSC_OPSET_RTS;
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);
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);
117 * Lastly enable the UART transmitter and receiver, and
119 @@ -588,10 +640,20 @@ static void shutdown(struct mcf_serial *
121 volatile unsigned char *uartp;
123 +#ifdef CONFIG_SERIAL_COLDFIRE_IRDA
124 + unsigned long delay_counter = 0;
127 if (!(info->flags & ASYNC_INITIALIZED))
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)
138 #ifdef SERIAL_DEBUG_OPEN
139 printk("Shutting down serial port %d (irq %d)....\n", info->line,
141 @@ -820,10 +882,19 @@ static int mcfrs_write(struct tty_struct
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 */
152 + uartp[MCFUART_UCR] = MCFUART_UCR_TXENABLE;
155 info->imr |= MCFUART_UIR_TXREADY;
156 uartp[MCFUART_UIMR] = info->imr;
157 local_irq_restore(flags);
162 @@ -884,9 +955,21 @@ static void mcfrs_throttle(struct tty_st
164 if (serial_paranoia_check(info, tty->name, "mcfrs_throttle"))
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);
180 info->x_char = STOP_CHAR(tty);
183 /* Turn off RTS line (do this atomic) */
185 @@ -907,8 +990,22 @@ static void mcfrs_unthrottle(struct tty_
189 +#ifdef CONFIG_SERIAL_COLDFIRE_IRDA
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);
203 info->x_char = START_CHAR(tty);
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)
211 struct mcf_serial *info = (struct mcf_serial *)tty->driver_data;
212 +#ifdef CONFIG_SERIAL_COLDFIRE_IRDA
213 + int i = 0; /* hush GCC */
216 if (tty->termios->c_cflag == old_termios->c_cflag)
219 +#ifdef CONFIG_SERIAL_COLDFIRE_IRDA
220 + while (i++ < 35000) udelay(1);
222 mcfrs_change_speed(info);
224 if ((old_termios->c_cflag & CRTSCTS) &&
225 !(tty->termios->c_cflag & CRTSCTS)) {
227 --- a/net/irda/irlap.c
228 +++ b/net/irda/irlap.c
229 @@ -627,7 +627,7 @@ void irlap_status_indication(struct irla
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"); */
237 IRDA_MESSAGE("IrLAP, noisy link!\n");