tty: serial: cpm_uart – fix init when SMC is relocated [Linux 5.3]

This Linux kernel change "tty: serial: cpm_uart – fix init when SMC is relocated" is included in the Linux 5.3 release. This change is authored by Christophe Leroy <christophe.leroy [at] c-s.fr> on Wed May 22 12:17:11 2019 +0000. The commit for this change in Linux stable tree is 06aaa3d (patch).

tty: serial: cpm_uart - fix init when SMC is relocated

SMC relocation can also be activated earlier by the bootloader,
so the driver's behaviour cannot rely on selected kernel config.

When the SMC is relocated, CPM_CR_INIT_TRX cannot be used.

But the only thing CPM_CR_INIT_TRX does is to clear the
rstate and tstate registers, so this can be done manually,
even when SMC is not relocated.

Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
Fixes: 9ab921201444 ("cpm_uart: fix non-console port startup bug")
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

There are 17 lines of Linux source code added/deleted in this change. Code changes to Linux kernel are as follows.

 drivers/tty/serial/cpm_uart/cpm_uart_core.c | 17 +++++++++++------
 1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/drivers/tty/serial/cpm_uart/cpm_uart_core.c b/drivers/tty/serial/cpm_uart/cpm_uart_core.c
index b929c7a..7bab9a3 100644
--- a/drivers/tty/serial/cpm_uart/cpm_uart_core.c
+++ b/drivers/tty/serial/cpm_uart/cpm_uart_core.c
@@ -407,7 +407,16 @@ static int cpm_uart_startup(struct uart_port *port)
            clrbits16(&pinfo->sccp->scc_sccm, UART_SCCM_RX);
        }
        cpm_uart_initbd(pinfo);
-       cpm_line_cr_cmd(pinfo, CPM_CR_INIT_TRX);
+       if (IS_SMC(pinfo)) {
+           out_be32(&pinfo->smcup->smc_rstate, 0);
+           out_be32(&pinfo->smcup->smc_tstate, 0);
+           out_be16(&pinfo->smcup->smc_rbptr,
+                in_be16(&pinfo->smcup->smc_rbase));
+           out_be16(&pinfo->smcup->smc_tbptr,
+                in_be16(&pinfo->smcup->smc_tbase));
+       } else {
+           cpm_line_cr_cmd(pinfo, CPM_CR_INIT_TRX);
+       }
    }
    /* Install interrupt handler. */
    retval = request_irq(port->irq, cpm_uart_int, 0, "cpm_uart", port);
@@ -861,16 +870,14 @@ static void cpm_uart_init_smc(struct uart_cpm_port *pinfo)
             (u8 __iomem *)pinfo->tx_bd_base - DPRAM_BASE);

 /*
- *  In case SMC1 is being relocated...
+ *  In case SMC is being relocated...
  */
-#if defined (CONFIG_I2C_SPI_SMC1_UCODE_PATCH)
    out_be16(&up->smc_rbptr, in_be16(&pinfo->smcup->smc_rbase));
    out_be16(&up->smc_tbptr, in_be16(&pinfo->smcup->smc_tbase));
    out_be32(&up->smc_rstate, 0);
    out_be32(&up->smc_tstate, 0);
    out_be16(&up->smc_brkcr, 1);              /* number of break chars */
    out_be16(&up->smc_brkec, 0);
-#endif

    /* Set up the uart parameters in the
     * parameter ram.
@@ -884,8 +891,6 @@ static void cpm_uart_init_smc(struct uart_cpm_port *pinfo)
    out_be16(&up->smc_brkec, 0);
    out_be16(&up->smc_brkcr, 1);

-   cpm_line_cr_cmd(pinfo, CPM_CR_INIT_TRX);
-
    /* Set UART mode, 8 bit, no parity, one stop.
     * Enable receive and transmit.
     */

Leave a Reply

Your email address will not be published. Required fields are marked *