Commit 078078cfa91f72331421e6f7a46938a58a9b21a7

Authored by Tom Warren
Committed by Albert ARIBAUD
1 parent 558cd995d6
Exists in master and in 55 other branches 8qm-imx_v2020.04_5.4.70_2.3.0, emb_lf_v2022.04, emb_lf_v2023.04, imx_v2015.04_4.1.15_1.0.0_ga, pitx_8mp_lf_v2020.04, smarc-8m-android-10.0.0_2.6.0, smarc-8m-android-11.0.0_2.0.0, smarc-8mp-android-11.0.0_2.0.0, smarc-emmc-imx_v2014.04_3.10.53_1.1.0_ga, smarc-emmc-imx_v2014.04_3.14.28_1.0.0_ga, smarc-imx-l5.0.0_1.0.0-ga, smarc-imx6_v2018.03_4.14.98_2.0.0_ga, smarc-imx7_v2017.03_4.9.11_1.0.0_ga, smarc-imx7_v2018.03_4.14.98_2.0.0_ga, smarc-imx_v2014.04_3.14.28_1.0.0_ga, smarc-imx_v2015.04_4.1.15_1.0.0_ga, smarc-imx_v2017.03_4.9.11_1.0.0_ga, smarc-imx_v2017.03_4.9.88_2.0.0_ga, smarc-imx_v2017.03_o8.1.0_1.3.0_8m, smarc-imx_v2018.03_4.14.78_1.0.0_ga, smarc-m6.0.1_2.1.0-ga, smarc-n7.1.2_2.0.0-ga, smarc-rel_imx_4.1.15_2.0.0_ga, smarc_8m-imx_v2018.03_4.14.98_2.0.0_ga, smarc_8m-imx_v2019.04_4.19.35_1.1.0, smarc_8m_00d0-imx_v2018.03_4.14.98_2.0.0_ga, smarc_8mm-imx_v2018.03_4.14.98_2.0.0_ga, smarc_8mm-imx_v2019.04_4.19.35_1.1.0, smarc_8mm-imx_v2020.04_5.4.24_2.1.0, smarc_8mp_lf_v2020.04, smarc_8mq-imx_v2020.04_5.4.24_2.1.0, smarc_8mq_lf_v2020.04, ti-u-boot-2015.07, u-boot-2013.01.y, v2013.10, v2013.10-smarct33, v2013.10-smartmen, v2014.01, v2014.04, v2014.04-smarct33, v2014.04-smarct33-emmc, v2014.04-smartmen, v2014.07, v2014.07-smarct33, v2014.07-smartmen, v2015.07-smarct33, v2015.07-smarct33-emmc, v2015.07-smarct4x, v2016.05-dlt, v2016.05-smarct3x, v2016.05-smarct3x-emmc, v2016.05-smarct4x, v2017.01-smarct3x, v2017.01-smarct3x-emmc, v2017.01-smarct4x

spi: Tegra2: Seaboard: fix UART corruption during SPI transactions

