From 2489007e7d740ccbc3e0a202914e243ad5178787 Mon Sep 17 00:00:00 2001 From: codeworkx Date: Sat, 22 Sep 2012 09:48:20 +0200 Subject: merge opensource jb u5 Change-Id: I1aaec157aa196f3448eff8636134fce89a814cf2 --- drivers/tty/serial/samsung.c | 274 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 267 insertions(+), 7 deletions(-) (limited to 'drivers/tty/serial/samsung.c') diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c index 2468df0..a3b31b8 100644 --- a/drivers/tty/serial/samsung.c +++ b/drivers/tty/serial/samsung.c @@ -52,6 +52,8 @@ #include "samsung.h" +#include +#include /* UART name and device definitions */ #define S3C24XX_SERIAL_NAME "ttySAC" @@ -67,7 +69,8 @@ #define RXSTAT_DUMMY_READ (0x10000000) #if defined(CONFIG_MACH_U1) || defined(CONFIG_MACH_MIDAS) || \ - defined(CONFIG_MACH_SLP_PQ)||defined(CONFIG_MACH_P10) + defined(CONFIG_MACH_SLP_PQ) || defined(CONFIG_MACH_P10) || \ + defined(CONFIG_MACH_PX) || defined(CONFIG_MACH_TRATS) /* Devices */ #define CONFIG_BT_S3C_UART 0 #define CONFIG_GPS_S3C_UART 1 @@ -197,7 +200,16 @@ static int s3c24xx_serial_rx_fifocnt(struct s3c24xx_uart_port *ourport, return (ufstat & info->rx_fifomask) >> info->rx_fifoshift; } +#ifdef CONFIG_CSR_GSD4T_CDMA +#define CSR_GPS_WORK_AROUND_RX_ISR /*it should be applied to*/ +#define CSR_GPS_WORK_AROUND_UART_DRIVER /*it should be applied to*/ +/*#define CSR_GPS_DEBUG */ /* just debug code*/ +/*#define CSR_GPS_DEBUG_RAW_DATA */ /*just debug code*/ +#endif +#ifdef CSR_GPS_DEBUG +#define GPIO_GPS_DEBUG_NEW EXYNOS4_GPK1(2) +#endif /* ? - where has parity gone?? */ #define S3C2410_UERSTAT_PARITY (0x1000) @@ -209,7 +221,32 @@ s3c24xx_serial_rx_chars(int irq, void *dev_id) struct uart_port *port = &ourport->port; struct tty_struct *tty = port->state->port.tty; unsigned int ufcon, ch, flag, ufstat, uerstat; +#ifdef CSR_GPS_WORK_AROUND_RX_ISR + int max_count = 256; + unsigned char received_data[256]; + unsigned char received_flag[256]; + int received_data_count = 0; +#else int max_count = 64; +#endif +#ifdef CSR_GPS_DEBUG + int overrun = 0; + static int gpio_init = 0; + static int active_signal = 1; +#endif +#ifdef CSR_GPS_DEBUG_RAW_DATA + char received_data_string[256*2+1]; + int i; +#endif +#ifdef CSR_GPS_DEBUG + if (gpio_init == 0) { + s3c_gpio_cfgpin(GPIO_GPS_DEBUG_NEW, S3C_GPIO_OUTPUT); + s3c_gpio_setpull(GPIO_GPS_DEBUG_NEW, S3C_GPIO_PULL_NONE); + gpio_init = 1; + } + + gpio_set_value(GPIO_GPS_DEBUG_NEW, active_signal); +#endif while (max_count-- > 0) { ufcon = rd_regl(port, S3C2410_UFCON); @@ -252,16 +289,32 @@ s3c24xx_serial_rx_chars(int irq, void *dev_id) /* check for break */ if (uerstat & S3C2410_UERSTAT_BREAK) { dbg("break!\n"); +#ifdef CSR_GPS_WORK_AROUND_RX_ISR + printk(KERN_ERR KERN_DEBUG "break!\n"); +#endif port->icount.brk++; if (uart_handle_break(port)) goto ignore_char; } - if (uerstat & S3C2410_UERSTAT_FRAME) + if (uerstat & S3C2410_UERSTAT_FRAME) { +#ifdef CSR_GPS_WORK_AROUND_RX_ISR + printk(KERN_ERR KERN_DEBUG "frame error!\n"); +#endif port->icount.frame++; - if (uerstat & S3C2410_UERSTAT_OVERRUN) + } + if (uerstat & S3C2410_UERSTAT_OVERRUN) { +#ifdef CSR_GPS_WORK_AROUND_RX_ISR + printk(KERN_ERR KERN_DEBUG "overrun error!\n"); +#endif port->icount.overrun++; - +#ifdef CSR_GPS_DEBUG + if (overrun == 0) { + overrun = 1; + active_signal = !active_signal; + } +#endif + } uerstat &= port->read_status_mask; if (uerstat & S3C2410_UERSTAT_BREAK) @@ -273,18 +326,72 @@ s3c24xx_serial_rx_chars(int irq, void *dev_id) flag = TTY_FRAME; } - if (uart_handle_sysrq_char(port, ch)) + if (uart_handle_sysrq_char(port, ch)) { + printk(KERN_ERR KERN_DEBUG "break-sysrq\n"); goto ignore_char; + } +#ifdef CSR_GPS_WORK_AROUND_RX_ISR + received_data[received_data_count] = ch; + received_flag[received_data_count] = flag; + received_data_count++; +#else uart_insert_char(port, uerstat, S3C2410_UERSTAT_OVERRUN, ch, flag); +#endif ignore_char: continue; } +#ifdef CSR_GPS_WORK_AROUND_RX_ISR + if (received_data_count) { +#ifdef CSR_GPS_DEBUG_RAW_DATA + if (tty->index == 1) { + int nibble; + unsigned char *ptr_src, *ptr_dst; + + ptr_src = received_data; + ptr_dst = received_data_string; + + for (i = 0; i < received_data_count; i++, ptr_src++) { + nibble = (*ptr_src >> 4) & 0x0F; + if (9 < nibble) + *ptr_dst = nibble - 10 + 'A'; + else + *ptr_dst = nibble + '0'; + + ptr_dst++; + + nibble = (*ptr_src) & 0x0F; + + if (9 < nibble) + *ptr_dst = nibble - 10 + 'A'; + else + *ptr_dst = nibble + '0'; + + ptr_dst++; + } + + *ptr_dst = '\0'; + printk(KERN_ERR KERN_DEBUG "CGPS:%s\n", \ + received_data_string); + } +#endif /* CSR_GPS_DEBUG_RAW_DATA */ + tty_insert_flip_string_flags(tty, \ + (const unsigned char *)received_data, \ + (const char *)received_flag, \ + (size_t) received_data_count); /* yr check */ + tty_flip_buffer_push(tty); + } +#else /* !CSR_GPS_WORK_AROUND_RX_ISR */ tty_flip_buffer_push(tty); +#endif /* CSR_GPS_WORK_AROUND_RX_ISR */ out: +#ifdef CSR_GPS_DEBUG + /*oif overrun, gpio toggle*/ + gpio_set_value(GPIO_GPS_DEBUG_NEW, !active_signal); +#endif return IRQ_HANDLED; } @@ -366,7 +473,7 @@ static void s3c24xx_serial_set_mctrl(struct uart_port *port, unsigned int mctrl) #if defined(CONFIG_MACH_U1) || defined(CONFIG_MACH_MIDAS) || \ defined(CONFIG_MACH_SLP_PQ) || defined(CONFIG_MACH_P10) || \ - defined(CONFIG_MACH_U1CAMERA_BD) + defined(CONFIG_MACH_PX) || defined(CONFIG_MACH_TRATS) unsigned int umcon = 0; umcon = rd_regl(port, S3C2410_UMCON); @@ -723,7 +830,8 @@ static void s3c24xx_serial_set_termios(struct uart_port *port, * Ask the core to calculate the divisor for us. */ #if defined(CONFIG_MACH_U1) || defined(CONFIG_MACH_MIDAS) || \ - defined(CONFIG_MACH_SLP_PQ)||defined(CONFIG_MACH_P10) + defined(CONFIG_MACH_SLP_PQ) || defined(CONFIG_MACH_P10) || \ + defined(CONFIG_MACH_PX) || defined(CONFIG_MACH_TRATS) baud = uart_get_baud_rate(port, termios, old, 0, 4000000); // 4Mbps #else baud = uart_get_baud_rate(port, termios, old, 0, 3000000); @@ -1200,6 +1308,152 @@ static ssize_t s3c24xx_serial_show_clksrc(struct device *dev, } static DEVICE_ATTR(clock_source, S_IRUGO, s3c24xx_serial_show_clksrc, NULL); +#ifdef CSR_GPS_WORK_AROUND_UART_DRIVER +static ssize_t s3c24xx_serial_rts_pullup_detect(struct device *dev, \ + struct device_attribute *attr, char *buf) +{ + int i; + s3c_gpio_pull_t back_pull; + unsigned int back_cfg; + + /*back_pull = s3c_gpio_getpull(GPIO_GPS_RTS); back up*/ + back_pull = S3C_GPIO_PULL_NONE; + /*back_cfg = s3c_gpio_getcfg(GPIO_GPS_RTS);*/ + back_cfg = S3C_GPIO_SFN(2); + s3c_gpio_setpull(GPIO_GPS_RTS, S3C_GPIO_PULL_DOWN); + + s3c_gpio_cfgpin(GPIO_GPS_RTS, S3C_GPIO_OUTPUT); + + gpio_set_value(GPIO_GPS_RTS, 0); + + s3c_gpio_cfgpin(GPIO_GPS_RTS, S3C_GPIO_INPUT); + + /*here, you may need a little delay*/ + for (i = 0; i < 100; i++); + buf[0] = '0' + gpio_get_value(GPIO_GPS_RTS); + s3c_gpio_cfgpin(GPIO_GPS_RTS, back_cfg); + s3c_gpio_setpull(GPIO_GPS_RTS, back_pull); + + printk(KERN_ERR KERN_DEBUG \ + "rts_cts_gate:detect RTS pin pulled_up - %c\n", buf[0]); + + return 1; +} + +static ssize_t s3c24xx_serial_rts_cts_config(struct device *dev, \ + struct device_attribute *attr, const char *buf, size_t size) +{ + + s3c_gpio_pull_t rts_pull_option, cts_pull_option; + + printk(KERN_ERR KERN_DEBUG "rts_cts_gate:config [%c%c%c]\n", \ + buf[0], buf[1], buf[2]); + + rts_pull_option = S3C_GPIO_PULL_NONE; + cts_pull_option = S3C_GPIO_PULL_NONE; + + if (buf[1] == '-') { + rts_pull_option = S3C_GPIO_PULL_DOWN; + printk(KERN_ERR KERN_DEBUG "rts_cts_gate: rts pull-down\n"); + } else if (buf[1] == '+') { + rts_pull_option = S3C_GPIO_PULL_UP; + printk(KERN_ERR KERN_DEBUG "rts_cts_gate: rts pull-up\n"); + } else { + rts_pull_option = S3C_GPIO_PULL_NONE; + printk(KERN_ERR KERN_DEBUG "rts_cts_gate: rts pull-none\n"); + } + + if (buf[2] == '-') { + cts_pull_option = S3C_GPIO_PULL_DOWN; + printk(KERN_ERR KERN_DEBUG "rts_cts_gate: cts pull-down\n"); + } else if (buf[2] == '+') { + cts_pull_option = S3C_GPIO_PULL_UP; + printk(KERN_ERR KERN_DEBUG "rts_cts_gate: cts pull-up\n"); + } else { + cts_pull_option = S3C_GPIO_PULL_NONE; + printk(KERN_ERR KERN_DEBUG "rts_cts_gate: cts pull-none\n"); + } + + if (buf[0] == '0') { /* rts/cts*/ + printk(KERN_ERR KERN_DEBUG "rts_cts_gate: hw flow control\n"); + + s3c_gpio_cfgpin(GPIO_GPS_RTS, S3C_GPIO_SFN(2)); + s3c_gpio_setpull(GPIO_GPS_RTS, rts_pull_option); + + s3c_gpio_cfgpin(GPIO_GPS_CTS, S3C_GPIO_SFN(2)); + s3c_gpio_setpull(GPIO_GPS_CTS, cts_pull_option); + } + /* rts high cts high*/ + else if (buf[0] == '1') { /* control pins for GPS reset*/ + printk(KERN_ERR KERN_DEBUG "rts_cts_gate: RTS-HIGH, CTS-HIGH\n"); + + s3c_gpio_cfgpin(GPIO_GPS_RTS, S3C_GPIO_OUTPUT); + s3c_gpio_setpull(GPIO_GPS_RTS, rts_pull_option); + gpio_set_value(GPIO_GPS_RTS, 1); + + s3c_gpio_cfgpin(GPIO_GPS_CTS, S3C_GPIO_OUTPUT); + s3c_gpio_setpull(GPIO_GPS_CTS, cts_pull_option); + gpio_set_value(GPIO_GPS_CTS, 1); + } + /* rts high cts input*/ + else if (buf[0] == '2') { /* control pins for GPS reset*/ + printk(KERN_ERR KERN_DEBUG "rts_cts_gate: RTS-HIGH, CTS-INPUT\n"); + + s3c_gpio_cfgpin(GPIO_GPS_RTS, S3C_GPIO_OUTPUT); + s3c_gpio_setpull(GPIO_GPS_RTS, rts_pull_option); + gpio_set_value(GPIO_GPS_RTS, 1); + + s3c_gpio_cfgpin(GPIO_GPS_CTS, S3C_GPIO_INPUT); + s3c_gpio_setpull(GPIO_GPS_CTS, cts_pull_option); + } + /* rts input cts input*/ + else if (buf[0] == '3') { /* control pins for GPS reset */ + printk(KERN_ERR KERN_DEBUG "rts_cts_gate: RTS-INPUT, CTS-INPUT\n"); + + s3c_gpio_cfgpin(GPIO_GPS_RTS, S3C_GPIO_INPUT); + s3c_gpio_setpull(GPIO_GPS_RTS, rts_pull_option); + + s3c_gpio_cfgpin(GPIO_GPS_CTS, S3C_GPIO_INPUT); + s3c_gpio_setpull(GPIO_GPS_CTS, cts_pull_option); + } + /* rts input cts high */ + else if (buf[0] == '4') { /*control pins for GPS reset*/ + printk(KERN_ERR KERN_DEBUG "rts_cts_gate: RTS-INPUT, CTS-HIGH\n"); + + s3c_gpio_cfgpin(GPIO_GPS_RTS, S3C_GPIO_INPUT); + s3c_gpio_setpull(GPIO_GPS_RTS, rts_pull_option); + + s3c_gpio_cfgpin(GPIO_GPS_CTS, S3C_GPIO_OUTPUT); + s3c_gpio_setpull(GPIO_GPS_CTS, cts_pull_option); + gpio_set_value(GPIO_GPS_CTS, 1); + } + /*test rts high*/ + else if (buf[0] == '5') { /*rts test - ouput 0*/ + printk(KERN_ERR KERN_DEBUG "rts_cts_gate: RTS set 0\n"); + + s3c_gpio_cfgpin(GPIO_GPS_RTS, S3C_GPIO_OUTPUT); + s3c_gpio_setpull(GPIO_GPS_RTS, rts_pull_option); + + gpio_set_value(GPIO_GPS_RTS, 0); + } + /* test rts low*/ + else if (buf[0] == '6') { /*rts test - output 1*/ + printk(KERN_ERR KERN_DEBUG "rts_cts_gate:RTS set 1\n"); + + s3c_gpio_cfgpin(GPIO_GPS_RTS, S3C_GPIO_OUTPUT); + s3c_gpio_setpull(GPIO_GPS_RTS, rts_pull_option); + + gpio_set_value(GPIO_GPS_RTS, 1); + } + + return 1; +} + +static DEVICE_ATTR(rts_cts_gate, \ + S_IRGRP | S_IWGRP | S_IRUSR | S_IWUSR | S_IROTH, \ + s3c24xx_serial_rts_pullup_detect, \ + s3c24xx_serial_rts_cts_config); +#endif /* Device driver serial port probe */ @@ -1230,6 +1484,12 @@ int s3c24xx_serial_probe(struct platform_device *dev, if (ret < 0) printk(KERN_ERR "%s: failed to add clksrc attr.\n", __func__); +#ifdef CSR_GPS_WORK_AROUND_UART_DRIVER + ret = device_create_file(&dev->dev, &dev_attr_rts_cts_gate); /* woojun*/ + if (ret < 0) + printk(KERN_ERR "%s: failed to add rts_cts_gate attr.\n", \ + __func__); +#endif ret = s3c24xx_serial_cpufreq_register(ourport); if (ret < 0) dev_err(&dev->dev, "failed to add cpufreq notifier\n"); -- cgit v1.1