# # Patch managed by http://www.holgerschurig.de/patcher.html # --- linux-2.4.27/include/asm-arm/arch-sa1100/simpad.h~simpad-serial +++ linux-2.4.27/include/asm-arm/arch-sa1100/simpad.h @@ -16,7 +16,7 @@ #error "include 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 --- linux-2.4.27/arch/arm/mach-sa1100/simpad.c~simpad-serial +++ linux-2.4.27/arch/arm/mach-sa1100/simpad.c @@ -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; } @@ -107,18 +109,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) @@ -129,13 +283,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); --- linux-2.4.27/drivers/video/mq200fb.c~simpad-serial +++ linux-2.4.27/drivers/video/mq200fb.c @@ -672,7 +672,7 @@ #ifdef CONFIG_SA1100_SIMPAD GPDR |= (1<<3); - GAFR |= ~(1<<3); + GAFR &= ~(1<<3); GPSR |= (1<<3); #endif