Skip to content

Commit 235b54a

Browse files
RengarajanSSmehmetb0
authored andcommitted
8250: microchip: pci1xxxx: Add workaround for RTS bit toggle
BugLink: https://bugs.launchpad.net/bugs/2104873 [ Upstream commit e95cb63 ] In the B0 revision, the RTS pin remains high due to incorrect hardware mapping. To address this issue, enable auto-direction control with the RTS bit in ADCL_CFG_REG. This configuration ensures that the RTS pin goes low when the terminal is opened and high when the terminal is closed. Additionally, we reset the step counter for Rx and Tx engines by writing into FRAC_DIV_CFG_REG. Signed-off-by: Rengarajan S <rengarajan.s@microchip.com> Link: https://lore.kernel.org/r/20241218094017.18290-1-rengarajan.s@microchip.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Sasha Levin <sashal@kernel.org> Signed-off-by: Noah Wager <noah.wager@canonical.com>
1 parent 097a9c7 commit 235b54a

File tree

1 file changed

+59
-1
lines changed

1 file changed

+59
-1
lines changed

drivers/tty/serial/8250/8250_pci1xxxx.c

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,12 @@
7878
#define UART_TX_BYTE_FIFO 0x00
7979
#define UART_FIFO_CTL 0x02
8080

81+
#define UART_MODEM_CTL_REG 0x04
82+
#define UART_MODEM_CTL_RTS_SET BIT(1)
83+
84+
#define UART_LINE_STAT_REG 0x05
85+
#define UART_LINE_XMIT_CHECK_MASK GENMASK(6, 5)
86+
8187
#define UART_ACTV_REG 0x11
8288
#define UART_BLOCK_SET_ACTIVE BIT(0)
8389

@@ -94,6 +100,7 @@
94100
#define UART_BIT_SAMPLE_CNT_16 16
95101
#define BAUD_CLOCK_DIV_INT_MSK GENMASK(31, 8)
96102
#define ADCL_CFG_RTS_DELAY_MASK GENMASK(11, 8)
103+
#define FRAC_DIV_TX_END_POINT_MASK GENMASK(23, 20)
97104

98105
#define UART_WAKE_REG 0x8C
99106
#define UART_WAKE_MASK_REG 0x90
@@ -134,6 +141,11 @@
134141
#define UART_BST_STAT_LSR_FRAME_ERR 0x8000000
135142
#define UART_BST_STAT_LSR_THRE 0x20000000
136143

144+
#define GET_MODEM_CTL_RTS_STATUS(reg) ((reg) & UART_MODEM_CTL_RTS_SET)
145+
#define GET_RTS_PIN_STATUS(val) (((val) & TIOCM_RTS) >> 1)
146+
#define RTS_TOGGLE_STATUS_MASK(val, reg) (GET_MODEM_CTL_RTS_STATUS(reg) \
147+
!= GET_RTS_PIN_STATUS(val))
148+
137149
struct pci1xxxx_8250 {
138150
unsigned int nr;
139151
u8 dev_rev;
@@ -254,6 +266,47 @@ static void pci1xxxx_set_divisor(struct uart_port *port, unsigned int baud,
254266
port->membase + UART_BAUD_CLK_DIVISOR_REG);
255267
}
256268

269+
static void pci1xxxx_set_mctrl(struct uart_port *port, unsigned int mctrl)
270+
{
271+
u32 fract_div_cfg_reg;
272+
u32 line_stat_reg;
273+
u32 modem_ctl_reg;
274+
u32 adcl_cfg_reg;
275+
276+
adcl_cfg_reg = readl(port->membase + ADCL_CFG_REG);
277+
278+
/* HW is responsible in ADCL_EN case */
279+
if ((adcl_cfg_reg & (ADCL_CFG_EN | ADCL_CFG_PIN_SEL)))
280+
return;
281+
282+
modem_ctl_reg = readl(port->membase + UART_MODEM_CTL_REG);
283+
284+
serial8250_do_set_mctrl(port, mctrl);
285+
286+
if (RTS_TOGGLE_STATUS_MASK(mctrl, modem_ctl_reg)) {
287+
line_stat_reg = readl(port->membase + UART_LINE_STAT_REG);
288+
if (line_stat_reg & UART_LINE_XMIT_CHECK_MASK) {
289+
fract_div_cfg_reg = readl(port->membase +
290+
FRAC_DIV_CFG_REG);
291+
292+
writel((fract_div_cfg_reg &
293+
~(FRAC_DIV_TX_END_POINT_MASK)),
294+
port->membase + FRAC_DIV_CFG_REG);
295+
296+
/* Enable ADC and set the nRTS pin */
297+
writel((adcl_cfg_reg | (ADCL_CFG_EN |
298+
ADCL_CFG_PIN_SEL)),
299+
port->membase + ADCL_CFG_REG);
300+
301+
/* Revert to the original settings */
302+
writel(adcl_cfg_reg, port->membase + ADCL_CFG_REG);
303+
304+
writel(fract_div_cfg_reg, port->membase +
305+
FRAC_DIV_CFG_REG);
306+
}
307+
}
308+
}
309+
257310
static int pci1xxxx_rs485_config(struct uart_port *port,
258311
struct ktermios *termios,
259312
struct serial_rs485 *rs485)
@@ -631,9 +684,14 @@ static int pci1xxxx_setup(struct pci_dev *pdev,
631684
port->port.rs485_config = pci1xxxx_rs485_config;
632685
port->port.rs485_supported = pci1xxxx_rs485_supported;
633686

634-
/* From C0 rev Burst operation is supported */
687+
/*
688+
* C0 and later revisions support Burst operation.
689+
* RTS workaround in mctrl is applicable only to B0.
690+
*/
635691
if (rev >= 0xC0)
636692
port->port.handle_irq = pci1xxxx_handle_irq;
693+
else if (rev == 0xB0)
694+
port->port.set_mctrl = pci1xxxx_set_mctrl;
637695

638696
ret = serial8250_pci_setup_port(pdev, port, 0, PORT_OFFSET * port_idx, 0);
639697
if (ret < 0)

0 commit comments

Comments
 (0)