Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

tty: imx serial: Implement support for reversing TX and RX polarity

The peripheral has support for inverting its input and/or output
signals. This is useful if the hardware flips polarity of the
peripheral's signal, such as swapped +/- pins on an RS-422 transceiver,
or an inverting level shifter. Add support for these control registers
via the device tree binding.

As part of this change, make the writes of the various registers more
uniform by moving the UCR3 block up near the other registers' blocks,
since the INVT bit must be set before enabling the peripheral.

Signed-off-by: George Hilliard <ghilliard@kopismobile.com>
Acked-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Link: https://lore.kernel.org/r/20200226222319.18383-3-ghilliard@kopismobile.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

George Hilliard and committed by
Greg Kroah-Hartman
5a08a487 9dd5185a

+28 -16
+28 -16
drivers/tty/serial/imx.c
··· 195 195 unsigned int have_rtscts:1; 196 196 unsigned int have_rtsgpio:1; 197 197 unsigned int dte_mode:1; 198 + unsigned int inverted_tx:1; 199 + unsigned int inverted_rx:1; 198 200 struct clk *clk_ipg; 199 201 struct clk *clk_per; 200 202 const struct imx_uart_data *devdata; ··· 1337 1335 int retval, i; 1338 1336 unsigned long flags; 1339 1337 int dma_is_inited = 0; 1340 - u32 ucr1, ucr2, ucr4; 1338 + u32 ucr1, ucr2, ucr3, ucr4; 1341 1339 1342 1340 retval = clk_prepare_enable(sport->clk_per); 1343 1341 if (retval) ··· 1389 1387 1390 1388 imx_uart_writel(sport, ucr1, UCR1); 1391 1389 1392 - ucr4 = imx_uart_readl(sport, UCR4) & ~UCR4_OREN; 1390 + ucr4 = imx_uart_readl(sport, UCR4) & ~(UCR4_OREN | UCR4_INVR); 1393 1391 if (!sport->dma_is_enabled) 1394 1392 ucr4 |= UCR4_OREN; 1393 + if (sport->inverted_rx) 1394 + ucr4 |= UCR4_INVR; 1395 1395 imx_uart_writel(sport, ucr4, UCR4); 1396 + 1397 + ucr3 = imx_uart_readl(sport, UCR3) & ~UCR3_INVT; 1398 + /* 1399 + * configure tx polarity before enabling tx 1400 + */ 1401 + if (sport->inverted_tx) 1402 + ucr3 |= UCR3_INVT; 1403 + 1404 + if (!imx_uart_is_imx1(sport)) { 1405 + ucr3 |= UCR3_DTRDEN | UCR3_RI | UCR3_DCD; 1406 + 1407 + if (sport->dte_mode) 1408 + /* disable broken interrupts */ 1409 + ucr3 &= ~(UCR3_RI | UCR3_DCD); 1410 + } 1411 + imx_uart_writel(sport, ucr3, UCR3); 1396 1412 1397 1413 ucr2 = imx_uart_readl(sport, UCR2) & ~UCR2_ATEN; 1398 1414 ucr2 |= (UCR2_RXEN | UCR2_TXEN); ··· 1423 1403 if (!imx_uart_is_imx1(sport)) 1424 1404 ucr2 &= ~UCR2_RTSEN; 1425 1405 imx_uart_writel(sport, ucr2, UCR2); 1426 - 1427 - if (!imx_uart_is_imx1(sport)) { 1428 - u32 ucr3; 1429 - 1430 - ucr3 = imx_uart_readl(sport, UCR3); 1431 - 1432 - ucr3 |= UCR3_DTRDEN | UCR3_RI | UCR3_DCD; 1433 - 1434 - if (sport->dte_mode) 1435 - /* disable broken interrupts */ 1436 - ucr3 &= ~(UCR3_RI | UCR3_DCD); 1437 - 1438 - imx_uart_writel(sport, ucr3, UCR3); 1439 - } 1440 1406 1441 1407 /* 1442 1408 * Enable modem status interrupts ··· 2189 2183 2190 2184 if (of_get_property(np, "rts-gpios", NULL)) 2191 2185 sport->have_rtsgpio = 1; 2186 + 2187 + if (of_get_property(np, "fsl,inverted-tx", NULL)) 2188 + sport->inverted_tx = 1; 2189 + 2190 + if (of_get_property(np, "fsl,inverted-rx", NULL)) 2191 + sport->inverted_rx = 1; 2192 2192 2193 2193 return 0; 2194 2194 }