summaryrefslogtreecommitdiff
path: root/board
diff options
context:
space:
mode:
authorTom Warren <twarren.nvidia@gmail.com>2011-04-28 07:55:13 -0700
committerSimon Glass <sjg@chromium.org>2011-08-24 09:56:21 -0700
commitd1b282db26a73650b51c680a693e707579ea8035 (patch)
treec985d8a611a2d549edd30902b0b4fd048686c455 /board
parenta14a954f1ed38a92f83a7b2861e438f21d728027 (diff)
Fix Seaboard UART corruption on SPI activity
On Seaboard the UART and SPI interfere with each other. This causes the UART to receive spurious zero bytes after SPI transactions and also means that SPI can corrupt a few output characters when it starts up if they are still in the UART buffer. This hack corrects this by making SPI record that it may have corrupted the UART, and making the UART take evasive action. BUG=chromium-os:13228 TEST=Try developer U-Boot on Seaboard, make sure it auto-boots OK now Review URL: http://codereview.chromium.org/6715017 Change-Id: If2281357f177eeb3a19a170ddea22adbcf5942e9 Reviewed-on: http://gerrit.chromium.org/gerrit/191 Reviewed-by: Simon Glass <sjg@chromium.org> Tested-by: Simon Glass <sjg@chromium.org>
Diffstat (limited to 'board')
-rw-r--r--board/nvidia/seaboard/seaboard.c69
1 files changed, 51 insertions, 18 deletions
diff --git a/board/nvidia/seaboard/seaboard.c b/board/nvidia/seaboard/seaboard.c
index 4b9a8f33e89..86655098faa 100644
--- a/board/nvidia/seaboard/seaboard.c
+++ b/board/nvidia/seaboard/seaboard.c
@@ -23,8 +23,14 @@
#include <common.h>
#include <asm/io.h>
-#include <asm/arch/tegra2.h>
+#include <ns16550.h>
+#include <asm/arch/bitfield.h>
#include <asm/arch/gpio.h>
+#include <asm/arch/pinmux.h>
+#include <asm/arch/tegra2.h>
+#include <asm/arch/tegra2_spi.h>
+
+static enum spi_uart_switch switch_pos;
/*
* Routine: gpio_config_uart
@@ -32,21 +38,48 @@
*/
void gpio_config_uart(void)
{
- int gp = GPIO_PI3;
- struct gpio_ctlr *gpio = (struct gpio_ctlr *)NV_PA_GPIO_BASE;
- struct gpio_ctlr_bank *bank = &gpio->gpio_bank[GPIO_BANK(gp)];
- u32 val;
-
- /* Enable UART via GPIO_PI3 (port 8, bit 3) so serial console works */
- val = readl(&bank->gpio_config[GPIO_PORT(gp)]);
- val |= 1 << GPIO_BIT(gp);
- writel(val, &bank->gpio_config[GPIO_PORT(gp)]);
-
- val = readl(&bank->gpio_out[GPIO_PORT(gp)]);
- val &= ~(1 << GPIO_BIT(gp));
- writel(val, &bank->gpio_out[GPIO_PORT(gp)]);
-
- val = readl(&bank->gpio_dir_out[GPIO_PORT(gp)]);
- val |= 1 << GPIO_BIT(gp);
- writel(val, &bank->gpio_dir_out[GPIO_PORT(gp)]);
+ gpio_direction_output(UART_DISABLE_GPIO, 0);
+ switch_pos = SWITCH_UART;
+}
+
+#ifdef CONFIG_SPI_CORRUPTS_UART
+
+void seaboard_switch_spi_uart(enum spi_uart_switch new_pos)
+{
+ struct pmux_tri_ctlr *pmt = (struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE;
+
+ if (new_pos == switch_pos)
+ return;
+
+ /* if the UART was selected, allow it to drain */
+ if (switch_pos == SWITCH_UART)
+ NS16550_drain((NS16550_t)CONFIG_SPI_CORRUPTS_UART,
+ CONFIG_SPI_CORRUPTS_UART_NR);
+
+ /* We need to dynamically change the pinmux, shared w/UART RXD/CTS */
+ bf_writel(GMC_SEL_SFLASH, new_pos == SWITCH_SPI ? 3 : 0,
+ &pmt->pmt_ctl_b);
+
+ /*
+ * 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(UART_DISABLE_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((NS16550_t)CONFIG_SPI_CORRUPTS_UART,
+ CONFIG_SPI_CORRUPTS_UART_NR);
+ }
+}
+
+void enable_uart(void)
+{
+ seaboard_switch_spi_uart(SWITCH_UART);
}
+
+#endif