mirror of https://github.com/hak5/openwrt-owl.git
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");
|