Simon Glass's proposal to fix this on Seaboard was NAK'd, so I
removed his NS16550 references and added a small delay before
SPI/UART muxing. Tested on my Seaboard with large SPI reads/writes
and saw no corruption (crc's matched) and no spurious comm chars.

Signed-off-by: Tom Warren <twarren@nvidia.com>
Acked-by: Simon Glass <sjg@chromium.org>
Tested-by: Jimmy Zhang <jimmzhang@nvidia.com>

Showing 3 changed files with 21 additions and 23 deletions Side-by-side Diff

arch/arm/include/asm/arch-tegra2/uart-spi-switch.h
... ... @@ -29,7 +29,7 @@
29 29 * time! If the board file provides this, the board config will declare it.
30 30 * Let this be a lesson for others.
31 31 */
32   -void pinmux_select_uart(NS16550_t regs);
  32 +void pinmux_select_uart(void);
33 33  
34 34 /*
35 35 * Signal that we are about the use the SPI bus.
... ... @@ -38,7 +38,7 @@
38 38  
39 39 #else /* not CONFIG_SPI_UART_SWITCH */
40 40  
41   -static inline void pinmux_select_uart(NS16550_t regs) {}
  41 +static inline void pinmux_select_uart(void) {}
42 42 static inline void pinmux_select_spi(void) {}
43 43  
44 44 #endif
board/nvidia/common/uart-spi-switch.c
... ... @@ -21,7 +21,6 @@
21 21 */
22 22  
23 23 #include <common.h>
24   -#include <ns16550.h>
25 24 #include <asm/gpio.h>
26 25 #include <asm/arch/pinmux.h>
27 26 #include <asm/arch/uart-spi-switch.h>
... ... @@ -40,7 +39,6 @@
40 39 /* Information about the spi/uart switch */
41 40 struct spi_uart {
42 41 int gpio; /* GPIO to control switch */
43   - NS16550_t regs; /* Address of UART affected */
44 42 u32 port; /* Port number of UART affected */
45 43 };
46 44  
... ... @@ -52,7 +50,6 @@
52 50 {
53 51 #if defined CONFIG_SPI_CORRUPTS_UART
54 52 config->gpio = CONFIG_UART_DISABLE_GPIO;
55   - config->regs = (NS16550_t)CONFIG_SPI_CORRUPTS_UART;
56 53 config->port = CONFIG_SPI_CORRUPTS_UART_NR;
57 54 #else
58 55 config->gpio = -1;
59 56  
60 57  
61 58  
62 59  
... ... @@ -101,34 +98,24 @@
101 98 if (switch_pos == SWITCH_BOTH || new_pos == switch_pos)
102 99 return;
103 100  
104   - /* if the UART was selected, allow it to drain */
105   - if (switch_pos == SWITCH_UART)
106   - NS16550_drain(config->regs, config->port);
  101 + /* pre-delay, allow SPI/UART to settle, FIFO to empty, etc. */
  102 + udelay(CONFIG_SPI_CORRUPTS_UART_DLY);
107 103  
108 104 /* We need to dynamically change the pinmux, shared w/UART RXD/CTS */
109 105 pinmux_set_func(PINGRP_GMC, new_pos == SWITCH_SPI ?
110 106 PMUX_FUNC_SFLASH : PMUX_FUNC_UARTD);
111 107  
112 108 /*
113   - * On Seaboard, MOSI/MISO are shared w/UART.
114   - * Use GPIO I3 (UART_DISABLE) to tristate UART during SPI activity.
115   - * Enable UART later (cs_deactivate) so we can use it for U-Boot comms.
116   - */
  109 + * On Seaboard, MOSI/MISO are shared w/UART.
  110 + * Use GPIO I3 (UART_DISABLE) to tristate UART during SPI activity.
  111 + * Enable UART later (cs_deactivate) so we can use it for U-Boot comms.
  112 + */
117 113 gpio_direction_output(config->gpio, new_pos == SWITCH_SPI);
118 114 switch_pos = new_pos;
119   -
120   - /* if the SPI was selected, clear any junk bytes in the UART */
121   - if (switch_pos == SWITCH_UART) {
122   - /* TODO: What if it is part-way through clocking in junk? */
123   - udelay(100);
124   - NS16550_clear(config->regs, config->port);
125   - }
126 115 }
127 116  
128   -void pinmux_select_uart(NS16550_t regs)
  117 +void pinmux_select_uart(void)
129 118 {
130   - /* Also prevents calling spi_uart_switch() before relocation */
131   - if (regs == local.regs)
132 119 spi_uart_switch(&local, SWITCH_UART);
133 120 }
134 121  
drivers/spi/tegra2_spi.c
... ... @@ -28,13 +28,18 @@
28 28 #include <spi.h>
29 29 #include <asm/io.h>
30 30 #include <asm/gpio.h>
31   -#include <ns16550.h>
32 31 #include <asm/arch/clk_rst.h>
33 32 #include <asm/arch/clock.h>
34 33 #include <asm/arch/pinmux.h>
35 34 #include <asm/arch/uart-spi-switch.h>
36 35 #include <asm/arch/tegra2_spi.h>
37 36  
  37 +#if defined(CONFIG_SPI_CORRUPTS_UART)
  38 + #define corrupt_delay() udelay(CONFIG_SPI_CORRUPTS_UART_DLY);
  39 +#else
  40 + #define corrupt_delay()
  41 +#endif
  42 +
38 43 struct tegra_spi_slave {
39 44 struct spi_slave slave;
40 45 struct spi_tegra *regs;
41 46  
42 47  
... ... @@ -161,14 +166,20 @@
161 166  
162 167 /* CS is negated on Tegra, so drive a 1 to get a 0 */
163 168 setbits_le32(&spi->regs->command, SPI_CMD_CS_VAL);
  169 +
  170 + corrupt_delay(); /* Let UART settle */
164 171 }
165 172  
166 173 void spi_cs_deactivate(struct spi_slave *slave)
167 174 {
168 175 struct tegra_spi_slave *spi = to_tegra_spi(slave);
169 176  
  177 + pinmux_select_uart();
  178 +
170 179 /* CS is negated on Tegra, so drive a 0 to get a 1 */
171 180 clrbits_le32(&spi->regs->command, SPI_CMD_CS_VAL);
  181 +
  182 + corrupt_delay(); /* Let SPI settle */
172 183 }
173 184  
174 185 int spi_xfer(struct spi_slave *slave, unsigned int bitlen,