aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty/serial/samsung.c
diff options
context:
space:
mode:
authorcodeworkx <daniel.hillenbrand@codeworkx.de>2012-06-02 13:09:29 +0200
committercodeworkx <daniel.hillenbrand@codeworkx.de>2012-06-02 13:09:29 +0200
commitc6da2cfeb05178a11c6d062a06f8078150ee492f (patch)
treef3b4021d252c52d6463a9b3c1bb7245e399b009c /drivers/tty/serial/samsung.c
parentc6d7c4dbff353eac7919342ae6b3299a378160a6 (diff)
downloadkernel_samsung_smdk4412-c6da2cfeb05178a11c6d062a06f8078150ee492f.zip
kernel_samsung_smdk4412-c6da2cfeb05178a11c6d062a06f8078150ee492f.tar.gz
kernel_samsung_smdk4412-c6da2cfeb05178a11c6d062a06f8078150ee492f.tar.bz2
samsung update 1
Diffstat (limited to 'drivers/tty/serial/samsung.c')
-rw-r--r--drivers/tty/serial/samsung.c99
1 files changed, 82 insertions, 17 deletions
diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c
index f66f648..2468df0 100644
--- a/drivers/tty/serial/samsung.c
+++ b/drivers/tty/serial/samsung.c
@@ -66,6 +66,18 @@
/* flag to ignore all characters coming in */
#define RXSTAT_DUMMY_READ (0x10000000)
+#if defined(CONFIG_MACH_U1) || defined(CONFIG_MACH_MIDAS) || \
+ defined(CONFIG_MACH_SLP_PQ)||defined(CONFIG_MACH_P10)
+/* Devices */
+#define CONFIG_BT_S3C_UART 0
+#define CONFIG_GPS_S3C_UART 1
+#endif
+
+#ifdef CONFIG_SERIAL_SAMSUNG_CONSOLE_SWITCH
+static unsigned uart_debug; /* Initialized automatically with 0 by compiler */
+module_param_named(uart_debug, uart_debug, uint, 0644);
+#endif
+
static inline struct s3c24xx_uart_port *to_ourport(struct uart_port *port)
{
return container_of(port, struct s3c24xx_uart_port, port);
@@ -351,6 +363,28 @@ static unsigned int s3c24xx_serial_get_mctrl(struct uart_port *port)
static void s3c24xx_serial_set_mctrl(struct uart_port *port, unsigned int mctrl)
{
/* todo - possibly remove AFC and do manual CTS */
+
+#if defined(CONFIG_MACH_U1) || defined(CONFIG_MACH_MIDAS) || \
+ defined(CONFIG_MACH_SLP_PQ) || defined(CONFIG_MACH_P10) || \
+ defined(CONFIG_MACH_U1CAMERA_BD)
+ unsigned int umcon = 0;
+ umcon = rd_regl(port, S3C2410_UMCON);
+
+ if (port->line == CONFIG_BT_S3C_UART) {
+ if (mctrl & TIOCM_RTS) {
+ umcon |= S3C2410_UMCOM_AFC;
+ } else {
+ umcon &= ~S3C2410_UMCOM_AFC;
+ }
+
+ } else if (port->line == CONFIG_GPS_S3C_UART) {
+ umcon |= S3C2410_UMCOM_AFC;
+ } else {
+ umcon &= ~S3C2410_UMCOM_AFC;
+ }
+
+ wr_regl(port, S3C2410_UMCON, umcon);
+#endif
}
static void s3c24xx_serial_break_ctl(struct uart_port *port, int break_state)
@@ -375,29 +409,40 @@ static void s3c24xx_serial_break_ctl(struct uart_port *port, int break_state)
static void s3c24xx_serial_shutdown(struct uart_port *port)
{
struct s3c24xx_uart_port *ourport = to_ourport(port);
+ struct s3c2410_uartcfg *cfg = s3c24xx_port_to_cfg(port);
if (ourport->tx_claimed) {
+ disable_irq(ourport->tx_irq);
free_irq(ourport->tx_irq, ourport);
tx_enabled(port) = 0;
ourport->tx_claimed = 0;
}
if (ourport->rx_claimed) {
+ disable_irq(ourport->rx_irq);
free_irq(ourport->rx_irq, ourport);
ourport->rx_claimed = 0;
rx_enabled(port) = 0;
}
+
+ if (cfg->set_runstate)
+ cfg->set_runstate(0);
}
static int s3c24xx_serial_startup(struct uart_port *port)
{
struct s3c24xx_uart_port *ourport = to_ourport(port);
+ struct s3c2410_uartcfg *cfg = s3c24xx_port_to_cfg(port);
int ret;
dbg("s3c24xx_serial_startup: port=%p (%08lx,%p)\n",
port->mapbase, port->membase);
+ /* runstate should be 1 before request_irq is called */
+ if (cfg->set_runstate)
+ cfg->set_runstate(1);
+
rx_enabled(port) = 1;
ret = request_irq(ourport->rx_irq, s3c24xx_serial_rx_chars, 0,
@@ -405,7 +450,7 @@ static int s3c24xx_serial_startup(struct uart_port *port)
if (ret != 0) {
printk(KERN_ERR "cannot get irq %d\n", ourport->rx_irq);
- return ret;
+ goto err;
}
ourport->rx_claimed = 1;
@@ -574,7 +619,7 @@ static unsigned int s3c24xx_serial_getclk(struct uart_port *port,
*/
if (strcmp(clkp->name, "fclk") == 0) {
- struct s3c24xx_uart_clksrc src;
+ struct s3c24xx_uart_clksrc src = { "", 0, };
s3c24xx_serial_getsource(port, &src);
@@ -596,6 +641,7 @@ static unsigned int s3c24xx_serial_getclk(struct uart_port *port,
} else {
resptr = res;
+ best = res;
for (i = 0; i < cfg->clocks_size; i++, clkp++) {
if (s3c24xx_serial_calcbaud(resptr, port, clkp, baud))
resptr++;
@@ -608,6 +654,7 @@ static unsigned int s3c24xx_serial_getclk(struct uart_port *port,
unsigned int deviation = (1<<30)|((1<<30)-1);
int calc_deviation;
+ best = res;
for (sptr = res; sptr < resptr; sptr++) {
calc_deviation = baud - sptr->calc;
if (calc_deviation < 0)
@@ -675,9 +722,12 @@ static void s3c24xx_serial_set_termios(struct uart_port *port,
/*
* Ask the core to calculate the divisor for us.
*/
-
- baud = uart_get_baud_rate(port, termios, old, 0, 115200*8);
-
+#if defined(CONFIG_MACH_U1) || defined(CONFIG_MACH_MIDAS) || \
+ defined(CONFIG_MACH_SLP_PQ)||defined(CONFIG_MACH_P10)
+ baud = uart_get_baud_rate(port, termios, old, 0, 4000000); // 4Mbps
+#else
+ baud = uart_get_baud_rate(port, termios, old, 0, 3000000);
+#endif
if (baud == 38400 && (port->flags & UPF_SPD_MASK) == UPF_SPD_CUST)
quot = port->custom_divisor;
else
@@ -849,6 +899,14 @@ s3c24xx_serial_verify_port(struct uart_port *port, struct serial_struct *ser)
return 0;
}
+static void
+s3c24xx_serial_wake_peer(struct uart_port *port)
+{
+ struct s3c2410_uartcfg *cfg = s3c24xx_port_to_cfg(port);
+
+ if(cfg->wake_peer)
+ cfg->wake_peer(port);
+}
#ifdef CONFIG_SERIAL_SAMSUNG_CONSOLE
@@ -877,6 +935,7 @@ static struct uart_ops s3c24xx_serial_ops = {
.request_port = s3c24xx_serial_request_port,
.config_port = s3c24xx_serial_config_port,
.verify_port = s3c24xx_serial_verify_port,
+ .wake_peer = s3c24xx_serial_wake_peer,
};
@@ -884,7 +943,11 @@ static struct uart_driver s3c24xx_uart_drv = {
.owner = THIS_MODULE,
.driver_name = "s3c2410_serial",
.nr = CONFIG_SERIAL_SAMSUNG_UARTS,
+#ifdef CONFIG_SERIAL_SAMSUNG_CONSOLE_SWITCH
+ .cons = NULL,
+#else
.cons = S3C24XX_SERIAL_CONSOLE,
+#endif
.dev_name = S3C24XX_SERIAL_NAME,
.major = S3C24XX_SERIAL_MAJOR,
.minor = S3C24XX_SERIAL_MINOR,
@@ -982,10 +1045,10 @@ static int s3c24xx_serial_cpufreq_transition(struct notifier_block *nb,
* a disturbance in the clock-rate over the change.
*/
- if (IS_ERR(port->clk))
+ if (IS_ERR_OR_NULL(port->baudclk))
goto exit;
- if (port->baudclk_rate == clk_get_rate(port->clk))
+ if (port->baudclk_rate == clk_get_rate(port->baudclk))
goto exit;
if (val == CPUFREQ_PRECHANGE) {
@@ -1109,7 +1172,7 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
ourport->rx_irq = ret;
ourport->tx_irq = ret + 1;
}
-
+
ret = platform_get_irq(platdev, 1);
if (ret > 0)
ourport->tx_irq = ret;
@@ -1132,7 +1195,8 @@ static ssize_t s3c24xx_serial_show_clksrc(struct device *dev,
struct uart_port *port = s3c24xx_dev_to_port(dev);
struct s3c24xx_uart_port *ourport = to_ourport(port);
- return snprintf(buf, PAGE_SIZE, "* %s\n", ourport->clksrc->name);
+ return snprintf(buf, PAGE_SIZE, "* %s\n",
+ ourport->clksrc ? ourport->clksrc->name : "(null)");
}
static DEVICE_ATTR(clock_source, S_IRUGO, s3c24xx_serial_show_clksrc, NULL);
@@ -1244,7 +1308,10 @@ EXPORT_SYMBOL_GPL(s3c24xx_serial_init);
static int __init s3c24xx_serial_modinit(void)
{
int ret;
-
+#ifdef CONFIG_SERIAL_SAMSUNG_CONSOLE_SWITCH
+ if (uart_debug)
+ s3c24xx_uart_drv.cons = S3C24XX_SERIAL_CONSOLE;
+#endif
ret = uart_register_driver(&s3c24xx_uart_drv);
if (ret < 0) {
printk(KERN_ERR "failed to register UART driver\n");
@@ -1307,7 +1374,7 @@ static void __init
s3c24xx_serial_get_options(struct uart_port *port, int *baud,
int *parity, int *bits)
{
- struct s3c24xx_uart_clksrc clksrc;
+ struct s3c24xx_uart_clksrc clksrc = { "", 0, };
struct clk *clk;
unsigned int ulcon;
unsigned int ucon;
@@ -1365,7 +1432,6 @@ s3c24xx_serial_get_options(struct uart_port *port, int *baud,
else
rate = 1;
-
*baud = rate / (16 * (ubrdiv + 1));
dbg("calculated baud %d\n", *baud);
}
@@ -1416,10 +1482,8 @@ s3c24xx_serial_console_setup(struct console *co, char *options)
/* is the port configured? */
- if (port->mapbase == 0x0) {
- co->index = 0;
- port = &s3c24xx_serial_ports[co->index].port;
- }
+ if (port->mapbase == 0x0)
+ return -ENODEV;
cons_uart = port;
@@ -1451,7 +1515,8 @@ static struct console s3c24xx_serial_console = {
.flags = CON_PRINTBUFFER,
.index = -1,
.write = s3c24xx_serial_console_write,
- .setup = s3c24xx_serial_console_setup
+ .setup = s3c24xx_serial_console_setup,
+ .data = &s3c24xx_uart_drv,
};
int s3c24xx_serial_initconsole(struct platform_driver *drv,