From 5425e03f97d1e5847372aae0b895d8d1c9bf2741 Mon Sep 17 00:00:00 2001 From: Barry Song Date: Tue, 25 Dec 2012 17:32:04 +0800 Subject: serial: sirf: add support for new SiRFmarco SMP SoC CSR SiRFmarco's UART IP is same with SiRFprimaII except that it has two more uart ports. this patch makes the old driver support new SiRFmarco as well: 1. add .compatible = "sirf,marco-uart" to OF match table 2. add two ports in the port table 3. take spin_lock in isr to avoid the conflict of threads opening uart on CPU1 and isr running on CPU0. For 3, we did see some problems on SiRFmarco as SiRFmarco is a SMP SoC but the old SiRFprimaII is UP. Signed-off-by: Barry Song Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/sirfsoc_uart.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/tty/serial/sirfsoc_uart.h') diff --git a/drivers/tty/serial/sirfsoc_uart.h b/drivers/tty/serial/sirfsoc_uart.h index 6e207fdc2fe..6431640c316 100644 --- a/drivers/tty/serial/sirfsoc_uart.h +++ b/drivers/tty/serial/sirfsoc_uart.h @@ -139,7 +139,7 @@ #define SIRFSOC_UART_MINOR 0 #define SIRFUART_PORT_NAME "sirfsoc-uart" #define SIRFUART_MAP_SIZE 0x200 -#define SIRFSOC_UART_NR 3 +#define SIRFSOC_UART_NR 5 #define SIRFSOC_PORT_TYPE 0xa5 /* Baud Rate Calculation */ -- cgit v1.2.3-70-g09d2 From ac4ce718893c546f7a2d34ab55a8f75842399f86 Mon Sep 17 00:00:00 2001 From: Barry Song Date: Wed, 16 Jan 2013 14:49:27 +0800 Subject: serial: sirf: only use lookup table to set baudrate when ioclk=150MHz The fast lookup table to set baudrate is only right when ioclk is 150MHz. for most platforms, ioclk is 150MHz, but some boards might set ioclk to other frequency. so re-calc the clk_div_reg when ioclk is not 150MHz. this patch also gets clk in probe and puts it in remove. Signed-off-by: Barry Song Cc: Russell King Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/sirfsoc_uart.c | 28 +++++++++++++++++++++------- drivers/tty/serial/sirfsoc_uart.h | 1 + 2 files changed, 22 insertions(+), 7 deletions(-) (limited to 'drivers/tty/serial/sirfsoc_uart.h') diff --git a/drivers/tty/serial/sirfsoc_uart.c b/drivers/tty/serial/sirfsoc_uart.c index 8f3d6c091ac..6bbfe9934a4 100644 --- a/drivers/tty/serial/sirfsoc_uart.c +++ b/drivers/tty/serial/sirfsoc_uart.c @@ -357,7 +357,6 @@ static void sirfsoc_uart_set_termios(struct uart_port *port, struct ktermios *old) { struct sirfsoc_uart_port *sirfport = to_sirfport(port); - unsigned long ioclk_rate; unsigned long config_reg = 0; unsigned long baud_rate; unsigned long setted_baud; @@ -369,7 +368,6 @@ static void sirfsoc_uart_set_termios(struct uart_port *port, int threshold_div; int temp; - ioclk_rate = 150000000; switch (termios->c_cflag & CSIZE) { default: case CS8: @@ -425,14 +423,17 @@ static void sirfsoc_uart_set_termios(struct uart_port *port, sirfsoc_uart_disable_ms(port); } - /* common rate: fast calculation */ - for (ic = 0; ic < SIRF_BAUD_RATE_SUPPORT_NR; ic++) - if (baud_rate == baudrate_to_regv[ic].baud_rate) - clk_div_reg = baudrate_to_regv[ic].reg_val; + if (port->uartclk == 150000000) { + /* common rate: fast calculation */ + for (ic = 0; ic < SIRF_BAUD_RATE_SUPPORT_NR; ic++) + if (baud_rate == baudrate_to_regv[ic].baud_rate) + clk_div_reg = baudrate_to_regv[ic].reg_val; + } + setted_baud = baud_rate; /* arbitary rate setting */ if (unlikely(clk_div_reg == 0)) - clk_div_reg = sirfsoc_calc_sample_div(baud_rate, ioclk_rate, + clk_div_reg = sirfsoc_calc_sample_div(baud_rate, port->uartclk, &setted_baud); wr_regl(port, SIRFUART_DIVISOR, clk_div_reg); @@ -691,6 +692,14 @@ int sirfsoc_uart_probe(struct platform_device *pdev) goto err; } + sirfport->clk = clk_get(&pdev->dev, NULL); + if (IS_ERR(sirfport->clk)) { + ret = PTR_ERR(sirfport->clk); + goto clk_err; + } + clk_prepare_enable(sirfport->clk); + port->uartclk = clk_get_rate(sirfport->clk); + port->ops = &sirfsoc_uart_ops; spin_lock_init(&port->lock); @@ -704,6 +713,9 @@ int sirfsoc_uart_probe(struct platform_device *pdev) return 0; port_err: + clk_disable_unprepare(sirfport->clk); + clk_put(sirfport->clk); +clk_err: platform_set_drvdata(pdev, NULL); if (sirfport->hw_flow_ctrl) pinctrl_put(sirfport->p); @@ -718,6 +730,8 @@ static int sirfsoc_uart_remove(struct platform_device *pdev) platform_set_drvdata(pdev, NULL); if (sirfport->hw_flow_ctrl) pinctrl_put(sirfport->p); + clk_disable_unprepare(sirfport->clk); + clk_put(sirfport->clk); uart_remove_one_port(&sirfsoc_uart_drv, port); return 0; } diff --git a/drivers/tty/serial/sirfsoc_uart.h b/drivers/tty/serial/sirfsoc_uart.h index 6431640c316..85328ba0c4e 100644 --- a/drivers/tty/serial/sirfsoc_uart.h +++ b/drivers/tty/serial/sirfsoc_uart.h @@ -163,6 +163,7 @@ struct sirfsoc_uart_port { struct uart_port port; struct pinctrl *p; + struct clk *clk; }; /* Hardware Flow Control */ -- cgit v1.2.3-70-g09d2