Message ID | 20200228124810.31543-1-rojay@codeaurora.org (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | [V3] tty: serial: qcom_geni_serial: Support pin swapping | expand |
Quoting Roja Rani Yarubandi (2020-02-28 04:48:10) > Add capability to supoort RX-TX, CTS-RTS pins swap in HW. > > Configure UART_IO_MACRO_CTRL register accordingly if RX-TX pair > or CTS-RTS pair or both pairs swapped. > > Signed-off-by: Roja Rani Yarubandi <rojay@codeaurora.org> > --- Reviewed-by: Stephen Boyd <swboyd@chromium.org>
On Fri, Feb 28, 2020 at 06:18:10PM +0530, Roja Rani Yarubandi wrote: > Add capability to supoort RX-TX, CTS-RTS pins swap in HW. > > Configure UART_IO_MACRO_CTRL register accordingly if RX-TX pair > or CTS-RTS pair or both pairs swapped. > > Signed-off-by: Roja Rani Yarubandi <rojay@codeaurora.org> > --- > Changes in V2: > - As per Greg's comment removed the change id. > > Changes in V3: > - As per Bjorn's comment using of_property_read_bool() to read dtsi entries. > - As per Matthias's comment add capability to support individual pairs swap, > that is, only RX-TX swap and only CTS-RTS swap cases. > > Dt-bindings support for this is posted at > https://patchwork.kernel.org/patch/11385969/ > > drivers/tty/serial/qcom_geni_serial.c | 30 +++++++++++++++++++++++++++ > 1 file changed, 30 insertions(+) > > diff --git a/drivers/tty/serial/qcom_geni_serial.c b/drivers/tty/serial/qcom_geni_serial.c > index 191abb18fc2a..2ad041cde4d7 100644 > --- a/drivers/tty/serial/qcom_geni_serial.c > +++ b/drivers/tty/serial/qcom_geni_serial.c > @@ -21,6 +21,7 @@ > > /* UART specific GENI registers */ > #define SE_UART_LOOPBACK_CFG 0x22c > +#define SE_UART_IO_MACRO_CTRL 0x240 > #define SE_UART_TX_TRANS_CFG 0x25c > #define SE_UART_TX_WORD_LEN 0x268 > #define SE_UART_TX_STOP_BIT_LEN 0x26c > @@ -95,6 +96,12 @@ > #define CTS_RTS_SORTED BIT(1) > #define RX_TX_CTS_RTS_SORTED (RX_TX_SORTED | CTS_RTS_SORTED) > > +/* UART pin swap value */ > +#define DEFAULT_IO_MACRO_IO0_IO1_MASK GENMASK(3, 0) > +#define IO_MACRO_IO0_SEL GENMASK(1, 0) not sure the use of GENMASK adds value here since it's not a mask, I rather find it obfuscating, IMO just 0x03 / 0x3 would be clearer. > +#define DEFAULT_IO_MACRO_IO2_IO3_MASK GENMASK(15, 4) > +#define IO_MACRO_IO2_IO3_SWAP 0x4640 > + > #ifdef CONFIG_CONSOLE_POLL > #define CONSOLE_RX_BYTES_PW 1 > #else > @@ -119,6 +126,8 @@ struct qcom_geni_serial_port { > > unsigned int tx_remaining; > int wakeup_irq; > + bool rx_tx_swap; > + bool cts_rts_swap; > }; > > static const struct uart_ops qcom_geni_console_pops; > @@ -826,6 +835,7 @@ static int qcom_geni_serial_port_setup(struct uart_port *uport) > struct qcom_geni_serial_port *port = to_dev_port(uport, uport); > u32 rxstale = DEFAULT_BITS_PER_CHAR * STALE_TIMEOUT; > u32 proto; > + u32 pin_swap; > > if (uart_console(uport)) { > port->tx_bytes_pw = 1; > @@ -846,6 +856,20 @@ static int qcom_geni_serial_port_setup(struct uart_port *uport) > get_tx_fifo_size(port); > > writel(rxstale, uport->membase + SE_UART_RX_STALE_CNT); > + > + pin_swap = readl(uport->membase + SE_UART_IO_MACRO_CTRL); > + if (port->rx_tx_swap) { > + pin_swap &= ~DEFAULT_IO_MACRO_IO2_IO3_MASK; > + pin_swap |= IO_MACRO_IO2_IO3_SWAP; > + } > + if (port->cts_rts_swap) { > + pin_swap &= ~DEFAULT_IO_MACRO_IO0_IO1_MASK; > + pin_swap |= IO_MACRO_IO0_SEL; > + } > + /* Configure this register if RX-TX, CTS-RTS pins are swapped */ > + if (port->rx_tx_swap || port->cts_rts_swap) > + writel(pin_swap, uport->membase + SE_UART_IO_MACRO_CTRL); > + > /* > * Make an unconditional cancel on the main sequencer to reset > * it else we could end up in data loss scenarios. > @@ -1289,6 +1313,12 @@ static int qcom_geni_serial_probe(struct platform_device *pdev) > if (!console) > port->wakeup_irq = platform_get_irq_optional(pdev, 1); > > + if (of_property_read_bool(pdev->dev.of_node, "rx-tx-swap")) > + port->rx_tx_swap = true; > + > + if (of_property_read_bool(pdev->dev.of_node, "cts-rts-swap")) > + port->cts_rts_swap = true; > + > uport->private_data = drv; > platform_set_drvdata(pdev, port); > port->handle_rx = console ? handle_rx_console : handle_rx_uart; Tested-by: Matthias Kaehlcke <mka@chromium.org> (TX/RX swap)
diff --git a/drivers/tty/serial/qcom_geni_serial.c b/drivers/tty/serial/qcom_geni_serial.c index 191abb18fc2a..2ad041cde4d7 100644 --- a/drivers/tty/serial/qcom_geni_serial.c +++ b/drivers/tty/serial/qcom_geni_serial.c @@ -21,6 +21,7 @@ /* UART specific GENI registers */ #define SE_UART_LOOPBACK_CFG 0x22c +#define SE_UART_IO_MACRO_CTRL 0x240 #define SE_UART_TX_TRANS_CFG 0x25c #define SE_UART_TX_WORD_LEN 0x268 #define SE_UART_TX_STOP_BIT_LEN 0x26c @@ -95,6 +96,12 @@ #define CTS_RTS_SORTED BIT(1) #define RX_TX_CTS_RTS_SORTED (RX_TX_SORTED | CTS_RTS_SORTED) +/* UART pin swap value */ +#define DEFAULT_IO_MACRO_IO0_IO1_MASK GENMASK(3, 0) +#define IO_MACRO_IO0_SEL GENMASK(1, 0) +#define DEFAULT_IO_MACRO_IO2_IO3_MASK GENMASK(15, 4) +#define IO_MACRO_IO2_IO3_SWAP 0x4640 + #ifdef CONFIG_CONSOLE_POLL #define CONSOLE_RX_BYTES_PW 1 #else @@ -119,6 +126,8 @@ struct qcom_geni_serial_port { unsigned int tx_remaining; int wakeup_irq; + bool rx_tx_swap; + bool cts_rts_swap; }; static const struct uart_ops qcom_geni_console_pops; @@ -826,6 +835,7 @@ static int qcom_geni_serial_port_setup(struct uart_port *uport) struct qcom_geni_serial_port *port = to_dev_port(uport, uport); u32 rxstale = DEFAULT_BITS_PER_CHAR * STALE_TIMEOUT; u32 proto; + u32 pin_swap; if (uart_console(uport)) { port->tx_bytes_pw = 1; @@ -846,6 +856,20 @@ static int qcom_geni_serial_port_setup(struct uart_port *uport) get_tx_fifo_size(port); writel(rxstale, uport->membase + SE_UART_RX_STALE_CNT); + + pin_swap = readl(uport->membase + SE_UART_IO_MACRO_CTRL); + if (port->rx_tx_swap) { + pin_swap &= ~DEFAULT_IO_MACRO_IO2_IO3_MASK; + pin_swap |= IO_MACRO_IO2_IO3_SWAP; + } + if (port->cts_rts_swap) { + pin_swap &= ~DEFAULT_IO_MACRO_IO0_IO1_MASK; + pin_swap |= IO_MACRO_IO0_SEL; + } + /* Configure this register if RX-TX, CTS-RTS pins are swapped */ + if (port->rx_tx_swap || port->cts_rts_swap) + writel(pin_swap, uport->membase + SE_UART_IO_MACRO_CTRL); + /* * Make an unconditional cancel on the main sequencer to reset * it else we could end up in data loss scenarios. @@ -1289,6 +1313,12 @@ static int qcom_geni_serial_probe(struct platform_device *pdev) if (!console) port->wakeup_irq = platform_get_irq_optional(pdev, 1); + if (of_property_read_bool(pdev->dev.of_node, "rx-tx-swap")) + port->rx_tx_swap = true; + + if (of_property_read_bool(pdev->dev.of_node, "cts-rts-swap")) + port->cts_rts_swap = true; + uport->private_data = drv; platform_set_drvdata(pdev, port); port->handle_rx = console ? handle_rx_console : handle_rx_uart;
Add capability to supoort RX-TX, CTS-RTS pins swap in HW. Configure UART_IO_MACRO_CTRL register accordingly if RX-TX pair or CTS-RTS pair or both pairs swapped. Signed-off-by: Roja Rani Yarubandi <rojay@codeaurora.org> --- Changes in V2: - As per Greg's comment removed the change id. Changes in V3: - As per Bjorn's comment using of_property_read_bool() to read dtsi entries. - As per Matthias's comment add capability to support individual pairs swap, that is, only RX-TX swap and only CTS-RTS swap cases. Dt-bindings support for this is posted at https://patchwork.kernel.org/patch/11385969/ drivers/tty/serial/qcom_geni_serial.c | 30 +++++++++++++++++++++++++++ 1 file changed, 30 insertions(+)