diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index b4b3981..c61bd61 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c @@ -42,6 +42,8 @@ #include #include +#include + #include "8250.h" #ifdef CONFIG_SPARC @@ -370,6 +372,43 @@ static inline int map_8250_out_reg(struct uart_port *p, int offset) #endif + + + +/* to set UART1 RTS in SAFE mode and pull up/down for test purposes */ +static unsigned int toggle_rts_uart1(unsigned int state) { + if (state == 0) + omap_ctrl_writew(0x08 | 0x7,0x17e); /*SAFE mode, pullup, offset */ + else if (state == 1) + omap_ctrl_writew(0x18 | 0x7,0x17e); /*SAFE mode, pulldown, offset */ + else { + printk(KERN_WARNING "UART1 RTS could not be toggled! state is %u\n",state); + return 1; + } + return 0; +} + +static int uart1_rts_set(void *data, u64 val) +{ + toggle_rts_uart1((unsigned int) val); + return 0; +} + +static int uart1_rts_get(void *data, u64 *val) +{ + u32 tmp; + tmp = omap_ctrl_readw(0x17e); + + if (tmp & 0x7) /* only makes sense when controlled in SAFE mode */ + *val = tmp & 0x10; /* show pull up/down bit status */ + else + *val = 99; /*value that doesn't make sense */ + return 0; +} + +DEFINE_SIMPLE_ATTRIBUTE(uart1_rts_toggle_fops, uart1_rts_get,uart1_rts_set, "%llu\n"); + + static unsigned int hub6_serial_in(struct uart_port *p, int offset) { offset = map_8250_in_reg(p, offset) << p->regshift; @@ -2390,6 +2429,11 @@ serial8250_set_termios(struct uart_port *port, struct ktermios *termios, serial_outp(up, UART_FCR, fcr); /* set fcr */ } serial8250_set_mctrl(&up->port, up->port.mctrl); + + /* set rts to pull up initially */ + toggle_rts_uart1(0); + + spin_unlock_irqrestore(&up->port.lock, flags); /* Don't rewrite B0 */ if (tty_termios_baud_rate(termios)) @@ -2666,6 +2710,58 @@ static void __init serial8250_isa_init_ports(void) } } +static ssize_t uart1_rts_show(struct kobject *kobj, + struct kobj_attribute *attr, + char *buf) +{ + // return sprintf(buf, "%u\n", sleep_timeout / HZ); + + u32 tmp,val; + tmp = omap_ctrl_readw(0x17e); + + if (tmp & 0x7) /* only makes sense when controlled in SAFE mode */ + val = (tmp & 0x10) >> 4; /* show pull up/down bit status */ + else + val = 99; /*value that doesn't make sense */ + + return sprintf(buf,"UART1 RTS pin is %u\n", val); +} + +/* set RTS pin to value */ +static ssize_t uart1_rts_store(struct kobject *kobj, + struct kobj_attribute *attr, + const char *buf, size_t n) +{ + unsigned int value, state; + u32 tmp; + + if (sscanf(buf, "%u", &value) != 1) { + printk(KERN_ERR "uart1_rts_store: Invalid input value\n"); + return -EINVAL; + } + + if (value == 1) { + + tmp = omap_ctrl_readw(0x17e); + if (tmp & 0x7) {/* if SAFE mode then toggle*/ + state = (tmp & 0x10) >> 4; /* complement pull up/down bit status */ + toggle_rts_uart1(state ^ 0x1); + + } else /* set in safe mode and RTs to 1 */ + toggle_rts_uart1((unsigned int) 1); + + } else if (value == 0) + omap_ctrl_writew(0x0,0x17e); /*UART mode, disable safe mode */ + else + printk(KERN_ERR "uart1_rts_store: Invalid input value\n"); + + + return n; +} + +static struct kobj_attribute uart1_rts_toggle_attr = + __ATTR(uart1_rts_toggle, 0644, uart1_rts_show, uart1_rts_store); + static void __init serial8250_register_ports(struct uart_driver *drv, struct device *dev) { @@ -2679,6 +2775,7 @@ serial8250_register_ports(struct uart_driver *drv, struct device *dev) up->port.dev = dev; uart_add_one_port(drv, &up->port); } + } #ifdef CONFIG_SERIAL_8250_CONSOLE @@ -2941,6 +3038,11 @@ static int __devinit serial8250_probe(struct platform_device *dev) p->irq, ret); } } + + + if (dev->id == 0) + sysfs_create_file(&dev->dev.kobj,&uart1_rts_toggle_attr.attr); + return 0; }