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

This Linux kernel change "tty: serial: cpm_uart – fix init when SMC is relocated" is included in the Linux 4.4.187 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 63d1bc1 (patch) which is from upstream commit 06aaa3d. The same Linux upstream change may have been applied to various maintained Linux releases and you can find all Linux releases containing changes from upstream 06aaa3d.

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

[ Upstream commit 06aaa3d066db87e8478522d910285141d44b1e58 ]

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 <[email protected]>
Fixes: 9ab921201444 ("cpm_uart: fix non-console port startup bug")
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Sasha Levin <[email protected]>

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 0040c29..b9e137c 100644
--- a/drivers/tty/serial/cpm_uart/cpm_uart_core.c
+++ b/drivers/tty/serial/cpm_uart/cpm_uart_core.c
@@ -421,7 +421,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);
@@ -875,16 +884,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.
@@ -898,8 +905,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 *