238 lines
		
	
	
		
			6.5 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			238 lines
		
	
	
		
			6.5 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
From 5f645d0668b469c4738fe1e9d3994287a519d0f3 Mon Sep 17 00:00:00 2001
 | 
						|
From: Kurt Mahan <kmahan@freescale.com>
 | 
						|
Date: Tue, 8 Jul 2008 15:57:47 -0600
 | 
						|
Subject: [PATCH] Add Coldfire IRDA support in serial driver.
 | 
						|
 | 
						|
LTIBName: mcfv4e-irda
 | 
						|
Signed-off-by: Kurt Mahan <kmahan@freescale.com>
 | 
						|
Signed-off-by: Huan, Wang <b18965@freescale.com>
 | 
						|
---
 | 
						|
 drivers/serial/Kconfig     |    6 ++
 | 
						|
 drivers/serial/mcfserial.c |  110 ++++++++++++++++++++++++++++++++++++++++++--
 | 
						|
 net/irda/irlap.c           |    2 +-
 | 
						|
 3 files changed, 113 insertions(+), 5 deletions(-)
 | 
						|
 | 
						|
--- a/drivers/serial/Kconfig
 | 
						|
+++ b/drivers/serial/Kconfig
 | 
						|
@@ -979,6 +979,12 @@ config SERIAL_COLDFIRE
 | 
						|
 	  This driver supports the built-in serial ports of the Motorola ColdFire
 | 
						|
 	  family of CPUs.
 | 
						|
 
 | 
						|
+config SERIAL_COLDFIRE_IRDA
 | 
						|
+	bool "ColdFire IRDA support"
 | 
						|
+	depends on SERIAL_COLDFIRE
 | 
						|
+	help
 | 
						|
+	  This driver supports IRDA on the Motorola ColdFire.
 | 
						|
+
 | 
						|
 config SERIAL_MCF
 | 
						|
 	bool "Coldfire serial support (new style driver)"
 | 
						|
 	depends on COLDFIRE
 | 
						|
--- a/drivers/serial/mcfserial.c
 | 
						|
+++ b/drivers/serial/mcfserial.c
 | 
						|
@@ -109,6 +109,10 @@ static struct tty_driver *mcfrs_serial_d
 | 
						|
 #define	IRQBASE	73
 | 
						|
 #endif
 | 
						|
 
 | 
						|
+#ifdef CONFIG_SERIAL_COLDFIRE_IRDA
 | 
						|
+#define SERIAL_IRDA_LINE (2)
 | 
						|
+#endif
 | 
						|
+
 | 
						|
 /*
 | 
						|
  *	Configuration table, UARTs to look for at startup.
 | 
						|
  */
 | 
						|
