Patchwork [U-Boot,8/8] tegra2: Create SPI/UART switch code

login
register
mail settings
Submitter Simon Glass
Date Oct. 20, 2011, 7:03 p.m.
Message ID <1319137409-4132-9-git-send-email-sjg@chromium.org>
Download mbox | patch
Permalink /patch/120860/
State New, archived
Headers show

Comments

Simon Glass - Oct. 20, 2011, 7:03 p.m.
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 updates the board to use the SPI/UART switch to avoid the problem.

For now this feature is turned off since it needs changes to the NS16550
UART to operate.

Signed-off-by: Simon Glass <sjg@chromium.org>
---
 board/nvidia/common/board.c      |    8 ++++++++
 board/nvidia/common/board.h      |    1 +
 board/nvidia/seaboard/seaboard.c |    3 +++
 3 files changed, 12 insertions(+), 0 deletions(-)
Mike Frysinger - Oct. 20, 2011, 8:09 p.m.
On Thursday 20 October 2011 15:03:29 Simon Glass wrote:
> --- a/board/nvidia/seaboard/seaboard.c
> +++ b/board/nvidia/seaboard/seaboard.c
>
> +/* TODO: Remove this code when the SPI switch is working */
> +#ifndef CONFIG_SPI_UART_SWITCH

eh ?  isn't it working after these patches ?
-mike
Simon Glass - Oct. 20, 2011, 8:23 p.m.
Hi Mike,

On Thu, Oct 20, 2011 at 1:09 PM, Mike Frysinger <vapier@gentoo.org> wrote:
> On Thursday 20 October 2011 15:03:29 Simon Glass wrote:
>> --- a/board/nvidia/seaboard/seaboard.c
>> +++ b/board/nvidia/seaboard/seaboard.c
>>
>> +/* TODO: Remove this code when the SPI switch is working */
>> +#ifndef CONFIG_SPI_UART_SWITCH
>
> eh ?  isn't it working after these patches ?
> -mike
>

No, we need to resolve the NS16550 buffering issue, and also work out
how to get that driver to indicate when it needs to 'claim' the pins
from SPI.

I have a working implementation, and patches for it. Basically I call
uart_enable() from the NS16550 driver before writing any serial data
out or when wanting to read serial data. But it is ugly and I am torn
between simple ugliness and complex pervasiveness.

Advice welcome.

Regards,
Simon
Mike Frysinger - Oct. 20, 2011, 8:34 p.m.
On Thursday 20 October 2011 16:23:33 Simon Glass wrote:
> On Thu, Oct 20, 2011 at 1:09 PM, Mike Frysinger wrote:
> > On Thursday 20 October 2011 15:03:29 Simon Glass wrote:
> >> --- a/board/nvidia/seaboard/seaboard.c
> >> +++ b/board/nvidia/seaboard/seaboard.c
> >> 
> >> +/* TODO: Remove this code when the SPI switch is working */
> >> +#ifndef CONFIG_SPI_UART_SWITCH
> > 
> > eh ?  isn't it working after these patches ?
> 
> No, we need to resolve the NS16550 buffering issue, and also work out
> how to get that driver to indicate when it needs to 'claim' the pins
> from SPI.
> 
> I have a working implementation, and patches for it. Basically I call
> uart_enable() from the NS16550 driver before writing any serial data
> out or when wanting to read serial data. But it is ugly and I am torn
> between simple ugliness and complex pervasiveness.
> 
> Advice welcome.

hmmmmmmmmmm.  this is probably crazy, but ... if you enable multi serial, 
enable the ns16550 driver, and then write another "serial" driver that merely 
makes the relevant pinmux calls before tailing into the ns16550, and then set 
your stdout/stdin/stderr to that glue driver ...
-mike
Simon Glass - Oct. 20, 2011, 8:44 p.m.
Hi Mike,

