SIMpad kernel 2.4.25 serial patches

Till Harbaum <[email protected]> Fri, 24 Sep 2004 17:27:01 +0200
Newsgroups gmane.comp.handhelds.openembedded,gmane.comp.handhelds.simpad.linux
Organization BeeCon GmbH
Message-ID <[email protected]>
Hi all,

although this patch does not have the effect i hoped (allowing bluetooth > 
230kbit/s and simultaneous blitter operation) i'd like to get it included 
anyway.

This patch adds full serial support for both the internal (dect/bluetooth) and 
external rs232. The patch enables the control signals CTS/RTS/DCD/DSR and 
DTR. It should only have minor influences on current setups. These are e.g. 
the fact, that linux now closes a serial session whenever the rs232 connector 
is pulled (since it now detects, that dcd drops).

Furthermore this patch fixes a severe bug in the mq200fb driver that affected 
all gpio pins (except the one it was meant to).

Can anyone please apply this patch and my last one? Both do not break existing 
interfaces or the like.

Ciao,
  Till

-- 
Dr.-Ing. Till Harbaum                       Tel.:  +49 721 4998963
BeeCon GmbH                                 Fax:   +49 721 4998962
Haid-und-Neu Strasse 7, 76131 Karlsruhe     Mobil: +49 179 9087904
[email protected]                           http://www.beecon.de

_______________________________________________
Oe mailing list
[email protected]
https://handhelds.org/mailman/listinfo/oe
kernel-simpad-serial.patch (text/x-diff, 7.4 KB)
--- include/asm-arm/arch-sa1100/simpad.h.orig	2004-09-23 14:28:07.000000000 +0200
+++ include/asm-arm/arch-sa1100/simpad.h	2004-09-23 19:33:33.000000000 +0200
@@ -16,7 +16,7 @@
 #error "include <asm/hardware.h> instead"
 #endif
 
-#define GPIO_UART1_RTS	GPIO_GPIO14
+#define GPIO_UART1_RTS	GPIO_GPIO9
 #define GPIO_UART1_DTR	GPIO_GPIO7
 #define GPIO_UART1_CTS	GPIO_GPIO8
 #define GPIO_UART1_DCD	GPIO_GPIO23
@@ -31,12 +31,12 @@
 #define GPIO_POWER_BUTTON       GPIO_GPIO0
 #define GPIO_UCB1300_IRQ	GPIO_GPIO (22)	/* UCB GPIO and touchscreen */
 
-#define IRQ_UART1_CTS	IRQ_GPIO15
-#define IRQ_UART1_DCD	GPIO_GPIO23
-#define IRQ_UART1_DSR	GPIO_GPIO6
-#define IRQ_UART3_CTS	GPIO_GPIO13
-#define IRQ_UART3_DCD	GPIO_GPIO18
-#define IRQ_UART3_DSR	GPIO_GPIO17
+#define IRQ_GPIO_UART1_CTS	IRQ_GPIO8
+#define IRQ_GPIO_UART1_DCD	IRQ_GPIO23
+#define IRQ_GPIO_UART1_DSR	IRQ_GPIO6
+#define IRQ_GPIO_UART3_CTS	IRQ_GPIO13
+#define IRQ_GPIO_UART3_DCD	IRQ_GPIO18
+#define IRQ_GPIO_UART3_DSR	IRQ_GPIO17
 
 #define IRQ_GPIO_UCB1300_IRQ IRQ_GPIO22
 #define IRQ_GPIO_POWER_BUTTON    IRQ_GPIO0
--- arch/arm/mach-sa1100/simpad.c.orig	2004-09-24 17:15:46.000000000 +0200
+++ arch/arm/mach-sa1100/simpad.c	2004-09-24 17:09:52.000000000 +0200
@@ -22,9 +22,11 @@
 
 #include "generic.h"
 
+#undef SIMPAD_UART_USE_IRQ  // irq handling on CTS/DCD doesn't work yet
+
 long cs3_shadow;
 
-long get_cs3_shadow()
+long get_cs3_shadow(void)
 {
 	return cs3_shadow;
 }
@@ -102,18 +104,170 @@
   LAST_DESC
 };
 
