Update Linux to v5.4.2
Change-Id: Idf6911045d9d382da2cfe01b1edff026404ac8fd
diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c
index e8d7a7b..df90747 100644
--- a/drivers/tty/serial/stm32-usart.c
+++ b/drivers/tty/serial/stm32-usart.c
@@ -24,6 +24,7 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_platform.h>
+#include <linux/pinctrl/consumer.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/pm_wakeirq.h>
@@ -105,9 +106,7 @@
struct stm32_usart_config *cfg = &stm32_port->info->cfg;
u32 usartdiv, baud, cr1, cr3;
bool over8;
- unsigned long flags;
- spin_lock_irqsave(&port->lock, flags);
stm32_clr_bits(port, ofs->cr1, BIT(cfg->uart_enable_bit));
port->rs485 = *rs485conf;
@@ -147,7 +146,6 @@
}
stm32_set_bits(port, ofs->cr1, BIT(cfg->uart_enable_bit));
- spin_unlock_irqrestore(&port->lock, flags);
return 0;
}
@@ -194,8 +192,8 @@
return 0;
}
-static unsigned long
-stm32_get_char(struct uart_port *port, u32 *sr, int *last_res)
+static unsigned long stm32_get_char(struct uart_port *port, u32 *sr,
+ int *last_res)
{
struct stm32_port *stm32_port = to_stm32_port(port);
struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
@@ -205,10 +203,13 @@
c = stm32_port->rx_buf[RX_BUF_L - (*last_res)--];
if ((*last_res) == 0)
*last_res = RX_BUF_L;
- return c;
} else {
- return readl_relaxed(port->membase + ofs->rdr);
+ c = readl_relaxed(port->membase + ofs->rdr);
+ /* apply RDR data mask */
+ c &= stm32_port->rdr_mask;
}
+
+ return c;
}
static void stm32_receive_chars(struct uart_port *port, bool threaded)
@@ -225,35 +226,51 @@
while (stm32_pending_rx(port, &sr, &stm32_port->last_res, threaded)) {
sr |= USART_SR_DUMMY_RX;
- c = stm32_get_char(port, &sr, &stm32_port->last_res);
flag = TTY_NORMAL;
- port->icount.rx++;
+ /*
+ * Status bits has to be cleared before reading the RDR:
+ * In FIFO mode, reading the RDR will pop the next data
+ * (if any) along with its status bits into the SR.
+ * Not doing so leads to misalignement between RDR and SR,
+ * and clear status bits of the next rx data.
+ *
+ * Clear errors flags for stm32f7 and stm32h7 compatible
+ * devices. On stm32f4 compatible devices, the error bit is
+ * cleared by the sequence [read SR - read DR].
+ */
+ if ((sr & USART_SR_ERR_MASK) && ofs->icr != UNDEF_REG)
+ stm32_clr_bits(port, ofs->icr, USART_ICR_ORECF |
+ USART_ICR_PECF | USART_ICR_FECF);
+
+ c = stm32_get_char(port, &sr, &stm32_port->last_res);
+ port->icount.rx++;
if (sr & USART_SR_ERR_MASK) {
- if (sr & USART_SR_LBD) {
- port->icount.brk++;
- if (uart_handle_break(port))
- continue;
- } else if (sr & USART_SR_ORE) {
- if (ofs->icr != UNDEF_REG)
- writel_relaxed(USART_ICR_ORECF,
- port->membase +
- ofs->icr);
+ if (sr & USART_SR_ORE) {
port->icount.overrun++;
} else if (sr & USART_SR_PE) {
port->icount.parity++;
} else if (sr & USART_SR_FE) {
- port->icount.frame++;
+ /* Break detection if character is null */
+ if (!c) {
+ port->icount.brk++;
+ if (uart_handle_break(port))
+ continue;
+ } else {
+ port->icount.frame++;
+ }
}
sr &= port->read_status_mask;
- if (sr & USART_SR_LBD)
- flag = TTY_BREAK;
- else if (sr & USART_SR_PE)
+ if (sr & USART_SR_PE) {
flag = TTY_PARITY;
- else if (sr & USART_SR_FE)
- flag = TTY_FRAME;
+ } else if (sr & USART_SR_FE) {
+ if (!c)
+ flag = TTY_BREAK;
+ else
+ flag = TTY_FRAME;
+ }
}
if (uart_handle_sysrq_char(port, c))
@@ -271,21 +288,6 @@
struct uart_port *port = arg;
struct stm32_port *stm32port = to_stm32_port(port);
struct stm32_usart_offsets *ofs = &stm32port->info->ofs;
- unsigned int isr;
- int ret;
-
- ret = readl_relaxed_poll_timeout_atomic(port->membase + ofs->isr,
- isr,
- (isr & USART_SR_TC),
- 10, 100000);
-
- if (ret)
- dev_err(port->dev, "terminal count not set\n");
-
- if (ofs->icr == UNDEF_REG)
- stm32_clr_bits(port, ofs->isr, USART_SR_TC);
- else
- stm32_set_bits(port, ofs->icr, USART_CR_TC);
stm32_clr_bits(port, ofs->cr3, USART_CR3_DMAT);
stm32port->tx_dma_busy = false;
@@ -294,32 +296,57 @@
stm32_transmit_chars(port);
}
+static void stm32_tx_interrupt_enable(struct uart_port *port)
+{
+ struct stm32_port *stm32_port = to_stm32_port(port);
+ struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
+
+ /*
+ * Enables TX FIFO threashold irq when FIFO is enabled,
+ * or TX empty irq when FIFO is disabled
+ */
+ if (stm32_port->fifoen)
+ stm32_set_bits(port, ofs->cr3, USART_CR3_TXFTIE);
+ else
+ stm32_set_bits(port, ofs->cr1, USART_CR1_TXEIE);
+}
+
+static void stm32_tx_interrupt_disable(struct uart_port *port)
+{
+ struct stm32_port *stm32_port = to_stm32_port(port);
+ struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
+
+ if (stm32_port->fifoen)
+ stm32_clr_bits(port, ofs->cr3, USART_CR3_TXFTIE);
+ else
+ stm32_clr_bits(port, ofs->cr1, USART_CR1_TXEIE);
+}
+
static void stm32_transmit_chars_pio(struct uart_port *port)
{
struct stm32_port *stm32_port = to_stm32_port(port);
struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
struct circ_buf *xmit = &port->state->xmit;
- unsigned int isr;
- int ret;
if (stm32_port->tx_dma_busy) {
stm32_clr_bits(port, ofs->cr3, USART_CR3_DMAT);
stm32_port->tx_dma_busy = false;
}
- ret = readl_relaxed_poll_timeout_atomic(port->membase + ofs->isr,
- isr,
- (isr & USART_SR_TXE),
- 10, 100000);
+ while (!uart_circ_empty(xmit)) {
+ /* Check that TDR is empty before filling FIFO */
+ if (!(readl_relaxed(port->membase + ofs->isr) & USART_SR_TXE))
+ break;
+ writel_relaxed(xmit->buf[xmit->tail], port->membase + ofs->tdr);
+ xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+ port->icount.tx++;
+ }
- if (ret)
- dev_err(port->dev, "tx empty not set\n");
-
- stm32_set_bits(port, ofs->cr1, USART_CR1_TXEIE);
-
- writel_relaxed(xmit->buf[xmit->tail], port->membase + ofs->tdr);
- xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
- port->icount.tx++;
+ /* rely on TXE irq (mask or unmask) for sending remaining data */
+ if (uart_circ_empty(xmit))
+ stm32_tx_interrupt_disable(port);
+ else
+ stm32_tx_interrupt_enable(port);
}
static void stm32_transmit_chars_dma(struct uart_port *port)
@@ -377,7 +404,6 @@
/* Issue pending DMA TX requests */
dma_async_issue_pending(stm32port->tx_ch);
- stm32_clr_bits(port, ofs->isr, USART_SR_TC);
stm32_set_bits(port, ofs->cr3, USART_CR3_DMAT);
xmit->tail = (xmit->tail + count) & (UART_XMIT_SIZE - 1);
@@ -401,15 +427,15 @@
return;
}
- if (uart_tx_stopped(port)) {
- stm32_stop_tx(port);
+ if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
+ stm32_tx_interrupt_disable(port);
return;
}
- if (uart_circ_empty(xmit)) {
- stm32_stop_tx(port);
- return;
- }
+ if (ofs->icr == UNDEF_REG)
+ stm32_clr_bits(port, ofs->isr, USART_SR_TC);
+ else
+ stm32_set_bits(port, ofs->icr, USART_ICR_TCCF);
if (stm32_port->tx_ch)
stm32_transmit_chars_dma(port);
@@ -420,7 +446,7 @@
uart_write_wakeup(port);
if (uart_circ_empty(xmit))
- stm32_stop_tx(port);
+ stm32_tx_interrupt_disable(port);
}
static irqreturn_t stm32_interrupt(int irq, void *ptr)
@@ -434,6 +460,10 @@
sr = readl_relaxed(port->membase + ofs->isr);
+ if ((sr & USART_SR_RTOF) && ofs->icr != UNDEF_REG)
+ writel_relaxed(USART_ICR_RTOCF,
+ port->membase + ofs->icr);
+
if ((sr & USART_SR_WUF) && (ofs->icr != UNDEF_REG))
writel_relaxed(USART_ICR_WUCF,
port->membase + ofs->icr);
@@ -495,10 +525,7 @@
/* Transmit stop */
static void stm32_stop_tx(struct uart_port *port)
{
- struct stm32_port *stm32_port = to_stm32_port(port);
- struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
-
- stm32_clr_bits(port, ofs->cr1, USART_CR1_TXEIE);
+ stm32_tx_interrupt_disable(port);
}
/* There are probably characters waiting to be transmitted. */
@@ -520,7 +547,10 @@
unsigned long flags;
spin_lock_irqsave(&port->lock, flags);
- stm32_clr_bits(port, ofs->cr1, USART_CR1_RXNEIE);
+ stm32_clr_bits(port, ofs->cr1, stm32_port->cr1_irq);
+ if (stm32_port->cr3_irq)
+ stm32_clr_bits(port, ofs->cr3, stm32_port->cr3_irq);
+
spin_unlock_irqrestore(&port->lock, flags);
}
@@ -532,7 +562,10 @@
unsigned long flags;
spin_lock_irqsave(&port->lock, flags);
- stm32_set_bits(port, ofs->cr1, USART_CR1_RXNEIE);
+ stm32_set_bits(port, ofs->cr1, stm32_port->cr1_irq);
+ if (stm32_port->cr3_irq)
+ stm32_set_bits(port, ofs->cr3, stm32_port->cr3_irq);
+
spin_unlock_irqrestore(&port->lock, flags);
}
@@ -542,7 +575,10 @@
struct stm32_port *stm32_port = to_stm32_port(port);
struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
- stm32_clr_bits(port, ofs->cr1, USART_CR1_RXNEIE);
+ stm32_clr_bits(port, ofs->cr1, stm32_port->cr1_irq);
+ if (stm32_port->cr3_irq)
+ stm32_clr_bits(port, ofs->cr3, stm32_port->cr3_irq);
+
}
/* Handle breaks - ignored by us */
@@ -554,7 +590,6 @@
{
struct stm32_port *stm32_port = to_stm32_port(port);
struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
- struct stm32_usart_config *cfg = &stm32_port->info->cfg;
const char *name = to_platform_device(port->dev)->name;
u32 val;
int ret;
@@ -565,16 +600,21 @@
if (ret)
return ret;
- if (cfg->has_wakeup && stm32_port->wakeirq >= 0) {
- ret = dev_pm_set_dedicated_wake_irq(port->dev,
- stm32_port->wakeirq);
- if (ret) {
- free_irq(port->irq, port);
- return ret;
- }
+ /* RX FIFO Flush */
+ if (ofs->rqr != UNDEF_REG)
+ stm32_set_bits(port, ofs->rqr, USART_RQR_RXFRQ);
+
+ /* Tx and RX FIFO configuration */
+ if (stm32_port->fifoen) {
+ val = readl_relaxed(port->membase + ofs->cr3);
+ val &= ~(USART_CR3_TXFTCFG_MASK | USART_CR3_RXFTCFG_MASK);
+ val |= USART_CR3_TXFTCFG_HALF << USART_CR3_TXFTCFG_SHIFT;
+ val |= USART_CR3_RXFTCFG_HALF << USART_CR3_RXFTCFG_SHIFT;
+ writel_relaxed(val, port->membase + ofs->cr3);
}
- val = USART_CR1_RXNEIE | USART_CR1_TE | USART_CR1_RE;
+ /* RX FIFO enabling */
+ val = stm32_port->cr1_irq | USART_CR1_RE;
if (stm32_port->fifoen)
val |= USART_CR1_FIFOEN;
stm32_set_bits(port, ofs->cr1, val);
@@ -587,18 +627,57 @@
struct stm32_port *stm32_port = to_stm32_port(port);
struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
struct stm32_usart_config *cfg = &stm32_port->info->cfg;
- u32 val;
+ u32 val, isr;
+ int ret;
- val = USART_CR1_TXEIE | USART_CR1_RXNEIE | USART_CR1_TE | USART_CR1_RE;
+ val = USART_CR1_TXEIE | USART_CR1_TE;
+ val |= stm32_port->cr1_irq | USART_CR1_RE;
val |= BIT(cfg->uart_enable_bit);
if (stm32_port->fifoen)
val |= USART_CR1_FIFOEN;
+
+ ret = readl_relaxed_poll_timeout(port->membase + ofs->isr,
+ isr, (isr & USART_SR_TC),
+ 10, 100000);
+
+ if (ret)
+ dev_err(port->dev, "transmission complete not set\n");
+
stm32_clr_bits(port, ofs->cr1, val);
- dev_pm_clear_wake_irq(port->dev);
free_irq(port->irq, port);
}
+static unsigned int stm32_get_databits(struct ktermios *termios)
+{
+ unsigned int bits;
+
+ tcflag_t cflag = termios->c_cflag;
+
+ switch (cflag & CSIZE) {
+ /*
+ * CSIZE settings are not necessarily supported in hardware.
+ * CSIZE unsupported configurations are handled here to set word length
+ * to 8 bits word as default configuration and to print debug message.
+ */
+ case CS5:
+ bits = 5;
+ break;
+ case CS6:
+ bits = 6;
+ break;
+ case CS7:
+ bits = 7;
+ break;
+ /* default including CS8 */
+ default:
+ bits = 8;
+ break;
+ }
+
+ return bits;
+}
+
static void stm32_set_termios(struct uart_port *port, struct ktermios *termios,
struct ktermios *old)
{
@@ -606,7 +685,7 @@
struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
struct stm32_usart_config *cfg = &stm32_port->info->cfg;
struct serial_rs485 *rs485conf = &port->rs485;
- unsigned int baud;
+ unsigned int baud, bits;
u32 usartdiv, mantissa, fraction, oversampling;
tcflag_t cflag = termios->c_cflag;
u32 cr1, cr2, cr3;
@@ -622,26 +701,64 @@
/* Stop serial port and reset value */
writel_relaxed(0, port->membase + ofs->cr1);
- cr1 = USART_CR1_TE | USART_CR1_RE | USART_CR1_RXNEIE;
+ /* flush RX & TX FIFO */
+ if (ofs->rqr != UNDEF_REG)
+ stm32_set_bits(port, ofs->rqr,
+ USART_RQR_TXFRQ | USART_RQR_RXFRQ);
+ cr1 = USART_CR1_TE | USART_CR1_RE;
if (stm32_port->fifoen)
cr1 |= USART_CR1_FIFOEN;
cr2 = 0;
- cr3 = 0;
+ cr3 = readl_relaxed(port->membase + ofs->cr3);
+ cr3 &= USART_CR3_TXFTIE | USART_CR3_RXFTCFG_MASK | USART_CR3_RXFTIE
+ | USART_CR3_TXFTCFG_MASK;
if (cflag & CSTOPB)
cr2 |= USART_CR2_STOP_2B;
+ bits = stm32_get_databits(termios);
+ stm32_port->rdr_mask = (BIT(bits) - 1);
+
if (cflag & PARENB) {
+ bits++;
cr1 |= USART_CR1_PCE;
- if ((cflag & CSIZE) == CS8) {
- if (cfg->has_7bits_data)
- cr1 |= USART_CR1_M0;
- else
- cr1 |= USART_CR1_M;
- }
}
+ /*
+ * Word length configuration:
+ * CS8 + parity, 9 bits word aka [M1:M0] = 0b01
+ * CS7 or (CS6 + parity), 7 bits word aka [M1:M0] = 0b10
+ * CS8 or (CS7 + parity), 8 bits word aka [M1:M0] = 0b00
+ * M0 and M1 already cleared by cr1 initialization.
+ */
+ if (bits == 9)
+ cr1 |= USART_CR1_M0;
+ else if ((bits == 7) && cfg->has_7bits_data)
+ cr1 |= USART_CR1_M1;
+ else if (bits != 8)
+ dev_dbg(port->dev, "Unsupported data bits config: %u bits\n"
+ , bits);
+
+ if (ofs->rtor != UNDEF_REG && (stm32_port->rx_ch ||
+ stm32_port->fifoen)) {
+ if (cflag & CSTOPB)
+ bits = bits + 3; /* 1 start bit + 2 stop bits */
+ else
+ bits = bits + 2; /* 1 start bit + 1 stop bit */
+
+ /* RX timeout irq to occur after last stop bit + bits */
+ stm32_port->cr1_irq = USART_CR1_RTOIE;
+ writel_relaxed(bits, port->membase + ofs->rtor);
+ cr2 |= USART_CR2_RTOEN;
+ /* Not using dma, enable fifo threshold irq */
+ if (!stm32_port->rx_ch)
+ stm32_port->cr3_irq = USART_CR3_RXFTIE;
+ }
+
+ cr1 |= stm32_port->cr1_irq;
+ cr3 |= stm32_port->cr3_irq;
+
if (cflag & PARODD)
cr1 |= USART_CR1_PS;
@@ -679,14 +796,14 @@
if (termios->c_iflag & INPCK)
port->read_status_mask |= USART_SR_PE | USART_SR_FE;
if (termios->c_iflag & (IGNBRK | BRKINT | PARMRK))
- port->read_status_mask |= USART_SR_LBD;
+ port->read_status_mask |= USART_SR_FE;
/* Characters to ignore */
port->ignore_status_mask = 0;
if (termios->c_iflag & IGNPAR)
port->ignore_status_mask = USART_SR_PE | USART_SR_FE;
if (termios->c_iflag & IGNBRK) {
- port->ignore_status_mask |= USART_SR_LBD;
+ port->ignore_status_mask |= USART_SR_FE;
/*
* If we're ignoring parity and break indicators,
* ignore overruns too (for real raw support).
@@ -765,13 +882,13 @@
switch (state) {
case UART_PM_STATE_ON:
- clk_prepare_enable(stm32port->clk);
+ pm_runtime_get_sync(port->dev);
break;
case UART_PM_STATE_OFF:
spin_lock_irqsave(&port->lock, flags);
stm32_clr_bits(port, ofs->cr1, BIT(cfg->uart_enable_bit));
spin_unlock_irqrestore(&port->lock, flags);
- clk_disable_unprepare(stm32port->clk);
+ pm_runtime_put_sync(port->dev);
break;
}
}
@@ -808,12 +925,23 @@
port->flags = UPF_BOOT_AUTOCONF;
port->ops = &stm32_uart_ops;
port->dev = &pdev->dev;
- port->irq = platform_get_irq(pdev, 0);
+ port->fifosize = stm32port->info->cfg.fifosize;
+
+ ret = platform_get_irq(pdev, 0);
+ if (ret <= 0)
+ return ret ? : -ENODEV;
+ port->irq = ret;
+
port->rs485_config = stm32_config_rs485;
stm32_init_rs485(port, pdev);
- stm32port->wakeirq = platform_get_irq(pdev, 1);
+ if (stm32port->info->cfg.has_wakeup) {
+ stm32port->wakeirq = platform_get_irq(pdev, 1);
+ if (stm32port->wakeirq <= 0 && stm32port->wakeirq != -ENXIO)
+ return stm32port->wakeirq ? : -ENODEV;
+ }
+
stm32port->fifoen = stm32port->info->cfg.has_fifo;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -862,6 +990,8 @@
stm32_ports[id].hw_flow_control = of_property_read_bool(np,
"st,hw-flow-ctrl");
stm32_ports[id].port.line = id;
+ stm32_ports[id].cr1_irq = USART_CR1_RXNEIE;
+ stm32_ports[id].cr3_irq = 0;
stm32_ports[id].last_res = RX_BUF_L;
return &stm32_ports[id];
}
@@ -1020,15 +1150,22 @@
if (ret)
return ret;
- if (stm32port->info->cfg.has_wakeup && stm32port->wakeirq >= 0) {
+ if (stm32port->wakeirq > 0) {
ret = device_init_wakeup(&pdev->dev, true);
if (ret)
goto err_uninit;
+
+ ret = dev_pm_set_dedicated_wake_irq(&pdev->dev,
+ stm32port->wakeirq);
+ if (ret)
+ goto err_nowup;
+
+ device_set_wakeup_enable(&pdev->dev, false);
}
ret = uart_add_one_port(&stm32_usart_driver, &stm32port->port);
if (ret)
- goto err_nowup;
+ goto err_wirq;
ret = stm32_of_dma_rx_probe(stm32port, pdev);
if (ret)
@@ -1040,10 +1177,19 @@
platform_set_drvdata(pdev, &stm32port->port);
+ pm_runtime_get_noresume(&pdev->dev);
+ pm_runtime_set_active(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
+ pm_runtime_put_sync(&pdev->dev);
+
return 0;
+err_wirq:
+ if (stm32port->wakeirq > 0)
+ dev_pm_clear_wake_irq(&pdev->dev);
+
err_nowup:
- if (stm32port->info->cfg.has_wakeup && stm32port->wakeirq >= 0)
+ if (stm32port->wakeirq > 0)
device_init_wakeup(&pdev->dev, false);
err_uninit:
@@ -1057,7 +1203,9 @@
struct uart_port *port = platform_get_drvdata(pdev);
struct stm32_port *stm32_port = to_stm32_port(port);
struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
- struct stm32_usart_config *cfg = &stm32_port->info->cfg;
+ int err;
+
+ pm_runtime_get_sync(&pdev->dev);
stm32_clr_bits(port, ofs->cr3, USART_CR3_DMAR);
@@ -1079,12 +1227,19 @@
TX_BUF_L, stm32_port->tx_buf,
stm32_port->tx_dma_buf);
- if (cfg->has_wakeup && stm32_port->wakeirq >= 0)
+ if (stm32_port->wakeirq > 0) {
+ dev_pm_clear_wake_irq(&pdev->dev);
device_init_wakeup(&pdev->dev, false);
+ }
clk_disable_unprepare(stm32_port->clk);
- return uart_remove_one_port(&stm32_usart_driver, port);
+ err = uart_remove_one_port(&stm32_usart_driver, port);
+
+ pm_runtime_disable(&pdev->dev);
+ pm_runtime_put_noidle(&pdev->dev);
+
+ return err;
}
@@ -1187,15 +1342,15 @@
.cons = STM32_SERIAL_CONSOLE,
};
-#ifdef CONFIG_PM_SLEEP
-static void stm32_serial_enable_wakeup(struct uart_port *port, bool enable)
+static void __maybe_unused stm32_serial_enable_wakeup(struct uart_port *port,
+ bool enable)
{
struct stm32_port *stm32_port = to_stm32_port(port);
struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
struct stm32_usart_config *cfg = &stm32_port->info->cfg;
u32 val;
- if (!cfg->has_wakeup || stm32_port->wakeirq < 0)
+ if (stm32_port->wakeirq <= 0)
return;
if (enable) {
@@ -1212,7 +1367,7 @@
}
}
-static int stm32_serial_suspend(struct device *dev)
+static int __maybe_unused stm32_serial_suspend(struct device *dev)
{
struct uart_port *port = dev_get_drvdata(dev);
@@ -1223,21 +1378,46 @@
else
stm32_serial_enable_wakeup(port, false);
+ pinctrl_pm_select_sleep_state(dev);
+
return 0;
}
-static int stm32_serial_resume(struct device *dev)
+static int __maybe_unused stm32_serial_resume(struct device *dev)
{
struct uart_port *port = dev_get_drvdata(dev);
+ pinctrl_pm_select_default_state(dev);
+
if (device_may_wakeup(dev))
stm32_serial_enable_wakeup(port, false);
return uart_resume_port(&stm32_usart_driver, port);
}
-#endif /* CONFIG_PM_SLEEP */
+
+static int __maybe_unused stm32_serial_runtime_suspend(struct device *dev)
+{
+ struct uart_port *port = dev_get_drvdata(dev);
+ struct stm32_port *stm32port = container_of(port,
+ struct stm32_port, port);
+
+ clk_disable_unprepare(stm32port->clk);
+
+ return 0;
+}
+
+static int __maybe_unused stm32_serial_runtime_resume(struct device *dev)
+{
+ struct uart_port *port = dev_get_drvdata(dev);
+ struct stm32_port *stm32port = container_of(port,
+ struct stm32_port, port);
+
+ return clk_prepare_enable(stm32port->clk);
+}
static const struct dev_pm_ops stm32_serial_pm_ops = {
+ SET_RUNTIME_PM_OPS(stm32_serial_runtime_suspend,
+ stm32_serial_runtime_resume, NULL)
SET_SYSTEM_SLEEP_PM_OPS(stm32_serial_suspend, stm32_serial_resume)
};