@@ -393,6 +397,9 @@ static inline void receive_chars(struct 
 | 
						|
 static inline void transmit_chars(struct mcf_serial *info)
 | 
						|
 {
 | 
						|
 	volatile unsigned char	*uartp;
 | 
						|
+#ifdef CONFIG_SERIAL_COLDFIRE_IRDA
 | 
						|
+	int i;
 | 
						|
+#endif
 | 
						|
 
 | 
						|
 	uartp = info->addr;
 | 
						|
 
 | 
						|
@@ -404,13 +411,36 @@ static inline void transmit_chars(struct
 | 
						|
 	}
 | 
						|
 
 | 
						|
 	if ((info->xmit_cnt <= 0) || info->tty->stopped) {
 | 
						|
+#ifdef CONFIG_SERIAL_COLDFIRE_IRDA
 | 
						|
+		if (info->line == SERIAL_IRDA_LINE) {
 | 
						|
+			/* Enable receiver for IRDA */
 | 
						|
+			uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETRX;
 | 
						|
+			/* reset RX */
 | 
						|
+			uartp[MCFUART_UCR] = MCFUART_UCR_TXENABLE | MCFUART_UCR_RXENABLE;
 | 
						|
+		}
 | 
						|
+#endif
 | 
						|
 		info->imr &= ~MCFUART_UIR_TXREADY;
 | 
						|
 		uartp[MCFUART_UIMR] = info->imr;
 | 
						|
 		return;
 | 
						|
 	}
 | 
						|
 
 | 
						|
 	while (uartp[MCFUART_USR] & MCFUART_USR_TXREADY) {
 | 
						|
+#ifdef CONFIG_SERIAL_COLDFIRE_IRDA
 | 
						|
+		if (info->line == SERIAL_IRDA_LINE) {
 | 
						|
+			while (!(uartp[MCFUART_USR] & MCFUART_USR_TXEMPTY));
 | 
						|
+			i = 0;
 | 
						|
+			/* delay for settle */
 | 
						|
+#if defined(CONFIG_M548X)
 | 
						|
+			udelay(1);
 | 
						|
+#elif defined(CONFIG_M547X)
 | 
						|
+			udelay(2);
 | 
						|
+#else
 | 
						|
+			while (i++ < 25000) udelay(1);
 | 
						|
+#endif
 | 
						|
+		}
 | 
						|
+#endif
 | 
						|
 		uartp[MCFUART_UTB] = info->xmit_buf[info->xmit_tail++];
 | 
						|
+
 | 
						|
 		info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1);
 | 
						|
 		info->stats.tx++;
 | 
						|
 		if (--info->xmit_cnt <= 0)
 | 
						|
@@ -567,6 +597,28 @@ static int startup(struct mcf_serial * i
 | 
						|
 	 */
 | 
						|
 	mcfrs_change_speed(info);
 | 
						|
 
 | 
						|
+#ifdef CONFIG_SERIAL_COLDFIRE_IRDA
 | 
						|
+	if (info->line == SERIAL_IRDA_LINE) {
 | 
						|
+		/* Put PSC in IrDA mode */
 | 
						|
+		MCF_PSC_SICR(info->line) = MCF_PSC_SICR_SIM_SIR;
 | 
						|
+
 | 
						|
+		/* Set pulse width to 1.6 uS */
 | 
						|
+		MCF_PSC_IRSDR(info->line) = (uint8_t)
 | 
						|
+					    (16 * (CONFIG_MCFCLK / 10000000));
 | 
						|
+		MCF_PSC_IRCR1(info->line) = MCF_PSC_IRCR1_SPUL;
 | 
						|
+		MCF_PSC_IRCR2(info->line) = 0;
 | 
						|
+
 | 
						|
+		/* Enable RTS to send */
 | 
						|
+		MCF_PSC_OPSET(info->line) = MCF_PSC_OPSET_RTS;
 | 
						|
+
 | 
						|
+		/* Setup FIFO Alarms */
 | 
						|
+		MCF_PSC_RFAR(info->line) = MCF_PSC_RFAR_ALARM(248);
 | 
						|
+		MCF_PSC_TFAR(info->line) = MCF_PSC_TFAR_ALARM(248);
 | 
						|
+
 | 
						|
+		MCF_PSC_RFCR(info->line) = MCF_PSC_RFCR_FRMEN | MCF_PSC_RFCR_GR(4);
 | 
						|
+		MCF_PSC_TFCR(info->line) = MCF_PSC_TFCR_FRMEN | MCF_PSC_RFCR_GR(4);
 | 
						|
+	}
 | 
						|
+#endif
 | 
						|
 	/*
 | 
						|
 	 * Lastly enable the UART transmitter and receiver, and
 | 
						|
 	 * interrupt enables.
 | 
						|
@@ -588,10 +640,20 @@ static void shutdown(struct mcf_serial *
 | 
						|
 {
 | 
						|
 	volatile unsigned char	*uartp;
 | 
						|
 	unsigned long		flags;
 | 
						|
+#ifdef CONFIG_SERIAL_COLDFIRE_IRDA
 | 
						|
+	unsigned long 		delay_counter = 0;
 | 
						|
+#endif
 | 
						|
 
 | 
						|
 	if (!(info->flags & ASYNC_INITIALIZED))
 | 
						|
 		return;
 | 
						|
-
 | 
						|
+#ifdef CONFIG_SERIAL_COLDFIRE_IRDA
 | 
						|
+	uartp = (volatile unsigned char *) info->addr;
 | 
						|
+	while (!(uartp[MCFUART_USR] & MCFUART_USR_TXEMPTY)) {
 | 
						|
+		if(delay_counter++ > 25000)
 | 
						|
+			break;
 | 
						|
+		udelay(10);
 | 
						|
+	}
 | 
						|
+#endif
 | 
						|
 #ifdef SERIAL_DEBUG_OPEN
 | 
						|
 	printk("Shutting down serial port %d (irq %d)....\n", info->line,
 | 
						|
 	       info->irq);
 | 
						|
@@ -820,10 +882,19 @@ static int mcfrs_write(struct tty_struct
 | 
						|
 
 | 
						|
 	local_irq_disable();
 | 
						|
 	uartp = info->addr;
 | 
						|
+
 | 
						|
+#ifdef CONFIG_SERIAL_COLDFIRE_IRDA
 | 
						|
+	if (info->line == SERIAL_IRDA_LINE) {
 | 
						|
+		/* Disable IRDA receiver*/
 | 
						|
+		uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETRX;    /* reset RX */
 | 
						|
+		uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETTX;    /* reset TX */
 | 
						|
+
 | 
						|
+		uartp[MCFUART_UCR] = MCFUART_UCR_TXENABLE;
 | 
						|
+	}
 | 
						|
+#endif
 | 
						|
 	info->imr |= MCFUART_UIR_TXREADY;
 | 
						|
 	uartp[MCFUART_UIMR] = info->imr;
 | 
						|
 	local_irq_restore(flags);
 | 
						|
-
 | 
						|
 	return total;
 | 
						|
 }
 | 
						|
 
 | 
						|
@@ -884,9 +955,21 @@ static void mcfrs_throttle(struct tty_st
 | 
						|
 
 | 
						|
 	if (serial_paranoia_check(info, tty->name, "mcfrs_throttle"))
 | 
						|
 		return;
 | 
						|
-	
 | 
						|
+#ifdef CONFIG_SERIAL_COLDFIRE_IRDA
 | 
						|
+	if (I_IXOFF(tty)) {
 | 
						|
+		/* Force STOP_CHAR (xoff) out */
 | 
						|
+		volatile unsigned char	*uartp;
 | 
						|
+		unsigned long		flags;
 | 
						|
+		uartp = (volatile unsigned char *) info->addr;
 | 
						|
+		local_irq_save(flags);
 | 
						|
+		info->imr |= MCFUART_UIR_TXREADY;
 | 
						|
+		uartp[MCFUART_UIMR] = info->imr;
 | 
						|
+		local_irq_restore(flags);
 | 
						|
+	}
 | 
						|
+#else
 | 
						|
 	if (I_IXOFF(tty))
 | 
						|
 		info->x_char = STOP_CHAR(tty);
 | 
						|
+#endif
 | 
						|
 
 | 
						|
 	/* Turn off RTS line (do this atomic) */
 | 
						|
 }
 | 
						|
@@ -907,8 +990,22 @@ static void mcfrs_unthrottle(struct tty_
 | 
						|
 	if (I_IXOFF(tty)) {
 | 
						|
 		if (info->x_char)
 | 
						|
 			info->x_char = 0;
 | 
						|
+#ifdef CONFIG_SERIAL_COLDFIRE_IRDA
 | 
						|
+		else {
 | 
						|
+			/* Force START_CHAR (xon) out */
 | 
						|
+			volatile unsigned char	*uartp;
 | 
						|
+			unsigned long		flags;
 | 
						|
+			info->x_char = START_CHAR(tty);
 | 
						|
+			uartp = (volatile unsigned char *) info->addr;
 | 
						|
+			local_irq_save(flags);
 | 
						|
+			info->imr |= MCFUART_UIR_TXREADY;
 | 
						|
+			uartp[MCFUART_UIMR] = info->imr;
 | 
						|
+			local_irq_restore(flags);
 | 
						|
+		}
 | 
						|
+#else
 | 
						|
 		else
 | 
						|
 			info->x_char = START_CHAR(tty);
 | 
						|
+#endif
 | 
						|
 	}
 | 
						|
 
 | 
						|
 	/* Assert RTS line (do this atomic) */
 | 
						|
@@ -1156,12 +1253,17 @@ static int mcfrs_ioctl(struct tty_struct
 | 
						|
 static void mcfrs_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
 | 
						|
 {
 | 
						|
 	struct mcf_serial *info = (struct mcf_serial *)tty->driver_data;
 | 
						|
+#ifdef CONFIG_SERIAL_COLDFIRE_IRDA
 | 
						|
+	int i = 0;	/* hush GCC */
 | 
						|
+#endif
 | 
						|
 
 | 
						|
 	if (tty->termios->c_cflag == old_termios->c_cflag)
 | 
						|
 		return;
 | 
						|
 
 | 
						|
+#ifdef CONFIG_SERIAL_COLDFIRE_IRDA
 | 
						|
+	while (i++ < 35000) udelay(1);
 | 
						|
+#endif
 | 
						|
 	mcfrs_change_speed(info);
 | 
						|
-
 | 
						|
 	if ((old_termios->c_cflag & CRTSCTS) &&
 | 
						|
 	    !(tty->termios->c_cflag & CRTSCTS)) {
 | 
						|
 		tty->hw_stopped = 0;
 | 
						|
--- a/net/irda/irlap.c
 | 
						|
+++ b/net/irda/irlap.c
 | 
						|
@@ -627,7 +627,7 @@ void irlap_status_indication(struct irla
 | 
						|
 {
 | 
						|
 	switch (quality_of_link) {
 | 
						|
 	case STATUS_NO_ACTIVITY:
 | 
						|
-		IRDA_MESSAGE("IrLAP, no activity on link!\n");
 | 
						|
+		/* IRDA_MESSAGE("IrLAP, no activity on link!\n"); */
 | 
						|
 		break;
 | 
						|
 	case STATUS_NOISY:
 | 
						|
 		IRDA_MESSAGE("IrLAP, noisy link!\n");
 |