summaryrefslogtreecommitdiff
path: root/drivers/tty/serial/8250/8250_mtk.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/tty/serial/8250/8250_mtk.c')
-rw-r--r--drivers/tty/serial/8250/8250_mtk.c119
1 files changed, 53 insertions, 66 deletions
diff --git a/drivers/tty/serial/8250/8250_mtk.c b/drivers/tty/serial/8250/8250_mtk.c
index fb65dc601b23..5875a7b9b4b1 100644
--- a/drivers/tty/serial/8250/8250_mtk.c
+++ b/drivers/tty/serial/8250/8250_mtk.c
@@ -37,6 +37,7 @@
#define MTK_UART_IER_RTSI 0x40 /* Enable RTS Modem status interrupt */
#define MTK_UART_IER_CTSI 0x80 /* Enable CTS Modem status interrupt */
+#define MTK_UART_EFR 38 /* I/O: Extended Features Register */
#define MTK_UART_EFR_EN 0x10 /* Enable enhancement feature */
#define MTK_UART_EFR_RTS 0x40 /* Enable hardware rx flow control */
#define MTK_UART_EFR_CTS 0x80 /* Enable hardware tx flow control */
@@ -53,6 +54,9 @@
#define MTK_UART_TX_TRIGGER 1
#define MTK_UART_RX_TRIGGER MTK_UART_RX_SIZE
+#define MTK_UART_XON1 40 /* I/O: Xon character 1 */
+#define MTK_UART_XOFF1 42 /* I/O: Xoff character 1 */
+
#ifdef CONFIG_SERIAL_8250_DMA
enum dma_rx_status {
DMA_RX_START = 0,
@@ -98,7 +102,7 @@ static void mtk8250_dma_rx_complete(void *param)
if (data->rx_status == DMA_RX_SHUTDOWN)
return;
- spin_lock_irqsave(&up->port.lock, flags);
+ uart_port_lock_irqsave(&up->port, &flags);
dmaengine_tx_status(dma->rxchan, dma->rx_cookie, &state);
total = dma->rx_size - state.residue;
@@ -124,7 +128,7 @@ static void mtk8250_dma_rx_complete(void *param)
mtk8250_rx_dma(up);
- spin_unlock_irqrestore(&up->port.lock, flags);
+ uart_port_unlock_irqrestore(&up->port, flags);
}
static void mtk8250_rx_dma(struct uart_8250_port *up)
@@ -169,7 +173,7 @@ static void mtk8250_dma_enable(struct uart_8250_port *up)
MTK_UART_DMA_EN_RX | MTK_UART_DMA_EN_TX);
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
- serial_out(up, UART_EFR, UART_EFR_ECB);
+ serial_out(up, MTK_UART_EFR, UART_EFR_ECB);
serial_out(up, UART_LCR, lcr);
if (dmaengine_slave_config(dma->rxchan, &dma->rxconf) != 0)
@@ -195,7 +199,7 @@ static int mtk8250_startup(struct uart_port *port)
if (up->dma) {
data->rx_status = DMA_RX_START;
- uart_circ_clear(&port->state->xmit);
+ kfifo_reset(&port->state->port.xmit_fifo);
}
#endif
memset(&port->icount, 0, sizeof(port->icount));
@@ -205,24 +209,34 @@ static int mtk8250_startup(struct uart_port *port)
static void mtk8250_shutdown(struct uart_port *port)
{
-#ifdef CONFIG_SERIAL_8250_DMA
struct uart_8250_port *up = up_to_u8250p(port);
struct mtk8250_data *data = port->private_data;
+ int irq = data->rx_wakeup_irq;
+#ifdef CONFIG_SERIAL_8250_DMA
if (up->dma)
data->rx_status = DMA_RX_SHUTDOWN;
#endif
- return serial8250_do_shutdown(port);
+ serial8250_do_shutdown(port);
+
+ if (irq >= 0)
+ serial8250_do_set_mctrl(&up->port, TIOCM_RTS);
}
static void mtk8250_disable_intrs(struct uart_8250_port *up, int mask)
{
+ /* Port locked to synchronize UART_IER access against the console. */
+ lockdep_assert_held_once(&up->port.lock);
+
serial_out(up, UART_IER, serial_in(up, UART_IER) & (~mask));
}
static void mtk8250_enable_intrs(struct uart_8250_port *up, int mask)
{
+ /* Port locked to synchronize UART_IER access against the console. */
+ lockdep_assert_held_once(&up->port.lock);
+
serial_out(up, UART_IER, serial_in(up, UART_IER) | mask);
}
@@ -231,8 +245,11 @@ static void mtk8250_set_flow_ctrl(struct uart_8250_port *up, int mode)
struct uart_port *port = &up->port;
int lcr = serial_in(up, UART_LCR);
+ /* Port locked to synchronize UART_IER access against the console. */
+ lockdep_assert_held_once(&port->lock);
+
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
- serial_out(up, UART_EFR, UART_EFR_ECB);
+ serial_out(up, MTK_UART_EFR, UART_EFR_ECB);
serial_out(up, UART_LCR, lcr);
lcr = serial_in(up, UART_LCR);
@@ -241,7 +258,7 @@ static void mtk8250_set_flow_ctrl(struct uart_8250_port *up, int mode)
serial_out(up, MTK_UART_ESCAPE_DAT, MTK_UART_ESCAPE_CHAR);
serial_out(up, MTK_UART_ESCAPE_EN, 0x00);
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
- serial_out(up, UART_EFR, serial_in(up, UART_EFR) &
+ serial_out(up, MTK_UART_EFR, serial_in(up, MTK_UART_EFR) &
(~(MTK_UART_EFR_HW_FC | MTK_UART_EFR_SW_FC_MASK)));
serial_out(up, UART_LCR, lcr);
mtk8250_disable_intrs(up, MTK_UART_IER_XOFFI |
@@ -255,8 +272,8 @@ static void mtk8250_set_flow_ctrl(struct uart_8250_port *up, int mode)
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
/*enable hw flow control*/
- serial_out(up, UART_EFR, MTK_UART_EFR_HW_FC |
- (serial_in(up, UART_EFR) &
+ serial_out(up, MTK_UART_EFR, MTK_UART_EFR_HW_FC |
+ (serial_in(up, MTK_UART_EFR) &
(~(MTK_UART_EFR_HW_FC | MTK_UART_EFR_SW_FC_MASK))));
serial_out(up, UART_LCR, lcr);
@@ -270,12 +287,12 @@ static void mtk8250_set_flow_ctrl(struct uart_8250_port *up, int mode)
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
/*enable sw flow control */
- serial_out(up, UART_EFR, MTK_UART_EFR_XON1_XOFF1 |
- (serial_in(up, UART_EFR) &
+ serial_out(up, MTK_UART_EFR, MTK_UART_EFR_XON1_XOFF1 |
+ (serial_in(up, MTK_UART_EFR) &
(~(MTK_UART_EFR_HW_FC | MTK_UART_EFR_SW_FC_MASK))));
- serial_out(up, UART_XON1, START_CHAR(port->state->port.tty));
- serial_out(up, UART_XOFF1, STOP_CHAR(port->state->port.tty));
+ serial_out(up, MTK_UART_XON1, START_CHAR(port->state->port.tty));
+ serial_out(up, MTK_UART_XOFF1, STOP_CHAR(port->state->port.tty));
serial_out(up, UART_LCR, lcr);
mtk8250_disable_intrs(up, MTK_UART_IER_CTSI|MTK_UART_IER_RTSI);
mtk8250_enable_intrs(up, MTK_UART_IER_XOFFI);
@@ -287,12 +304,12 @@ static void mtk8250_set_flow_ctrl(struct uart_8250_port *up, int mode)
static void
mtk8250_set_termios(struct uart_port *port, struct ktermios *termios,
- struct ktermios *old)
+ const struct ktermios *old)
{
- unsigned short fraction_L_mapping[] = {
+ static const unsigned short fraction_L_mapping[] = {
0, 1, 0x5, 0x15, 0x55, 0x57, 0x57, 0x77, 0x7F, 0xFF, 0xFF
};
- unsigned short fraction_M_mapping[] = {
+ static const unsigned short fraction_M_mapping[] = {
0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 3
};
struct uart_8250_port *up = up_to_u8250p(port);
@@ -329,8 +346,8 @@ mtk8250_set_termios(struct uart_port *port, struct ktermios *termios,
/*
* Mediatek UARTs use an extra highspeed register (MTK_UART_HIGHS)
*
- * We need to recalcualte the quot register, as the claculation depends
- * on the vaule in the highspeed register.
+ * We need to recalculate the quot register, as the calculation depends
+ * on the value in the highspeed register.
*
* Some baudrates are not supported by the chip, so we use the next
* lower rate supported and update termios c_flag.
@@ -355,7 +372,7 @@ mtk8250_set_termios(struct uart_port *port, struct ktermios *termios,
* Ok, we're now changing the port state. Do it with
* interrupts disabled.
*/
- spin_lock_irqsave(&port->lock, flags);
+ uart_port_lock_irqsave(port, &flags);
/*
* Update the per-port timeout.
@@ -403,7 +420,7 @@ mtk8250_set_termios(struct uart_port *port, struct ktermios *termios,
if (uart_console(port))
up->port.cons->cflag = termios->c_cflag;
- spin_unlock_irqrestore(&port->lock, flags);
+ uart_port_unlock_irqrestore(port, flags);
/* Don't rewrite B0 */
if (tty_termios_baud_rate(termios))
tty_termios_encode_baud_rate(termios, baud, baud);
@@ -418,12 +435,8 @@ static int __maybe_unused mtk8250_runtime_suspend(struct device *dev)
while
(serial_in(up, MTK_UART_DEBUG0));
- if (data->clk_count == 0U) {
- dev_dbg(dev, "%s clock count is 0\n", __func__);
- } else {
- clk_disable_unprepare(data->bus_clk);
- data->clk_count--;
- }
+ clk_disable_unprepare(data->uart_clk);
+ clk_disable_unprepare(data->bus_clk);
return 0;
}
@@ -431,19 +444,9 @@ static int __maybe_unused mtk8250_runtime_suspend(struct device *dev)
static int __maybe_unused mtk8250_runtime_resume(struct device *dev)
{
struct mtk8250_data *data = dev_get_drvdata(dev);
- int err;
- if (data->clk_count > 0U) {
- dev_dbg(dev, "%s clock count is %d\n", __func__,
- data->clk_count);
- } else {
- err = clk_prepare_enable(data->bus_clk);
- if (err) {
- dev_warn(dev, "Can't enable bus clock\n");
- return err;
- }
- data->clk_count++;
- }
+ clk_prepare_enable(data->bus_clk);
+ clk_prepare_enable(data->uart_clk);
return 0;
}
@@ -452,14 +455,12 @@ static void
mtk8250_do_pm(struct uart_port *port, unsigned int state, unsigned int old)
{
if (!state)
- if (!mtk8250_runtime_resume(port->dev))
- pm_runtime_get_sync(port->dev);
+ pm_runtime_get_sync(port->dev);
serial8250_do_pm(port, state, old);
if (state)
- if (!pm_runtime_put_sync_suspend(port->dev))
- mtk8250_runtime_suspend(port->dev);
+ pm_runtime_put_sync_suspend(port->dev);
}
#ifdef CONFIG_SERIAL_8250_DMA
@@ -476,13 +477,13 @@ static int mtk8250_probe_of(struct platform_device *pdev, struct uart_port *p,
int dmacnt;
#endif
- data->uart_clk = devm_clk_get(&pdev->dev, "baud");
+ data->uart_clk = devm_clk_get_enabled(&pdev->dev, "baud");
if (IS_ERR(data->uart_clk)) {
/*
* For compatibility with older device trees try unnamed
* clk when no baud clk can be found.
*/
- data->uart_clk = devm_clk_get(&pdev->dev, NULL);
+ data->uart_clk = devm_clk_get_enabled(&pdev->dev, NULL);
if (IS_ERR(data->uart_clk)) {
dev_warn(&pdev->dev, "Can't get uart clock\n");
return PTR_ERR(data->uart_clk);
@@ -491,7 +492,7 @@ static int mtk8250_probe_of(struct platform_device *pdev, struct uart_port *p,
return 0;
}
- data->bus_clk = devm_clk_get(&pdev->dev, "bus");
+ data->bus_clk = devm_clk_get_enabled(&pdev->dev, "bus");
if (IS_ERR(data->bus_clk))
return PTR_ERR(data->bus_clk);
@@ -574,28 +575,19 @@ static int mtk8250_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, data);
- pm_runtime_enable(&pdev->dev);
- err = mtk8250_runtime_resume(&pdev->dev);
- if (err)
- goto err_pm_disable;
-
data->line = serial8250_register_8250_port(&uart);
- if (data->line < 0) {
- err = data->line;
- goto err_pm_disable;
- }
+ if (data->line < 0)
+ return data->line;
data->rx_wakeup_irq = platform_get_irq_optional(pdev, 1);
- return 0;
-
-err_pm_disable:
- pm_runtime_disable(&pdev->dev);
+ pm_runtime_set_active(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
- return err;
+ return 0;
}
-static int mtk8250_remove(struct platform_device *pdev)
+static void mtk8250_remove(struct platform_device *pdev)
{
struct mtk8250_data *data = platform_get_drvdata(pdev);
@@ -605,11 +597,6 @@ static int mtk8250_remove(struct platform_device *pdev)
pm_runtime_disable(&pdev->dev);
pm_runtime_put_noidle(&pdev->dev);
-
- if (!pm_runtime_status_suspended(&pdev->dev))
- mtk8250_runtime_suspend(&pdev->dev);
-
- return 0;
}
static int __maybe_unused mtk8250_suspend(struct device *dev)