summaryrefslogtreecommitdiff
path: root/drivers/tty/serial/stm32-usart.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/tty/serial/stm32-usart.c')
-rw-r--r--drivers/tty/serial/stm32-usart.c310
1 files changed, 209 insertions, 101 deletions
diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c
index b3675cf25a69..c2ae7b392b86 100644
--- a/drivers/tty/serial/stm32-usart.c
+++ b/drivers/tty/serial/stm32-usart.c
@@ -218,8 +218,7 @@ static void stm32_usart_receive_chars(struct uart_port *port, bool threaded)
u32 sr;
char flag;
- if (irqd_is_wakeup_set(irq_get_irq_data(port->irq)))
- pm_wakeup_event(tport->tty->dev, 0);
+ spin_lock(&port->lock);
while (stm32_usart_pending_rx(port, &sr, &stm32_port->last_res,
threaded)) {
@@ -271,14 +270,14 @@ static void stm32_usart_receive_chars(struct uart_port *port, bool threaded)
}
}
- if (uart_handle_sysrq_char(port, c))
+ if (uart_prepare_sysrq_char(port, c))
continue;
uart_insert_char(port, sr, USART_SR_ORE, c, flag);
}
- spin_unlock(&port->lock);
+ uart_unlock_and_check_sysrq(port);
+
tty_flip_buffer_push(tport);
- spin_lock(&port->lock);
}
static void stm32_usart_tx_dma_complete(void *arg)
@@ -286,12 +285,16 @@ static void stm32_usart_tx_dma_complete(void *arg)
struct uart_port *port = arg;
struct stm32_port *stm32port = to_stm32_port(port);
const struct stm32_usart_offsets *ofs = &stm32port->info->ofs;
+ unsigned long flags;
+ dmaengine_terminate_async(stm32port->tx_ch);
stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAT);
stm32port->tx_dma_busy = false;
/* Let's see if we have pending data to send */
+ spin_lock_irqsave(&port->lock, flags);
stm32_usart_transmit_chars(port);
+ spin_unlock_irqrestore(&port->lock, flags);
}
static void stm32_usart_tx_interrupt_enable(struct uart_port *port)
@@ -303,7 +306,7 @@ static void stm32_usart_tx_interrupt_enable(struct uart_port *port)
* Enables TX FIFO threashold irq when FIFO is enabled,
* or TX empty irq when FIFO is disabled
*/
- if (stm32_port->fifoen)
+ if (stm32_port->fifoen && stm32_port->txftcfg >= 0)
stm32_usart_set_bits(port, ofs->cr3, USART_CR3_TXFTIE);
else
stm32_usart_set_bits(port, ofs->cr1, USART_CR1_TXEIE);
@@ -314,7 +317,7 @@ static void stm32_usart_tx_interrupt_disable(struct uart_port *port)
struct stm32_port *stm32_port = to_stm32_port(port);
const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
- if (stm32_port->fifoen)
+ if (stm32_port->fifoen && stm32_port->txftcfg >= 0)
stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_TXFTIE);
else
stm32_usart_clr_bits(port, ofs->cr1, USART_CR1_TXEIE);
@@ -455,29 +458,34 @@ static void stm32_usart_transmit_chars(struct uart_port *port)
static irqreturn_t stm32_usart_interrupt(int irq, void *ptr)
{
struct uart_port *port = ptr;
+ struct tty_port *tport = &port->state->port;
struct stm32_port *stm32_port = to_stm32_port(port);
const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
u32 sr;
- spin_lock(&port->lock);
-
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)
+ if ((sr & USART_SR_WUF) && ofs->icr != UNDEF_REG) {
+ /* Clear wake up flag and disable wake up interrupt */
writel_relaxed(USART_ICR_WUCF,
port->membase + ofs->icr);
+ stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_WUFIE);
+ if (irqd_is_wakeup_set(irq_get_irq_data(port->irq)))
+ pm_wakeup_event(tport->tty->dev, 0);
+ }
if ((sr & USART_SR_RXNE) && !(stm32_port->rx_ch))
stm32_usart_receive_chars(port, false);
- if ((sr & USART_SR_TXE) && !(stm32_port->tx_ch))
+ if ((sr & USART_SR_TXE) && !(stm32_port->tx_ch)) {
+ spin_lock(&port->lock);
stm32_usart_transmit_chars(port);
-
- spin_unlock(&port->lock);
+ spin_unlock(&port->lock);
+ }
if (stm32_port->rx_ch)
return IRQ_WAKE_THREAD;
@@ -490,13 +498,9 @@ static irqreturn_t stm32_usart_threaded_interrupt(int irq, void *ptr)
struct uart_port *port = ptr;
struct stm32_port *stm32_port = to_stm32_port(port);
- spin_lock(&port->lock);
-
if (stm32_port->rx_ch)
stm32_usart_receive_chars(port, true);
- spin_unlock(&port->lock);
-
return IRQ_HANDLED;
}
@@ -505,7 +509,10 @@ static unsigned int stm32_usart_tx_empty(struct uart_port *port)
struct stm32_port *stm32_port = to_stm32_port(port);
const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
- return readl_relaxed(port->membase + ofs->isr) & USART_SR_TXE;
+ if (readl_relaxed(port->membase + ofs->isr) & USART_SR_TC)
+ return TIOCSER_TEMT;
+
+ return 0;
}
static void stm32_usart_set_mctrl(struct uart_port *port, unsigned int mctrl)
@@ -584,6 +591,19 @@ static void stm32_usart_start_tx(struct uart_port *port)
stm32_usart_transmit_chars(port);
}
+/* Flush the transmit buffer. */
+static void stm32_usart_flush_buffer(struct uart_port *port)
+{
+ struct stm32_port *stm32_port = to_stm32_port(port);
+ const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
+
+ if (stm32_port->tx_ch) {
+ dmaengine_terminate_async(stm32_port->tx_ch);
+ stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAT);
+ stm32_port->tx_dma_busy = false;
+ }
+}
+
/* Throttle the remote when input buffer is about to overflow. */
static void stm32_usart_throttle(struct uart_port *port)
{
@@ -634,33 +654,30 @@ static int stm32_usart_startup(struct uart_port *port)
{
struct stm32_port *stm32_port = to_stm32_port(port);
const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
+ const struct stm32_usart_config *cfg = &stm32_port->info->cfg;
const char *name = to_platform_device(port->dev)->name;
u32 val;
int ret;
ret = request_threaded_irq(port->irq, stm32_usart_interrupt,
stm32_usart_threaded_interrupt,
- IRQF_NO_SUSPEND, name, port);
+ IRQF_ONESHOT | IRQF_NO_SUSPEND,
+ name, port);
if (ret)
return ret;
+ if (stm32_port->swap) {
+ val = readl_relaxed(port->membase + ofs->cr2);
+ val |= USART_CR2_SWAP;
+ writel_relaxed(val, port->membase + ofs->cr2);
+ }
+
/* RX FIFO Flush */
if (ofs->rqr != UNDEF_REG)
- stm32_usart_set_bits(port, ofs->rqr, USART_RQR_RXFRQ);
+ writel_relaxed(USART_RQR_RXFRQ, port->membase + ofs->rqr);
- /* 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);
- }
-
- /* RX FIFO enabling */
- val = stm32_port->cr1_irq | USART_CR1_RE;
- if (stm32_port->fifoen)
- val |= USART_CR1_FIFOEN;
+ /* RX enabling */
+ val = stm32_port->cr1_irq | USART_CR1_RE | BIT(cfg->uart_enable_bit);
stm32_usart_set_bits(port, ofs->cr1, val);
return 0;
@@ -691,6 +708,11 @@ static void stm32_usart_shutdown(struct uart_port *port)
if (ret)
dev_err(port->dev, "Transmission is not complete\n");
+ /* flush RX & TX FIFO */
+ if (ofs->rqr != UNDEF_REG)
+ writel_relaxed(USART_RQR_TXFRQ | USART_RQR_RXFRQ,
+ port->membase + ofs->rqr);
+
stm32_usart_clr_bits(port, ofs->cr1, val);
free_irq(port->irq, port);
@@ -737,8 +759,9 @@ static void stm32_usart_set_termios(struct uart_port *port,
unsigned int baud, bits;
u32 usartdiv, mantissa, fraction, oversampling;
tcflag_t cflag = termios->c_cflag;
- u32 cr1, cr2, cr3;
+ u32 cr1, cr2, cr3, isr;
unsigned long flags;
+ int ret;
if (!stm32_port->hw_flow_control)
cflag &= ~CRTSCTS;
@@ -747,21 +770,37 @@ static void stm32_usart_set_termios(struct uart_port *port,
spin_lock_irqsave(&port->lock, flags);
+ ret = readl_relaxed_poll_timeout_atomic(port->membase + ofs->isr,
+ isr,
+ (isr & USART_SR_TC),
+ 10, 100000);
+
+ /* Send the TC error message only when ISR_TC is not set. */
+ if (ret)
+ dev_err(port->dev, "Transmission is not complete\n");
+
/* Stop serial port and reset value */
writel_relaxed(0, port->membase + ofs->cr1);
/* flush RX & TX FIFO */
if (ofs->rqr != UNDEF_REG)
- stm32_usart_set_bits(port, ofs->rqr,
- USART_RQR_TXFRQ | USART_RQR_RXFRQ);
+ writel_relaxed(USART_RQR_TXFRQ | USART_RQR_RXFRQ,
+ port->membase + ofs->rqr);
cr1 = USART_CR1_TE | USART_CR1_RE;
if (stm32_port->fifoen)
cr1 |= USART_CR1_FIFOEN;
- cr2 = 0;
+ cr2 = stm32_port->swap ? USART_CR2_SWAP : 0;
+
+ /* Tx and RX FIFO configuration */
cr3 = readl_relaxed(port->membase + ofs->cr3);
- cr3 &= USART_CR3_TXFTIE | USART_CR3_RXFTCFG_MASK | USART_CR3_RXFTIE
- | USART_CR3_TXFTCFG_MASK;
+ cr3 &= USART_CR3_TXFTIE | USART_CR3_RXFTIE;
+ if (stm32_port->fifoen) {
+ if (stm32_port->txftcfg >= 0)
+ cr3 |= stm32_port->txftcfg << USART_CR3_TXFTCFG_SHIFT;
+ if (stm32_port->rxftcfg >= 0)
+ cr3 |= stm32_port->rxftcfg << USART_CR3_RXFTCFG_SHIFT;
+ }
if (cflag & CSTOPB)
cr2 |= USART_CR2_STOP_2B;
@@ -790,7 +829,8 @@ static void stm32_usart_set_termios(struct uart_port *port,
, bits);
if (ofs->rtor != UNDEF_REG && (stm32_port->rx_ch ||
- stm32_port->fifoen)) {
+ (stm32_port->fifoen &&
+ stm32_port->rxftcfg >= 0))) {
if (cflag & CSTOPB)
bits = bits + 3; /* 1 start bit + 2 stop bits */
else
@@ -817,12 +857,6 @@ static void stm32_usart_set_termios(struct uart_port *port,
cr3 |= USART_CR3_CTSE | USART_CR3_RTSE;
}
- /* Handle modem control interrupts */
- if (UART_ENABLE_MS(port, termios->c_cflag))
- stm32_usart_enable_ms(port);
- else
- stm32_usart_disable_ms(port);
-
usartdiv = DIV_ROUND_CLOSEST(port->uartclk, baud);
/*
@@ -892,12 +926,24 @@ static void stm32_usart_set_termios(struct uart_port *port,
cr1 &= ~(USART_CR1_DEDT_MASK | USART_CR1_DEAT_MASK);
}
+ /* Configure wake up from low power on start bit detection */
+ if (stm32_port->wakeup_src) {
+ cr3 &= ~USART_CR3_WUS_MASK;
+ cr3 |= USART_CR3_WUS_START_BIT;
+ }
+
writel_relaxed(cr3, port->membase + ofs->cr3);
writel_relaxed(cr2, port->membase + ofs->cr2);
writel_relaxed(cr1, port->membase + ofs->cr1);
stm32_usart_set_bits(port, ofs->cr1, BIT(cfg->uart_enable_bit));
spin_unlock_irqrestore(&port->lock, flags);
+
+ /* Handle modem control interrupts */
+ if (UART_ENABLE_MS(port, termios->c_cflag))
+ stm32_usart_enable_ms(port);
+ else
+ stm32_usart_disable_ms(port);
}
static const char *stm32_usart_type(struct uart_port *port)
@@ -962,6 +1008,7 @@ static const struct uart_ops stm32_uart_ops = {
.break_ctl = stm32_usart_break_ctl,
.startup = stm32_usart_startup,
.shutdown = stm32_usart_shutdown,
+ .flush_buffer = stm32_usart_flush_buffer,
.set_termios = stm32_usart_set_termios,
.pm = stm32_usart_pm,
.type = stm32_usart_type,
@@ -971,6 +1018,39 @@ static const struct uart_ops stm32_uart_ops = {
.verify_port = stm32_usart_verify_port,
};
+/*
+ * STM32H7 RX & TX FIFO threshold configuration (CR3 RXFTCFG / TXFTCFG)
+ * Note: 1 isn't a valid value in RXFTCFG / TXFTCFG. In this case,
+ * RXNEIE / TXEIE can be used instead of threshold irqs: RXFTIE / TXFTIE.
+ * So, RXFTCFG / TXFTCFG bitfields values are encoded as array index + 1.
+ */
+static const u32 stm32h7_usart_fifo_thresh_cfg[] = { 1, 2, 4, 8, 12, 14, 16 };
+
+static void stm32_usart_get_ftcfg(struct platform_device *pdev, const char *p,
+ int *ftcfg)
+{
+ u32 bytes, i;
+
+ /* DT option to get RX & TX FIFO threshold (default to 8 bytes) */
+ if (of_property_read_u32(pdev->dev.of_node, p, &bytes))
+ bytes = 8;
+
+ for (i = 0; i < ARRAY_SIZE(stm32h7_usart_fifo_thresh_cfg); i++)
+ if (stm32h7_usart_fifo_thresh_cfg[i] >= bytes)
+ break;
+ if (i >= ARRAY_SIZE(stm32h7_usart_fifo_thresh_cfg))
+ i = ARRAY_SIZE(stm32h7_usart_fifo_thresh_cfg) - 1;
+
+ dev_dbg(&pdev->dev, "%s set to %d bytes\n", p,
+ stm32h7_usart_fifo_thresh_cfg[i]);
+
+ /* Provide FIFO threshold ftcfg (1 is invalid: threshold irq unused) */
+ if (i)
+ *ftcfg = i - 1;
+ else
+ *ftcfg = -EINVAL;
+}
+
static void stm32_usart_deinit_port(struct stm32_port *stm32port)
{
clk_disable_unprepare(stm32port->clk);
@@ -1000,13 +1080,19 @@ static int stm32_usart_init_port(struct stm32_port *stm32port,
if (ret)
return ret;
- if (stm32port->info->cfg.has_wakeup) {
- stm32port->wakeirq = platform_get_irq_optional(pdev, 1);
- if (stm32port->wakeirq <= 0 && stm32port->wakeirq != -ENXIO)
- return stm32port->wakeirq ? : -ENODEV;
- }
+ stm32port->wakeup_src = stm32port->info->cfg.has_wakeup &&
+ of_property_read_bool(pdev->dev.of_node, "wakeup-source");
+
+ stm32port->swap = stm32port->info->cfg.has_swap &&
+ of_property_read_bool(pdev->dev.of_node, "rx-tx-swap");
stm32port->fifoen = stm32port->info->cfg.has_fifo;
+ if (stm32port->fifoen) {
+ stm32_usart_get_ftcfg(pdev, "rx-threshold",
+ &stm32port->rxftcfg);
+ stm32_usart_get_ftcfg(pdev, "tx-threshold",
+ &stm32port->txftcfg);
+ }
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
port->membase = devm_ioremap_resource(&pdev->dev, res);
@@ -1106,6 +1192,13 @@ static int stm32_usart_of_dma_rx_probe(struct stm32_port *stm32port,
struct dma_async_tx_descriptor *desc = NULL;
int ret;
+ /*
+ * Using DMA and threaded handler for the console could lead to
+ * deadlocks.
+ */
+ if (uart_console(port))
+ return -ENODEV;
+
/* Request DMA RX channel */
stm32port->rx_ch = dma_request_slave_channel(dev, "rx");
if (!stm32port->rx_ch) {
@@ -1239,23 +1332,13 @@ static int stm32_usart_serial_probe(struct platform_device *pdev)
if (ret)
return ret;
- 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 (stm32port->wakeup_src) {
+ device_set_wakeup_capable(&pdev->dev, true);
+ ret = dev_pm_set_wake_irq(&pdev->dev, stm32port->port.irq);
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_wirq;
-
ret = stm32_usart_of_dma_rx_probe(stm32port, pdev);
if (ret)
dev_info(&pdev->dev, "interrupt mode used for rx (no dma)\n");
@@ -1269,19 +1352,47 @@ static int stm32_usart_serial_probe(struct platform_device *pdev)
pm_runtime_get_noresume(&pdev->dev);
pm_runtime_set_active(&pdev->dev);
pm_runtime_enable(&pdev->dev);
+
+ ret = uart_add_one_port(&stm32_usart_driver, &stm32port->port);
+ if (ret)
+ goto err_port;
+
pm_runtime_put_sync(&pdev->dev);
return 0;
-err_wirq:
- if (stm32port->wakeirq > 0)
+err_port:
+ pm_runtime_disable(&pdev->dev);
+ pm_runtime_set_suspended(&pdev->dev);
+ pm_runtime_put_noidle(&pdev->dev);
+
+ if (stm32port->rx_ch) {
+ dmaengine_terminate_async(stm32port->rx_ch);
+ dma_release_channel(stm32port->rx_ch);
+ }
+
+ if (stm32port->rx_dma_buf)
+ dma_free_coherent(&pdev->dev,
+ RX_BUF_L, stm32port->rx_buf,
+ stm32port->rx_dma_buf);
+
+ if (stm32port->tx_ch) {
+ dmaengine_terminate_async(stm32port->tx_ch);
+ dma_release_channel(stm32port->tx_ch);
+ }
+
+ if (stm32port->tx_dma_buf)
+ dma_free_coherent(&pdev->dev,
+ TX_BUF_L, stm32port->tx_buf,
+ stm32port->tx_dma_buf);
+
+ if (stm32port->wakeup_src)
dev_pm_clear_wake_irq(&pdev->dev);
err_nowup:
- if (stm32port->wakeirq > 0)
- device_init_wakeup(&pdev->dev, false);
+ if (stm32port->wakeup_src)
+ device_set_wakeup_capable(&pdev->dev, false);
-err_uninit:
stm32_usart_deinit_port(stm32port);
return ret;
@@ -1295,11 +1406,20 @@ static int stm32_usart_serial_remove(struct platform_device *pdev)
int err;
pm_runtime_get_sync(&pdev->dev);
+ err = uart_remove_one_port(&stm32_usart_driver, port);
+ if (err)
+ return(err);
+
+ pm_runtime_disable(&pdev->dev);
+ pm_runtime_set_suspended(&pdev->dev);
+ pm_runtime_put_noidle(&pdev->dev);
stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAR);
- if (stm32_port->rx_ch)
+ if (stm32_port->rx_ch) {
+ dmaengine_terminate_async(stm32_port->rx_ch);
dma_release_channel(stm32_port->rx_ch);
+ }
if (stm32_port->rx_dma_buf)
dma_free_coherent(&pdev->dev,
@@ -1308,27 +1428,24 @@ static int stm32_usart_serial_remove(struct platform_device *pdev)
stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAT);
- if (stm32_port->tx_ch)
+ if (stm32_port->tx_ch) {
+ dmaengine_terminate_async(stm32_port->tx_ch);
dma_release_channel(stm32_port->tx_ch);
+ }
if (stm32_port->tx_dma_buf)
dma_free_coherent(&pdev->dev,
TX_BUF_L, stm32_port->tx_buf,
stm32_port->tx_dma_buf);
- if (stm32_port->wakeirq > 0) {
+ if (stm32_port->wakeup_src) {
dev_pm_clear_wake_irq(&pdev->dev);
device_init_wakeup(&pdev->dev, false);
}
stm32_usart_deinit_port(stm32_port);
- err = uart_remove_one_port(&stm32_usart_driver, port);
-
- pm_runtime_disable(&pdev->dev);
- pm_runtime_put_noidle(&pdev->dev);
-
- return err;
+ return 0;
}
#ifdef CONFIG_SERIAL_STM32_CONSOLE
@@ -1354,13 +1471,10 @@ static void stm32_usart_console_write(struct console *co, const char *s,
u32 old_cr1, new_cr1;
int locked = 1;
- local_irq_save(flags);
- if (port->sysrq)
- locked = 0;
- else if (oops_in_progress)
- locked = spin_trylock(&port->lock);
+ if (oops_in_progress)
+ locked = spin_trylock_irqsave(&port->lock, flags);
else
- spin_lock(&port->lock);
+ spin_lock_irqsave(&port->lock, flags);
/* Save and disable interrupts, enable the transmitter */
old_cr1 = readl_relaxed(port->membase + ofs->cr1);
@@ -1374,8 +1488,7 @@ static void stm32_usart_console_write(struct console *co, const char *s,
writel_relaxed(old_cr1, port->membase + ofs->cr1);
if (locked)
- spin_unlock(&port->lock);
- local_irq_restore(flags);
+ spin_unlock_irqrestore(&port->lock, flags);
}
static int stm32_usart_console_setup(struct console *co, char *options)
@@ -1436,23 +1549,20 @@ static void __maybe_unused stm32_usart_serial_en_wakeup(struct uart_port *port,
{
struct stm32_port *stm32_port = to_stm32_port(port);
const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
- const struct stm32_usart_config *cfg = &stm32_port->info->cfg;
- u32 val;
- if (stm32_port->wakeirq <= 0)
+ if (!stm32_port->wakeup_src)
return;
+ /*
+ * Enable low-power wake-up and wake-up irq if argument is set to
+ * "enable", disable low-power wake-up and wake-up irq otherwise
+ */
if (enable) {
- stm32_usart_clr_bits(port, ofs->cr1, BIT(cfg->uart_enable_bit));
stm32_usart_set_bits(port, ofs->cr1, USART_CR1_UESM);
- val = readl_relaxed(port->membase + ofs->cr3);
- val &= ~USART_CR3_WUS_MASK;
- /* Enable Wake up interrupt from low power on start bit */
- val |= USART_CR3_WUS_START_BIT | USART_CR3_WUFIE;
- writel_relaxed(val, port->membase + ofs->cr3);
- stm32_usart_set_bits(port, ofs->cr1, BIT(cfg->uart_enable_bit));
+ stm32_usart_set_bits(port, ofs->cr3, USART_CR3_WUFIE);
} else {
stm32_usart_clr_bits(port, ofs->cr1, USART_CR1_UESM);
+ stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_WUFIE);
}
}
@@ -1462,10 +1572,8 @@ static int __maybe_unused stm32_usart_serial_suspend(struct device *dev)
uart_suspend_port(&stm32_usart_driver, port);
- if (device_may_wakeup(dev))
+ if (device_may_wakeup(dev) || device_wakeup_path(dev))
stm32_usart_serial_en_wakeup(port, true);
- else
- stm32_usart_serial_en_wakeup(port, false);
/*
* When "no_console_suspend" is enabled, keep the pinctrl default state
@@ -1474,7 +1582,7 @@ static int __maybe_unused stm32_usart_serial_suspend(struct device *dev)
* capabilities.
*/
if (console_suspend_enabled || !uart_console(port)) {
- if (device_may_wakeup(dev))
+ if (device_may_wakeup(dev) || device_wakeup_path(dev))
pinctrl_pm_select_idle_state(dev);
else
pinctrl_pm_select_sleep_state(dev);
@@ -1489,7 +1597,7 @@ static int __maybe_unused stm32_usart_serial_resume(struct device *dev)
pinctrl_pm_select_default_state(dev);
- if (device_may_wakeup(dev))
+ if (device_may_wakeup(dev) || device_wakeup_path(dev))
stm32_usart_serial_en_wakeup(port, false);
return uart_resume_port(&stm32_usart_driver, port);