mirror of
https://github.com/torvalds/linux.git
synced 2026-09-22 12:44:03 +02:00
serial: 8250_mxpcie: add break support for RS485 using MUEx50 features
On MUEx50, break signaling under RS485 requires a driver-specific sequence and cannot be handled correctly by the generic 8250 break implementation alone. Implement a mxpcie break_ctl callback that performs MUEx50-specific break handling when RS485 is enabled and fall back to the default 8250 break handling for other modes. Signed-off-by: Crescent Hsieh <crescentcy.hsieh@moxa.com> Link: https://patch.msgid.link/20260731074820.735619-12-crescentcy.hsieh@moxa.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
af1ba61b62
commit
ade78d3d25
|
|
@ -54,6 +54,7 @@
|
|||
|
||||
/* Special Function Register (SFR) */
|
||||
#define MOXA_PUART_SFR 0x07
|
||||
#define MOXA_PUART_SFR_FORCE_TX BIT(0)
|
||||
#define MOXA_PUART_SFR_950 BIT(5)
|
||||
|
||||
/* Enhanced Function Register (EFR) */
|
||||
|
|
@ -382,6 +383,52 @@ static int mxpcie8250_handle_irq(struct uart_port *port)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static void mxpcie8250_software_break_ctl(struct uart_port *port, int break_state)
|
||||
{
|
||||
struct uart_8250_port *up = up_to_u8250p(port);
|
||||
struct tty_struct *tty = port->state->port.tty;
|
||||
unsigned int baud, quot;
|
||||
u8 sfr, tx_byte = 0x01;
|
||||
|
||||
guard(uart_port_lock_irqsave)(port);
|
||||
|
||||
if (break_state == -1) {
|
||||
serial_out(up, UART_LCR, up->lcr | UART_LCR_DLAB);
|
||||
serial_dl_write(up, 0);
|
||||
serial_out(up, UART_LCR, up->lcr);
|
||||
|
||||
serial_out(up, MOXA_PUART_TX_FIFO_MEM, tx_byte);
|
||||
|
||||
sfr = serial_in(up, MOXA_PUART_SFR);
|
||||
serial_out(up, MOXA_PUART_SFR, sfr | MOXA_PUART_SFR_FORCE_TX);
|
||||
|
||||
up->lcr |= UART_LCR_SBC;
|
||||
serial_out(up, UART_LCR, up->lcr);
|
||||
} else {
|
||||
up->lcr &= ~UART_LCR_SBC;
|
||||
serial_out(up, UART_LCR, up->lcr);
|
||||
|
||||
sfr = serial_in(up, MOXA_PUART_SFR);
|
||||
serial_out(up, MOXA_PUART_SFR, sfr & ~MOXA_PUART_SFR_FORCE_TX);
|
||||
|
||||
serial_out(up, UART_FCR, UART_FCR_CLEAR_XMIT);
|
||||
|
||||
baud = tty_get_baud_rate(tty);
|
||||
quot = uart_get_divisor(port, baud);
|
||||
serial8250_do_set_divisor(port, baud, quot);
|
||||
serial_out(up, UART_LCR, up->lcr);
|
||||
}
|
||||
}
|
||||
|
||||
static void mxpcie8250_break_ctl(struct uart_port *port, int break_state)
|
||||
{
|
||||
if (port->rs485.flags & SER_RS485_ENABLED &&
|
||||
!(port->rs485.flags & SER_RS485_MODE_RS422))
|
||||
mxpcie8250_software_break_ctl(port, break_state);
|
||||
else
|
||||
serial8250_do_break_ctl(port, break_state);
|
||||
}
|
||||
|
||||
static void mxpcie8250_init_board(struct pci_dev *pdev, struct mxpcie8250 *priv)
|
||||
{
|
||||
void __iomem *bar2_base = priv->bar2_base;
|
||||
|
|
@ -487,6 +534,7 @@ static int mxpcie8250_probe(struct pci_dev *pdev, const struct pci_device_id *id
|
|||
up.port.throttle = mxpcie8250_throttle;
|
||||
up.port.unthrottle = mxpcie8250_unthrottle;
|
||||
up.port.handle_irq = mxpcie8250_handle_irq;
|
||||
up.port.break_ctl = mxpcie8250_break_ctl;
|
||||
|
||||
for (unsigned int i = 0; i < num_ports; i++) {
|
||||
mxpcie8250_setup_port(pdev, priv, &up, i);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user