patch-2.4.14 linux/arch/arm/mach-sa1100/graphicsclient.c

Next file: linux/arch/arm/mach-sa1100/graphicsmaster.c
Previous file: linux/arch/arm/mach-sa1100/freebird.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.13/linux/arch/arm/mach-sa1100/graphicsclient.c linux/arch/arm/mach-sa1100/graphicsclient.c
@@ -23,6 +23,7 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/mach/serial_sa1100.h>
+#include <linux/serial_core.h>
 
 #include <asm/arch/irq.h>
 
@@ -143,11 +144,185 @@
   LAST_DESC
 };
 
+static struct gc_uart_ctrl_data_t gc_uart_ctrl_data[] = {
+  { GPIO_GC_UART0_CTS, 0, NULL,NULL },
+  { GPIO_GC_UART1_CTS, 0, NULL,NULL },
+  { GPIO_GC_UART2_CTS, 0, NULL,NULL }
+};
+
+static void
+graphicsclient_cts_intr(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct gc_uart_ctrl_data_t * uart_data = (struct gc_uart_ctrl_data_t *)dev_id;
+	int cts = !(GPLR & uart_data->cts_gpio);
+
+	/* NOTE: I supose that we will no get any interrupt
+	   if the GPIO is not changed, so maybe
+	   the cts_prev_state can be removed ... */
+	if (cts != uart_data->cts_prev_state) {
+		uart_data->cts_prev_state = cts;
+
+		uart_handle_cts_change(uart_data->info, cts);
+	}
+}
+
+static int
+graphicsclient_register_cts_intr(int gpio, int irq,
+				 struct gc_uart_ctrl_data_t *uart_data)
+{
+	int ret = 0;
+
+	set_GPIO_IRQ_edge(gpio, GPIO_BOTH_EDGES);
+
+	ret = request_irq(irq, graphicsclient_cts_intr,
+			  0, "GC RS232 CTS", uart_data);
+	if (ret) {
+		printk(KERN_ERR "uart_open: failed to register CTS irq (%d)\n",
+		       ret);
+		free_irq(irq, uart_data);
+	}
+
+	return ret;
+}
+
+static int
+graphicsclient_uart_open(struct uart_port *port, struct uart_info *info)
+{
+	int ret = 0;
+
+	if (port->mapbase == _Ser1UTCR0) {
+		Ser1SDCR0 |= SDCR0_UART;
+		/* Set RTS Output */
+		GPDR |= GPIO_GC_UART0_RTS;
+		GPSR  = GPIO_GC_UART0_RTS;
+
+		/* Set CTS Input */
+		GPDR &= ~GPIO_GC_UART0_CTS;
+
+		gc_uart_ctrl_data[0].cts_prev_state = 0;
+		gc_uart_ctrl_data[0].info = info;
+		gc_uart_ctrl_data[0].port = port;
+
+		/* register uart0 CTS irq */
+		ret = graphicsclient_register_cts_intr(GPIO_GC_UART0_CTS,
+							IRQ_GC_UART0_CTS,
+							&gc_uart_ctrl_data[0]);
+	} else if (port->mapbase == _Ser2UTCR0) {
+		Ser2UTCR4 = Ser2HSCR0 = 0;
+		/* Set RTS Output */
+		GPDR |= GPIO_GC_UART1_RTS;
+		GPSR  = GPIO_GC_UART1_RTS;
+
+		/* Set CTS Input */
+		GPDR &= ~GPIO_GC_UART1_RTS;
+
+		gc_uart_ctrl_data[1].cts_prev_state = 0;
+		gc_uart_ctrl_data[1].info = info;
+		gc_uart_ctrl_data[1].port = port;
+
+		/* register uart1 CTS irq */
+		ret = graphicsclient_register_cts_intr(GPIO_GC_UART1_CTS,
+							IRQ_GC_UART1_CTS,
+							&gc_uart_ctrl_data[1]);
+	} else if (port->mapbase == _Ser3UTCR0) {
+		/* Set RTS Output */
+		GPDR |= GPIO_GC_UART2_RTS;
+		GPSR =	GPIO_GC_UART2_RTS;
+
+		/* Set CTS Input */
+		GPDR &= ~GPIO_GC_UART2_RTS;
+
+		gc_uart_ctrl_data[2].cts_prev_state = 0;
+		gc_uart_ctrl_data[2].info = info;
+		gc_uart_ctrl_data[2].port = port;
+
+		/* register uart2 CTS irq */
+		ret = graphicsclient_register_cts_intr(GPIO_GC_UART2_CTS,
+							IRQ_GC_UART2_CTS,
+							&gc_uart_ctrl_data[2]);
+	}
+	return ret;
+}
+
+static int
+graphicsclient_uart_close(struct uart_port *port, struct uart_info *info)
+{
+	if (port->mapbase == _Ser1UTCR0) {
+		free_irq(IRQ_GC_UART0_CTS, &gc_uart_ctrl_data[0]);
+	} else if (port->mapbase == _Ser2UTCR0) {
+		free_irq(IRQ_GC_UART1_CTS, &gc_uart_ctrl_data[1]);
+	} else if (port->mapbase == _Ser3UTCR0) {
+		free_irq(IRQ_GC_UART2_CTS, &gc_uart_ctrl_data[2]);
+	}
+
+	return 0;
+}
+
+static int graphicsclient_get_mctrl(struct uart_port *port)
+{
+	int result = TIOCM_CD | TIOCM_DSR;
+
+	if (port->mapbase == _Ser1UTCR0) {
+		if (!(GPLR & GPIO_GC_UART0_CTS))
+			result |= TIOCM_CTS;
+	} else if (port->mapbase == _Ser2UTCR0) {
+		if (!(GPLR & GPIO_GC_UART1_CTS))
+			result |= TIOCM_CTS;
+	} else if (port->mapbase == _Ser3UTCR0) {
+		if (!(GPLR & GPIO_GC_UART2_CTS))
+			result |= TIOCM_CTS;
+	} else {
+		result = TIOCM_CTS;
+	}
+
+	return result;
+}
+
+static void graphicsclient_set_mctrl(struct uart_port *port, u_int mctrl)
+{
+	if (port->mapbase == _Ser1UTCR0) {
+		if (mctrl & TIOCM_RTS)
+			GPCR = GPIO_GC_UART0_RTS;
+		else
+			GPSR = GPIO_GC_UART0_RTS;
+	} else if (port->mapbase == _Ser2UTCR0) {
+		if (mctrl & TIOCM_RTS)
+			GPCR = GPIO_GC_UART1_RTS;
+		else
+			GPSR = GPIO_GC_UART1_RTS;
+	} else if (port->mapbase == _Ser3UTCR0) {
+		if (mctrl & TIOCM_RTS)
+			GPCR = GPIO_GC_UART2_RTS;
+		else
+			GPSR = GPIO_GC_UART2_RTS;
+	}
+}
+
+static void
+graphicsclient_uart_pm(struct uart_port *port, u_int state, u_int oldstate)
+{
+	if (!state) {
+		/* make serial ports work ... */
+		Ser2UTCR4 = 0;
+		Ser2HSCR0 = 0; 
+		Ser1SDCR0 |= SDCR0_UART;
+	}
+}
+
+static struct sa1100_port_fns graphicsclient_port_fns __initdata = {
+	open:		graphicsclient_uart_open,
+	close:		graphicsclient_uart_close,
+	get_mctrl:	graphicsclient_get_mctrl,
+	set_mctrl:	graphicsclient_set_mctrl,
+	pm:		graphicsclient_uart_pm,
+};
+
 static void __init graphicsclient_map_io(void)
 {
 	sa1100_map_io();
 	iotable_init(graphicsclient_io_desc);
 
+	sa1100_register_uart_fns(&graphicsclient_port_fns);
 	sa1100_register_uart(0, 3);
 	sa1100_register_uart(1, 1);
 	sa1100_register_uart(2, 2);

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)