serial: stm32: Use TC interrupt to deassert GPIO RTS in RS485 mode
[ Upstream commit d7c7671616
]
In case the RS485 mode is emulated using GPIO RTS, use the TC interrupt
to deassert the GPIO RTS, otherwise the GPIO RTS stays asserted after a
transmission ended and the RS485 cannot work.
Signed-off-by: Marek Vasut <marex@denx.de>
Cc: Alexandre Torgue <alexandre.torgue@foss.st.com>
Cc: Erwan Le Ray <erwan.leray@foss.st.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Jean Philippe Romain <jean-philippe.romain@foss.st.com>
Cc: Valentin Caron <valentin.caron@foss.st.com>
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-stm32@st-md-mailman.stormreply.com
To: linux-serial@vger.kernel.org
Link: https://lore.kernel.org/r/20220430162845.244655-2-marex@denx.de
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
Родитель
c60eae5b1d
Коммит
45f628f4fd
|
@ -314,6 +314,14 @@ static void stm32_usart_tx_interrupt_enable(struct uart_port *port)
|
|||
stm32_usart_set_bits(port, ofs->cr1, USART_CR1_TXEIE);
|
||||
}
|
||||
|
||||
static void stm32_usart_tc_interrupt_enable(struct uart_port *port)
|
||||
{
|
||||
struct stm32_port *stm32_port = to_stm32_port(port);
|
||||
const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
|
||||
|
||||
stm32_usart_set_bits(port, ofs->cr1, USART_CR1_TCIE);
|
||||
}
|
||||
|
||||
static void stm32_usart_tx_interrupt_disable(struct uart_port *port)
|
||||
{
|
||||
struct stm32_port *stm32_port = to_stm32_port(port);
|
||||
|
@ -325,6 +333,14 @@ static void stm32_usart_tx_interrupt_disable(struct uart_port *port)
|
|||
stm32_usart_clr_bits(port, ofs->cr1, USART_CR1_TXEIE);
|
||||
}
|
||||
|
||||
static void stm32_usart_tc_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;
|
||||
|
||||
stm32_usart_clr_bits(port, ofs->cr1, USART_CR1_TCIE);
|
||||
}
|
||||
|
||||
static void stm32_usart_rs485_rts_enable(struct uart_port *port)
|
||||
{
|
||||
struct stm32_port *stm32_port = to_stm32_port(port);
|
||||
|
@ -462,6 +478,13 @@ static void stm32_usart_transmit_chars(struct uart_port *port)
|
|||
u32 isr;
|
||||
int ret;
|
||||
|
||||
if (!stm32_port->hw_flow_control &&
|
||||
port->rs485.flags & SER_RS485_ENABLED) {
|
||||
stm32_port->txdone = false;
|
||||
stm32_usart_tc_interrupt_disable(port);
|
||||
stm32_usart_rs485_rts_enable(port);
|
||||
}
|
||||
|
||||
if (port->x_char) {
|
||||
if (stm32_port->tx_dma_busy)
|
||||
stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAT);
|
||||
|
@ -501,8 +524,14 @@ static void stm32_usart_transmit_chars(struct uart_port *port)
|
|||
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
|
||||
uart_write_wakeup(port);
|
||||
|
||||
if (uart_circ_empty(xmit))
|
||||
if (uart_circ_empty(xmit)) {
|
||||
stm32_usart_tx_interrupt_disable(port);
|
||||
if (!stm32_port->hw_flow_control &&
|
||||
port->rs485.flags & SER_RS485_ENABLED) {
|
||||
stm32_port->txdone = true;
|
||||
stm32_usart_tc_interrupt_enable(port);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static irqreturn_t stm32_usart_interrupt(int irq, void *ptr)
|
||||
|
@ -515,6 +544,13 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr)
|
|||
|
||||
sr = readl_relaxed(port->membase + ofs->isr);
|
||||
|
||||
if (!stm32_port->hw_flow_control &&
|
||||
port->rs485.flags & SER_RS485_ENABLED &&
|
||||
(sr & USART_SR_TC)) {
|
||||
stm32_usart_tc_interrupt_disable(port);
|
||||
stm32_usart_rs485_rts_disable(port);
|
||||
}
|
||||
|
||||
if ((sr & USART_SR_RTOF) && ofs->icr != UNDEF_REG)
|
||||
writel_relaxed(USART_ICR_RTOCF,
|
||||
port->membase + ofs->icr);
|
||||
|
@ -612,8 +648,10 @@ static void stm32_usart_start_tx(struct uart_port *port)
|
|||
{
|
||||
struct circ_buf *xmit = &port->state->xmit;
|
||||
|
||||
if (uart_circ_empty(xmit) && !port->x_char)
|
||||
if (uart_circ_empty(xmit) && !port->x_char) {
|
||||
stm32_usart_rs485_rts_disable(port);
|
||||
return;
|
||||
}
|
||||
|
||||
stm32_usart_rs485_rts_enable(port);
|
||||
|
||||
|
|
|
@ -267,6 +267,7 @@ struct stm32_port {
|
|||
bool hw_flow_control;
|
||||
bool swap; /* swap RX & TX pins */
|
||||
bool fifoen;
|
||||
bool txdone;
|
||||
int rxftcfg; /* RX FIFO threshold CFG */
|
||||
int txftcfg; /* TX FIFO threshold CFG */
|
||||
bool wakeup_src;
|
||||
|
|
Загрузка…
Ссылка в новой задаче