LKML Archive on lore.kernel.org
help / color / mirror / Atom feed
* [PATCH 0/7] usart various fixes for STM32
@ 2019-05-21 15:45 Erwan Le Ray
2019-05-21 15:45 ` [PATCH 1/7] serial: stm32: fix word length configuration Erwan Le Ray
` (6 more replies)
0 siblings, 7 replies; 8+ messages in thread
From: Erwan Le Ray @ 2019-05-21 15:45 UTC (permalink / raw)
To: Greg Kroah-Hartman, Jiri Slaby, Maxime Coquelin, Alexandre Torgue
Cc: linux-serial, linux-stm32, linux-arm-kernel, linux-kernel,
Erwan Le Ray, Fabrice Gasnier
This series delivers fixes in various uart functions of stm32-usart
driver.
Erwan Le Ray (7):
serial: stm32: fix word length configuration
serial: stm32: fix rx error handling
serial: stm32: fix rx data length when parity enabled
serial: stm32: fix transmit_chars when tx is stopped
serial: stm32: Add support of TC bit status check
serial: stm32: fix wakeup source initialization
serial: stm32: fix the get_irq error case
drivers/tty/serial/stm32-usart.c | 221 ++++++++++++++++++++++++++-------------
drivers/tty/serial/stm32-usart.h | 14 +--
2 files changed, 152 insertions(+), 83 deletions(-)
--
1.9.1
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 1/7] serial: stm32: fix word length configuration
2019-05-21 15:45 [PATCH 0/7] usart various fixes for STM32 Erwan Le Ray
@ 2019-05-21 15:45 ` Erwan Le Ray
2019-05-21 15:45 ` [PATCH 2/7] serial: stm32: fix rx error handling Erwan Le Ray
` (5 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Erwan Le Ray @ 2019-05-21 15:45 UTC (permalink / raw)
To: Greg Kroah-Hartman, Jiri Slaby, Maxime Coquelin, Alexandre Torgue
Cc: linux-serial, linux-stm32, linux-arm-kernel, linux-kernel,
Erwan Le Ray, Fabrice Gasnier
STM32 supports either:
- 8 and 9 bits word length (including parity bit) for stm32f4 compatible
devices
- 7, 8 and 9 bits word length (including parity bit) for stm32f7 and
stm32h7 compatible devices.
As a consequence STM32 supports the following termios configurations:
- CS7 with parity bit, and CS8 (with or without parity bit) for stm32f4
compatible devices.
- CS6 with parity bit, CS7 and CS8 (with or without parity bit) for
stm32f7 and stm32h7 compatible devices.
This patch is fixing word length by configuring correctly the SoC with
supported configurations.
Fixes: ada8618ff3bf ("serial: stm32: adding support for stm32f7")
Signed-off-by: Erwan Le Ray <erwan.leray@st.com>
diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c
index e8d7a7b..e832185 100644
--- a/drivers/tty/serial/stm32-usart.c
+++ b/drivers/tty/serial/stm32-usart.c
@@ -599,6 +599,36 @@ static void stm32_shutdown(struct uart_port *port)
free_irq(port->irq, port);
}
+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 +636,7 @@ static void stm32_set_termios(struct uart_port *port, struct ktermios *termios,
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;
@@ -632,16 +662,28 @@ static void stm32_set_termios(struct uart_port *port, struct ktermios *termios,
if (cflag & CSTOPB)
cr2 |= USART_CR2_STOP_2B;
+ bits = stm32_get_databits(termios);
+
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 (cflag & PARODD)
cr1 |= USART_CR1_PS;
diff --git a/drivers/tty/serial/stm32-usart.h b/drivers/tty/serial/stm32-usart.h
index 6f294e2..a70aa50 100644
--- a/drivers/tty/serial/stm32-usart.h
+++ b/drivers/tty/serial/stm32-usart.h
@@ -151,8 +151,7 @@ struct stm32_usart_info stm32h7_info = {
#define USART_CR1_PS BIT(9)
#define USART_CR1_PCE BIT(10)
#define USART_CR1_WAKE BIT(11)
-#define USART_CR1_M BIT(12)
-#define USART_CR1_M0 BIT(12) /* F7 */
+#define USART_CR1_M0 BIT(12) /* F7 (CR1_M for F4) */
#define USART_CR1_MME BIT(13) /* F7 */
#define USART_CR1_CMIE BIT(14) /* F7 */
#define USART_CR1_OVER8 BIT(15)
--
1.9.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 2/7] serial: stm32: fix rx error handling
2019-05-21 15:45 [PATCH 0/7] usart various fixes for STM32 Erwan Le Ray
2019-05-21 15:45 ` [PATCH 1/7] serial: stm32: fix word length configuration Erwan Le Ray
@ 2019-05-21 15:45 ` Erwan Le Ray
2019-05-21 15:45 ` [PATCH 3/7] serial: stm32: fix rx data length when parity enabled Erwan Le Ray
` (4 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Erwan Le Ray @ 2019-05-21 15:45 UTC (permalink / raw)
To: Greg Kroah-Hartman, Jiri Slaby, Maxime Coquelin, Alexandre Torgue
Cc: linux-serial, linux-stm32, linux-arm-kernel, linux-kernel,
Erwan Le Ray, Fabrice Gasnier
- Fixes parity and framing error bit by clearing parity and framing error
flag. The current implementation doesn't clear the error bits when an
error is detected.
- Fixes the incorrect name of framing error clearing flag in header file.
- Fixes misalignement between data frame and errors status. The status
read for "n" frame was the status of "n+1" frame".
- Fixes break detection was not triggered by the expected register.
Fixes: 48a6092fb41f ("serial: stm32-usart: Add STM32 USART Driver")
Signed-off-by: Erwan Le Ray <erwan.leray@st.com>
diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c
index e832185..f6b7393 100644
--- a/drivers/tty/serial/stm32-usart.c
+++ b/drivers/tty/serial/stm32-usart.c
@@ -225,35 +225,51 @@ static void stm32_receive_chars(struct uart_port *port, bool threaded)
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))
@@ -721,14 +737,14 @@ static void stm32_set_termios(struct uart_port *port, struct ktermios *termios,
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).
diff --git a/drivers/tty/serial/stm32-usart.h b/drivers/tty/serial/stm32-usart.h
index a70aa50..8d34802 100644
--- a/drivers/tty/serial/stm32-usart.h
+++ b/drivers/tty/serial/stm32-usart.h
@@ -108,7 +108,6 @@ struct stm32_usart_info stm32h7_info = {
#define USART_SR_RXNE BIT(5)
#define USART_SR_TC BIT(6)
#define USART_SR_TXE BIT(7)
-#define USART_SR_LBD BIT(8)
#define USART_SR_CTSIF BIT(9)
#define USART_SR_CTS BIT(10) /* F7 */
#define USART_SR_RTOF BIT(11) /* F7 */
@@ -120,8 +119,7 @@ struct stm32_usart_info stm32h7_info = {
#define USART_SR_SBKF BIT(18) /* F7 */
#define USART_SR_WUF BIT(20) /* H7 */
#define USART_SR_TEACK BIT(21) /* F7 */
-#define USART_SR_ERR_MASK (USART_SR_LBD | USART_SR_ORE | \
- USART_SR_FE | USART_SR_PE)
+#define USART_SR_ERR_MASK (USART_SR_ORE | USART_SR_FE | USART_SR_PE)
/* Dummy bits */
#define USART_SR_DUMMY_RX BIT(16)
@@ -168,8 +166,6 @@ struct stm32_usart_info stm32h7_info = {
/* USART_CR2 */
#define USART_CR2_ADD_MASK GENMASK(3, 0) /* F4 */
#define USART_CR2_ADDM7 BIT(4) /* F7 */
-#define USART_CR2_LBDL BIT(5)
-#define USART_CR2_LBDIE BIT(6)
#define USART_CR2_LBCL BIT(8)
#define USART_CR2_CPHA BIT(9)
#define USART_CR2_CPOL BIT(10)
@@ -226,12 +222,10 @@ struct stm32_usart_info stm32h7_info = {
/* USART_ICR */
#define USART_ICR_PECF BIT(0) /* F7 */
-#define USART_ICR_FFECF BIT(1) /* F7 */
-#define USART_ICR_NCF BIT(2) /* F7 */
+#define USART_ICR_FECF BIT(1) /* F7 */
#define USART_ICR_ORECF BIT(3) /* F7 */
#define USART_ICR_IDLECF BIT(4) /* F7 */
#define USART_ICR_TCCF BIT(6) /* F7 */
-#define USART_ICR_LBDCF BIT(8) /* F7 */
#define USART_ICR_CTSCF BIT(9) /* F7 */
#define USART_ICR_RTOCF BIT(11) /* F7 */
#define USART_ICR_EOBCF BIT(12) /* F7 */
--
1.9.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 3/7] serial: stm32: fix rx data length when parity enabled
2019-05-21 15:45 [PATCH 0/7] usart various fixes for STM32 Erwan Le Ray
2019-05-21 15:45 ` [PATCH 1/7] serial: stm32: fix word length configuration Erwan Le Ray
2019-05-21 15:45 ` [PATCH 2/7] serial: stm32: fix rx error handling Erwan Le Ray
@ 2019-05-21 15:45 ` Erwan Le Ray
2019-05-21 15:45 ` [PATCH 4/7] serial: stm32: fix transmit_chars when tx is stopped Erwan Le Ray
` (3 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Erwan Le Ray @ 2019-05-21 15:45 UTC (permalink / raw)
To: Greg Kroah-Hartman, Jiri Slaby, Maxime Coquelin, Alexandre Torgue
Cc: linux-serial, linux-stm32, linux-arm-kernel, linux-kernel,
Erwan Le Ray, Fabrice Gasnier
- Fixes a rx data error when data length < 8 bits and parity is enabled.
RDR register MSB is used for parity bit reception.
- Adds a mask to ignore MSB when data is get from RDR.
Fixes: 3489187204eb ("serial: stm32: adding dma support")
Signed-off-by: Erwan Le Ray <erwan.leray@st.com>
diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c
index f6b7393..0a7953e 100644
--- a/drivers/tty/serial/stm32-usart.c
+++ b/drivers/tty/serial/stm32-usart.c
@@ -194,8 +194,8 @@ static int stm32_pending_rx(struct uart_port *port, u32 *sr, int *last_res,
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 +205,13 @@ static int stm32_pending_rx(struct uart_port *port, u32 *sr, int *last_res,
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)
@@ -679,6 +682,7 @@ static void stm32_set_termios(struct uart_port *port, struct ktermios *termios,
cr2 |= USART_CR2_STOP_2B;
bits = stm32_get_databits(termios);
+ stm32_port->rdr_mask = (BIT(bits) - 1);
if (cflag & PARENB) {
bits++;
diff --git a/drivers/tty/serial/stm32-usart.h b/drivers/tty/serial/stm32-usart.h
index 8d34802..30d2433 100644
--- a/drivers/tty/serial/stm32-usart.h
+++ b/drivers/tty/serial/stm32-usart.h
@@ -254,6 +254,7 @@ struct stm32_port {
bool hw_flow_control;
bool fifoen;
int wakeirq;
+ int rdr_mask; /* receive data register mask */
};
static struct stm32_port stm32_ports[STM32_MAX_PORTS];
--
1.9.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 4/7] serial: stm32: fix transmit_chars when tx is stopped
2019-05-21 15:45 [PATCH 0/7] usart various fixes for STM32 Erwan Le Ray
` (2 preceding siblings ...)
2019-05-21 15:45 ` [PATCH 3/7] serial: stm32: fix rx data length when parity enabled Erwan Le Ray
@ 2019-05-21 15:45 ` Erwan Le Ray
2019-05-21 15:45 ` [PATCH 5/7] serial: stm32: Add support of TC bit status check Erwan Le Ray
` (2 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Erwan Le Ray @ 2019-05-21 15:45 UTC (permalink / raw)
To: Greg Kroah-Hartman, Jiri Slaby, Maxime Coquelin, Alexandre Torgue
Cc: linux-serial, linux-stm32, linux-arm-kernel, linux-kernel,
Erwan Le Ray, Fabrice Gasnier
Disables the tx irq when the transmission is ended and updates stop_tx
conditions for code cleanup.
Fixes: 48a6092fb41f ("serial: stm32-usart: Add STM32 USART Driver")
Signed-off-by: Erwan Le Ray <erwan.leray@st.com>
diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c
index 0a7953e..2e7757d 100644
--- a/drivers/tty/serial/stm32-usart.c
+++ b/drivers/tty/serial/stm32-usart.c
@@ -420,13 +420,8 @@ static void stm32_transmit_chars(struct uart_port *port)
return;
}
- if (uart_tx_stopped(port)) {
- stm32_stop_tx(port);
- return;
- }
-
- if (uart_circ_empty(xmit)) {
- stm32_stop_tx(port);
+ if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
+ stm32_clr_bits(port, ofs->cr1, USART_CR1_TXEIE);
return;
}
@@ -439,7 +434,7 @@ static void stm32_transmit_chars(struct uart_port *port)
uart_write_wakeup(port);
if (uart_circ_empty(xmit))
- stm32_stop_tx(port);
+ stm32_clr_bits(port, ofs->cr1, USART_CR1_TXEIE);
}
static irqreturn_t stm32_interrupt(int irq, void *ptr)
--
1.9.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 5/7] serial: stm32: Add support of TC bit status check
2019-05-21 15:45 [PATCH 0/7] usart various fixes for STM32 Erwan Le Ray
` (3 preceding siblings ...)
2019-05-21 15:45 ` [PATCH 4/7] serial: stm32: fix transmit_chars when tx is stopped Erwan Le Ray
@ 2019-05-21 15:45 ` Erwan Le Ray
2019-05-21 15:45 ` [PATCH 6/7] serial: stm32: fix wakeup source initialization Erwan Le Ray
2019-05-21 15:45 ` [PATCH 7/7] serial: stm32: fix the get_irq error case Erwan Le Ray
6 siblings, 0 replies; 8+ messages in thread
From: Erwan Le Ray @ 2019-05-21 15:45 UTC (permalink / raw)
To: Greg Kroah-Hartman, Jiri Slaby, Maxime Coquelin, Alexandre Torgue
Cc: linux-serial, linux-stm32, linux-arm-kernel, linux-kernel,
Erwan Le Ray, Fabrice Gasnier
Adds a check on the Transmission Complete bit status before closing the
com port. Prevents the port closure before the end of the transmission.
TC poll loop is moved from stm32_tx_dma_complete to stm32_shutdown
routine, in order to check TC before shutdown in both dma and
PIO tx modes.
TC clear is added in stm32_transmit_char routine, in order to be cleared
before transmitting in both dma and PIO tx modes.
Fixes: 3489187204eb ("serial: stm32: adding dma support")
Signed-off-by: Erwan Le Ray <erwan.leray@st.com>
diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c
index 2e7757d..d603be9 100644
--- a/drivers/tty/serial/stm32-usart.c
+++ b/drivers/tty/serial/stm32-usart.c
@@ -290,21 +290,6 @@ static void stm32_tx_dma_complete(void *arg)
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;
@@ -396,7 +381,6 @@ static void stm32_transmit_chars_dma(struct uart_port *port)
/* 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);
@@ -425,6 +409,11 @@ static void stm32_transmit_chars(struct uart_port *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);
else
@@ -601,12 +590,21 @@ static void stm32_shutdown(struct uart_port *port)
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 |= 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);
--
1.9.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 6/7] serial: stm32: fix wakeup source initialization
2019-05-21 15:45 [PATCH 0/7] usart various fixes for STM32 Erwan Le Ray
` (4 preceding siblings ...)
2019-05-21 15:45 ` [PATCH 5/7] serial: stm32: Add support of TC bit status check Erwan Le Ray
@ 2019-05-21 15:45 ` Erwan Le Ray
2019-05-21 15:45 ` [PATCH 7/7] serial: stm32: fix the get_irq error case Erwan Le Ray
6 siblings, 0 replies; 8+ messages in thread
From: Erwan Le Ray @ 2019-05-21 15:45 UTC (permalink / raw)
To: Greg Kroah-Hartman, Jiri Slaby, Maxime Coquelin, Alexandre Torgue
Cc: linux-serial, linux-stm32, linux-arm-kernel, linux-kernel,
Erwan Le Ray, Fabrice Gasnier
Fixes dedicated_irq_wakeup issue and deactivated uart as wakeup source by
default.
Fixes: 270e5a74fe4c ("serial: stm32: add wakeup mechanism")
Signed-off-by: Erwan Le Ray <erwan.leray@st.com>
diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c
index d603be9..1334e42 100644
--- a/drivers/tty/serial/stm32-usart.c
+++ b/drivers/tty/serial/stm32-usart.c
@@ -557,7 +557,6 @@ static int stm32_startup(struct uart_port *port)
{
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;
@@ -568,15 +567,6 @@ static int stm32_startup(struct uart_port *port)
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;
- }
- }
-
val = USART_CR1_RXNEIE | USART_CR1_TE | USART_CR1_RE;
if (stm32_port->fifoen)
val |= USART_CR1_FIFOEN;
@@ -607,7 +597,6 @@ static void stm32_shutdown(struct uart_port *port)
stm32_clr_bits(port, ofs->cr1, val);
- dev_pm_clear_wake_irq(port->dev);
free_irq(port->irq, port);
}
@@ -1079,11 +1068,18 @@ static int stm32_serial_probe(struct platform_device *pdev)
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)
@@ -1097,6 +1093,10 @@ static int stm32_serial_probe(struct platform_device *pdev)
return 0;
+err_wirq:
+ if (stm32port->info->cfg.has_wakeup && stm32port->wakeirq >= 0)
+ dev_pm_clear_wake_irq(&pdev->dev);
+
err_nowup:
if (stm32port->info->cfg.has_wakeup && stm32port->wakeirq >= 0)
device_init_wakeup(&pdev->dev, false);
@@ -1134,8 +1134,10 @@ static int stm32_serial_remove(struct platform_device *pdev)
TX_BUF_L, stm32_port->tx_buf,
stm32_port->tx_dma_buf);
- if (cfg->has_wakeup && stm32_port->wakeirq >= 0)
+ if (cfg->has_wakeup && stm32_port->wakeirq >= 0) {
+ dev_pm_clear_wake_irq(&pdev->dev);
device_init_wakeup(&pdev->dev, false);
+ }
clk_disable_unprepare(stm32_port->clk);
--
1.9.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 7/7] serial: stm32: fix the get_irq error case
2019-05-21 15:45 [PATCH 0/7] usart various fixes for STM32 Erwan Le Ray
` (5 preceding siblings ...)
2019-05-21 15:45 ` [PATCH 6/7] serial: stm32: fix wakeup source initialization Erwan Le Ray
@ 2019-05-21 15:45 ` Erwan Le Ray
6 siblings, 0 replies; 8+ messages in thread
From: Erwan Le Ray @ 2019-05-21 15:45 UTC (permalink / raw)
To: Greg Kroah-Hartman, Jiri Slaby, Maxime Coquelin, Alexandre Torgue
Cc: linux-serial, linux-stm32, linux-arm-kernel, linux-kernel,
Erwan Le Ray, Fabrice Gasnier, Fabien Dessenne
Checks the returned values of platform_get_irq() for both required
"event" and optional "wakeup" IRQs during probe. This allows the driver
probe to be deferred if needed.
Removes redundant checks for 'cfg.has_wakeup'.
Signed-off-by: Fabien Dessenne <fabien.dessenne@st.com>
Signed-off-by: Erwan Le Ray <erwan.leray@st.com>
diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c
index 1334e42..9c2b04e 100644
--- a/drivers/tty/serial/stm32-usart.c
+++ b/drivers/tty/serial/stm32-usart.c
@@ -852,12 +852,31 @@ static int stm32_init_port(struct stm32_port *stm32port,
port->flags = UPF_BOOT_AUTOCONF;
port->ops = &stm32_uart_ops;
port->dev = &pdev->dev;
- port->irq = platform_get_irq(pdev, 0);
+
+ ret = platform_get_irq(pdev, 0);
+ if (ret <= 0) {
+ if (ret != -EPROBE_DEFER)
+ dev_err(&pdev->dev, "Can't get event IRQ: %d\n", ret);
+ return ret ? 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) {
+ if (stm32port->wakeirq != -EPROBE_DEFER)
+ dev_err(&pdev->dev,
+ "Can't get event wake IRQ: %d\n",
+ stm32port->wakeirq);
+ return stm32port->wakeirq ? stm32port->wakeirq :
+ -ENODEV;
+ }
+ }
+
stm32port->fifoen = stm32port->info->cfg.has_fifo;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -1064,7 +1083,7 @@ static int stm32_serial_probe(struct platform_device *pdev)
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;
@@ -1094,11 +1113,11 @@ static int stm32_serial_probe(struct platform_device *pdev)
return 0;
err_wirq:
- if (stm32port->info->cfg.has_wakeup && stm32port->wakeirq >= 0)
+ 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:
@@ -1112,7 +1131,6 @@ static int stm32_serial_remove(struct platform_device *pdev)
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;
stm32_clr_bits(port, ofs->cr3, USART_CR3_DMAR);
@@ -1134,7 +1152,7 @@ static int stm32_serial_remove(struct platform_device *pdev)
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);
}
@@ -1252,7 +1270,7 @@ static void stm32_serial_enable_wakeup(struct uart_port *port, bool enable)
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) {
--
1.9.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
end of thread, other threads:[~2019-05-21 15:47 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-05-21 15:45 [PATCH 0/7] usart various fixes for STM32 Erwan Le Ray
2019-05-21 15:45 ` [PATCH 1/7] serial: stm32: fix word length configuration Erwan Le Ray
2019-05-21 15:45 ` [PATCH 2/7] serial: stm32: fix rx error handling Erwan Le Ray
2019-05-21 15:45 ` [PATCH 3/7] serial: stm32: fix rx data length when parity enabled Erwan Le Ray
2019-05-21 15:45 ` [PATCH 4/7] serial: stm32: fix transmit_chars when tx is stopped Erwan Le Ray
2019-05-21 15:45 ` [PATCH 5/7] serial: stm32: Add support of TC bit status check Erwan Le Ray
2019-05-21 15:45 ` [PATCH 6/7] serial: stm32: fix wakeup source initialization Erwan Le Ray
2019-05-21 15:45 ` [PATCH 7/7] serial: stm32: fix the get_irq error case Erwan Le Ray
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).