On Thu, Oct 20, 2011 at 1:34 PM, Mike Frysinger <vapier@gentoo.org> wrote:
> On Thursday 20 October 2011 16:23:33 Simon Glass wrote:
>> On Thu, Oct 20, 2011 at 1:09 PM, Mike Frysinger wrote:
>> > On Thursday 20 October 2011 15:03:29 Simon Glass wrote:
>> >> --- a/board/nvidia/seaboard/seaboard.c
>> >> +++ b/board/nvidia/seaboard/seaboard.c
>> >>
>> >> +/* TODO: Remove this code when the SPI switch is working */
>> >> +#ifndef CONFIG_SPI_UART_SWITCH
>> >
>> > eh ?  isn't it working after these patches ?
>>
>> No, we need to resolve the NS16550 buffering issue, and also work out
>> how to get that driver to indicate when it needs to 'claim' the pins
>> from SPI.
>>
>> I have a working implementation, and patches for it. Basically I call
>> uart_enable() from the NS16550 driver before writing any serial data
>> out or when wanting to read serial data. But it is ugly and I am torn
>> between simple ugliness and complex pervasiveness.
>>
>> Advice welcome.
>
> hmmmmmmmmmm.  this is probably crazy, but ... if you enable multi serial,
> enable the ns16550 driver, and then write another "serial" driver that merely
> makes the relevant pinmux calls before tailing into the ns16550, and then set
> your stdout/stdin/stderr to that glue driver ...
> -mike
>

Gosh, that is baroque. Still it is an unusual hardware situation.

Given the current mess around the eserial structure definition macros
I would need to copy that again and create a set of _putc(), _puts()
functions for each UART I think. It could be done once serial is
cleaned up, but really don't want to undertake it now. In any case we
need buffering for all this to work so I might as well wait until this
is resolved:

http://patchwork.ozlabs.org/patch/120013/

Regards,
Simon
Mike Frysinger - Oct. 20, 2011, 8:50 p.m.
On Thursday 20 October 2011 16:44:26 Simon Glass wrote:
> Given the current mess around the eserial structure definition macros
> I would need to copy that again and create a set of _putc(), _puts()
> functions for each UART I think. It could be done once serial is
> cleaned up, but really don't want to undertake it now.

well, your pseudo serial driver need not have one reflection per ns16550 
instance.  you could require the user set an env var to the name of the serial 
device that you should redirect to.
-mike

Patch

diff --git a/board/nvidia/common/board.c b/board/nvidia/common/board.c
index 2591ebc..0403645 100644
--- a/board/nvidia/common/board.c
+++ b/board/nvidia/common/board.c
@@ -112,9 +112,13 @@  static void pin_mux_uart(int uart_ids)
  */
 int board_init(void)
 {
+	/* Do clocks and UART first so that printf() works */
 	clock_init();
 	clock_verify();
 
+#ifdef CONFIG_SPI_UART_SWITCH
+	gpio_config_uart();
+#endif
 #ifdef CONFIG_TEGRA2_SPI
 	spi_init();
 #endif
@@ -149,7 +153,11 @@  int board_early_init_f(void)
 	pin_mux_uart(uart_ids);
 
 	/* Initialize periph GPIOs */
+#ifdef CONFIG_SPI_UART_SWITCH
+	gpio_early_init_uart();
+#else
 	gpio_config_uart();
+#endif
 
 	/* Init UART, scratch regs, and start CPU */
 	tegra2_start();
diff --git a/board/nvidia/common/board.h b/board/nvidia/common/board.h
index 35acbca..2c89ff4 100644
--- a/board/nvidia/common/board.h
+++ b/board/nvidia/common/board.h
@@ -27,5 +27,6 @@ 
 void tegra2_start(void);
 void gpio_config_uart(void);
 int tegra2_mmc_init(int dev_index, int bus_width, int pwr_gpio, int cd_gpio);
+void gpio_early_init_uart(void);
 
 #endif	/* BOARD_H */
diff --git a/board/nvidia/seaboard/seaboard.c b/board/nvidia/seaboard/seaboard.c
index 2e8f4cc..2074e50 100644
--- a/board/nvidia/seaboard/seaboard.c
+++ b/board/nvidia/seaboard/seaboard.c
@@ -31,6 +31,8 @@ 
 #endif
 #include "../common/board.h"
 
+/* TODO: Remove this code when the SPI switch is working */
+#ifndef CONFIG_SPI_UART_SWITCH
 /*
  * Routine: gpio_config_uart_seaboard
  * Description: Force GPIO_PI3 low on Seaboard so UART4 works.
@@ -48,6 +50,7 @@  void gpio_config_uart(void)
 		return;
 	gpio_config_uart_seaboard();
 }
+#endif
 
 #ifdef CONFIG_TEGRA2_MMC
 /*