Commit 078078cfa91f72331421e6f7a46938a58a9b21a7
Committed by
Albert ARIBAUD
1 parent
558cd995d6
Exists in
master
and in
55 other branches
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, |