diff options
author | Tom Warren <twarren@nvidia.com> | 2012-05-15 14:32:40 -0700 |
---|---|---|
committer | Albert ARIBAUD <albert.u.boot@aribaud.net> | 2012-07-07 14:07:17 +0200 |
commit | 078078cfa91f72331421e6f7a46938a58a9b21a7 (patch) | |
tree | 236b72582ed1f21e966b1d1fc89270cd36d9245d | |
parent | 558cd995d6d3eaa94fb342d142289a1fa2f76ba3 (diff) | |
download | u-boot-imx-078078cfa91f72331421e6f7a46938a58a9b21a7.zip u-boot-imx-078078cfa91f72331421e6f7a46938a58a9b21a7.tar.gz u-boot-imx-078078cfa91f72331421e6f7a46938a58a9b21a7.tar.bz2 |
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>
-rw-r--r-- | arch/arm/include/asm/arch-tegra2/uart-spi-switch.h | 4 | ||||
-rw-r--r-- | board/nvidia/common/uart-spi-switch.c | 27 | ||||
-rw-r--r-- | drivers/spi/tegra2_spi.c | 13 |
3 files changed, 21 insertions, 23 deletions
diff --git a/arch/arm/include/asm/arch-tegra2/uart-spi-switch.h b/arch/arm/include/asm/arch-tegra2/uart-spi-switch.h index e4503b1..82ac180 100644 --- a/arch/arm/include/asm/arch-tegra2/uart-spi-switch.h +++ b/arch/arm/include/asm/arch-tegra2/uart-spi-switch.h @@ -29,7 +29,7 @@ * time! If the board file provides this, the board config will declare it. * Let this be a lesson for others. */ -void pinmux_select_uart(NS16550_t regs); +void pinmux_select_uart(void); /* * Signal that we are about the use the SPI bus. @@ -38,7 +38,7 @@ void pinmux_select_spi(void); #else /* not CONFIG_SPI_UART_SWITCH */ -static inline void pinmux_select_uart(NS16550_t regs) {} +static inline void pinmux_select_uart(void) {} static inline void pinmux_select_spi(void) {} #endif diff --git a/board/nvidia/common/uart-spi-switch.c b/board/nvidia/common/uart-spi-switch.c index 23aa0b9..1ba1afd 100644 --- a/board/nvidia/common/uart-spi-switch.c +++ b/board/nvidia/common/uart-spi-switch.c @@ -21,7 +21,6 @@ */ #include <common.h> -#include <ns16550.h> #include <asm/gpio.h> #include <asm/arch/pinmux.h> #include <asm/arch/uart-spi-switch.h> @@ -40,7 +39,6 @@ enum spi_uart_switch { /* Information about the spi/uart switch */ struct spi_uart { int gpio; /* GPIO to control switch */ - NS16550_t regs; /* Address of UART affected */ u32 port; /* Port number of UART affected */ }; @@ -52,7 +50,6 @@ static void get_config(struct spi_uart *config) { #if defined CONFIG_SPI_CORRUPTS_UART config->gpio = CONFIG_UART_DISABLE_GPIO; - config->regs = (NS16550_t)CONFIG_SPI_CORRUPTS_UART; config->port = CONFIG_SPI_CORRUPTS_UART_NR; #else config->gpio = -1; @@ -101,34 +98,24 @@ static void spi_uart_switch(struct spi_uart *config, if (switch_pos == SWITCH_BOTH || new_pos == switch_pos) return; - /* if the UART was selected, allow it to drain */ - if (switch_pos == SWITCH_UART) - NS16550_drain(config->regs, config->port); + /* pre-delay, allow SPI/UART to settle, FIFO to empty, etc. */ + udelay(CONFIG_SPI_CORRUPTS_UART_DLY); /* We need to dynamically change the pinmux, shared w/UART RXD/CTS */ pinmux_set_func(PINGRP_GMC, new_pos == SWITCH_SPI ? PMUX_FUNC_SFLASH : PMUX_FUNC_UARTD); /* - * On Seaboard, MOSI/MISO are shared w/UART. - * Use GPIO I3 (UART_DISABLE) to tristate UART during SPI activity. - * Enable UART later (cs_deactivate) so we can use it for U-Boot comms. - */ + * On Seaboard, MOSI/MISO are shared w/UART. + * Use GPIO I3 (UART_DISABLE) to tristate UART during SPI activity. + * Enable UART later (cs_deactivate) so we can use it for U-Boot comms. + */ gpio_direction_output(config->gpio, new_pos == SWITCH_SPI); switch_pos = new_pos; - - /* if the SPI was selected, clear any junk bytes in the UART */ - if (switch_pos == SWITCH_UART) { - /* TODO: What if it is part-way through clocking in junk? */ - udelay(100); - NS16550_clear(config->regs, config->port); - } } -void pinmux_select_uart(NS16550_t regs) +void pinmux_select_uart(void) { - /* Also prevents calling spi_uart_switch() before relocation */ - if (regs == local.regs) spi_uart_switch(&local, SWITCH_UART); } diff --git a/drivers/spi/tegra2_spi.c b/drivers/spi/tegra2_spi.c index 56cb229..fe7b405 100644 --- a/drivers/spi/tegra2_spi.c +++ b/drivers/spi/tegra2_spi.c @@ -28,13 +28,18 @@ #include <spi.h> #include <asm/io.h> #include <asm/gpio.h> -#include <ns16550.h> #include <asm/arch/clk_rst.h> #include <asm/arch/clock.h> #include <asm/arch/pinmux.h> #include <asm/arch/uart-spi-switch.h> #include <asm/arch/tegra2_spi.h> +#if defined(CONFIG_SPI_CORRUPTS_UART) + #define corrupt_delay() udelay(CONFIG_SPI_CORRUPTS_UART_DLY); +#else + #define corrupt_delay() +#endif + struct tegra_spi_slave { struct spi_slave slave; struct spi_tegra *regs; @@ -161,14 +166,20 @@ void spi_cs_activate(struct spi_slave *slave) /* CS is negated on Tegra, so drive a 1 to get a 0 */ setbits_le32(&spi->regs->command, SPI_CMD_CS_VAL); + + corrupt_delay(); /* Let UART settle */ } void spi_cs_deactivate(struct spi_slave *slave) { struct tegra_spi_slave *spi = to_tegra_spi(slave); + pinmux_select_uart(); + /* CS is negated on Tegra, so drive a 0 to get a 1 */ clrbits_le32(&spi->regs->command, SPI_CMD_CS_VAL); + + corrupt_delay(); /* Let SPI settle */ } int spi_xfer(struct spi_slave *slave, unsigned int bitlen, |