+#define SER_INFO(fmt, arg...) printk(KERN_INFO fmt "\n" , ## arg)
+
+static void simpad_uart_set_mctrl(struct uart_port *port, u_int mctrl)
+{
+	if (port->mapbase == _Ser1UTCR0) {
+	        /* internal serial port (ttySA1, DECT/Bluetooth) */
+		if (mctrl & TIOCM_RTS)	GPCR = GPIO_UART1_RTS;
+		else			GPSR = GPIO_UART1_RTS;
+
+		if (mctrl & TIOCM_DTR)	GPCR = GPIO_UART1_DTR;
+		else			GPSR = GPIO_UART1_DTR;
+	}
+
+	else if (port->mapbase == _Ser3UTCR0) {
+	        /* external serial port (ttySA0, RS232) */
+	        if (mctrl & TIOCM_RTS)  GPCR = GPIO_UART3_RTS;
+		else			GPSR = GPIO_UART3_RTS;
+
+	        if (mctrl & TIOCM_DTR)  GPCR = GPIO_UART3_DTR;
+		else			GPSR = GPIO_UART3_DTR;
+	}
+}
+
+static u_int simpad_uart_get_mctrl(struct uart_port *port)
+{
+	u_int ret = TIOCM_CD | TIOCM_CTS | TIOCM_DSR;
+
+	if (port->mapbase == _Ser1UTCR0) {
+	        /* internal serial port (ttySA1, DECT/Bluetooth) */
+		int gplr = GPLR;
+		if (gplr & GPIO_UART1_DCD) ret &= ~TIOCM_CD;
+		if (gplr & GPIO_UART1_CTS) ret &= ~TIOCM_CTS;
+		if (gplr & GPIO_UART1_DSR) ret &= ~TIOCM_DSR;
+	}
+
+	else if (port->mapbase == _Ser3UTCR0) {
+	        /* external serial port (ttySA0, RS232) */
+		int gplr = GPLR;
+		if (gplr & GPIO_UART3_DCD) ret &= ~TIOCM_CD;
+		if (gplr & GPIO_UART3_CTS) ret &= ~TIOCM_CTS;
+		if (gplr & GPIO_UART3_DSR) ret &= ~TIOCM_DSR;
+	}
+	return ret;
+}
+
 static void simpad_uart_pm(struct uart_port *port, u_int state, u_int oldstate)
 {
-	if (port->mapbase == (u_int)&Ser1UTCR0) {
+	if (port->mapbase == (u_int)&Ser3UTCR0) {
 		if (state)
 			clear_cs3_bit(RS232_ON);
 		else
 			set_cs3_bit(RS232_ON);
 	}
 }
+/*
+ * Enable/Disable wake up events for this serial port.
+ * Obviously, we only support this on the normal COM port.
+ */
+static int simpad_uart_set_wake(struct uart_port *port, u_int enable)
+{
+	int err = -EINVAL;
+
+#if 0  // TODO: port management
+	if (port->mapbase == _Ser3UTCR0) {
+		if (enable)
+			PWER |= PWER_GPIO23 | PWER_GPIO25 ; /* DCD and CTS */
+		else
+			PWER &= ~(PWER_GPIO23 | PWER_GPIO25); /* DCD and CTS */
+		err = 0;
+	}
+#endif
+
+	return err;
+}
+
+#ifdef SIMPAD_UART_USE_IRQ
+static void simpad_uart1_dcd_intr(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct uart_port *port = dev_id;
+	/* Note: should only call this if something has changed */
+	uart_handle_dcd_change(port, !(GPLR & GPIO_UART1_DCD));
+}
+
+static void simpad_uart1_cts_intr(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct uart_port *port = dev_id;
+	/* Note: should only call this if something has changed */
+	uart_handle_cts_change(port, !(GPLR & GPIO_UART1_CTS));
+}
+
+static void simpad_uart3_dcd_intr(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct uart_port *port = dev_id;
+	/* Note: should only call this if something has changed */
+	uart_handle_dcd_change(port, !(GPLR & GPIO_UART3_DCD));
+}
+
+static void simpad_uart3_cts_intr(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct uart_port *port = dev_id;
+	/* Note: should only call this if something has changed */
+	uart_handle_cts_change(port, !(GPLR & GPIO_UART3_CTS));
+}
+#endif
+
+static int simpad_uart_open(struct uart_port *port)
+{
+	int ret = 0;
+#ifdef SIMPAD_UART_USE_IRQ
+	if (port->mapbase == _Ser1UTCR0) {
+		set_GPIO_IRQ_edge(GPIO_UART1_DCD|GPIO_UART1_CTS,
+				  GPIO_BOTH_EDGES);
+
+		ret = request_irq(IRQ_GPIO_UART1_DCD, simpad_uart1_dcd_intr,
+				  0, "UART1 DCD", port);
+		if (ret)
+			return ret;
+
+		ret = request_irq(IRQ_GPIO_UART1_CTS, simpad_uart1_cts_intr,
+				  0, "UART1 CTS", port);
+		if (ret)
+			free_irq(IRQ_GPIO_UART1_DCD, port);
+	}
+
+	else if (port->mapbase == _Ser3UTCR0) {
+		set_GPIO_IRQ_edge(GPIO_UART3_DCD|GPIO_UART3_CTS,
+				  GPIO_BOTH_EDGES);
+
+		ret = request_irq(IRQ_GPIO_UART3_DCD, simpad_uart3_dcd_intr,
+				  0, "UART3 DCD", port);
+		if (ret)
+			return ret;
+
+		ret = request_irq(IRQ_GPIO_UART3_CTS, simpad_uart3_cts_intr,
+				  0, "UART3 CTS", port);
+		if (ret)
+			free_irq(IRQ_GPIO_UART3_DCD, port);
+	}
+#endif
+	return ret;
+}
+
+static void simpad_uart_close(struct uart_port *port)
+{
+#ifdef SIMPAD_UART_USE_IRQ
+	if (port->mapbase == _Ser1UTCR0) {
+		free_irq(IRQ_GPIO_UART1_DCD, port);
+		free_irq(IRQ_GPIO_UART1_CTS, port);
+	}
+
+	else if (port->mapbase == _Ser3UTCR0) {
+		free_irq(IRQ_GPIO_UART3_DCD, port);
+		free_irq(IRQ_GPIO_UART3_CTS, port);
+	}
+#endif
+}
 
 static struct sa1100_port_fns simpad_port_fns __initdata = {
-	.pm	= simpad_uart_pm,
+	.set_mctrl	= simpad_uart_set_mctrl,
+	.get_mctrl	= simpad_uart_get_mctrl,
+	.pm	        = simpad_uart_pm,
+	.set_wake	= simpad_uart_set_wake,
+	.open		= simpad_uart_open,
+	.close		= simpad_uart_close,
 };
 
 static void __init simpad_map_io(void)
@@ -124,13 +278,32 @@
         set_cs3_bit (EN1 | EN0 | LED2_ON | DISPLAY_ON | RS232_ON |
                       ENABLE_5V | nRESET_SIMCARD);
 
+	sa1100_register_uart_fns(&simpad_port_fns);
+
         //It is only possible to register 3 UART in serial_sa1100.c
         sa1100_register_uart(0, 3);
         sa1100_register_uart(1, 1);
 
+	// txd and rxd use their alternate function
 	GAFR |= (GPIO_UART_TXD | GPIO_UART_RXD);
+
+	// the control lines are gpio
+	GAFR &= ~(GPIO_UART1_RTS | GPIO_UART1_CTS | GPIO_UART1_DCD);
+	GAFR &= ~(GPIO_UART1_DSR | GPIO_UART1_DTR);
+	GAFR &= ~(GPIO_UART3_RTS | GPIO_UART3_CTS | GPIO_UART3_DCD);
+	GAFR &= ~(GPIO_UART3_DSR | GPIO_UART3_DTR);
+
+	// txd, rts and dtr are outputs
 	GPDR |= GPIO_UART_TXD;
+	GPDR |= GPIO_UART1_RTS | GPIO_UART3_RTS;
+	GPDR |= GPIO_UART1_DTR | GPIO_UART3_DTR;
+
+	// cts, dcd, dsr and rxd are inputs
+	GPDR &= ~(GPIO_UART1_CTS | GPIO_UART3_CTS);
+	GPDR &= ~(GPIO_UART1_DCD | GPIO_UART3_DCD);
+	GPDR &= ~(GPIO_UART1_DSR | GPIO_UART3_DSR);
 	GPDR &= ~GPIO_UART_RXD;
+
 	PPAR |= PPAR_UPR;
 
         set_GPIO_IRQ_edge(GPIO_UCB1300_IRQ, GPIO_RISING_EDGE);
--- drivers/video/mq200fb.c~	2004-09-21 16:11:48.000000000 +0200
+++ drivers/video/mq200fb.c	2004-09-24 13:58:21.000000000 +0200
@@ -699,7 +699,7 @@
 
 #ifdef CONFIG_SA1100_SIMPAD
     GPDR |=   (1<<3);
-    GAFR |=  ~(1<<3);
+    GAFR &=  ~(1<<3);
     GPSR |=   (1<<3);
 #endif