diff options
| author | Wolfgang Denk <wd@denx.de> | 2012-01-05 16:38:50 +0100 | 
|---|---|---|
| committer | Wolfgang Denk <wd@denx.de> | 2012-01-05 16:38:50 +0100 | 
| commit | 145afab32c3a049bd646d2eede5f2feba08576c6 (patch) | |
| tree | 52aba8f8d68626195027dc3dc190deef84895bfd /board/nvidia/common/uart-spi-switch.c | |
| parent | 72ebafbe2bd5044eecbfdaa132390a1421db25be (diff) | |
| parent | a747cc0a8c55d69a56a6db80a35cdb48c853447d (diff) | |
| download | olio-uboot-2014.01-145afab32c3a049bd646d2eede5f2feba08576c6.tar.xz olio-uboot-2014.01-145afab32c3a049bd646d2eede5f2feba08576c6.zip | |
Merge branch 'master' of git://git.denx.de/u-boot-arm
* 'master' of git://git.denx.de/u-boot-arm:
  tegra2: Optimize out-of-tree build for Ventana.
  tegra: Move boards over to use arch-level board UART function
  tegra: Add support for UART init in cpu board.c
  tegra: Add a function mux feature
  tegra: add clock_ll_start_uart() to enable UART prior to reloc
  tegra: Move clock_early_init() to arch_cpu_init()
  tegra: Move cpu_init_cp15() to arch_cpu_init()
  arm: Tegra: Fix Harmony and Ventana builds in u-boot-tegra/master
  tegra: Fix build error in plutux, medcom
  tegra2: Add Avionic Design Medcom support.
  tegra2: Add Avionic Design Plutux support.
  tegra2: Add common Avionic Design Tamonten support.
  tegra2: Move tegra2_mmc_init() prototype to public header.
  tegra2: Change CONFIG_SYS_TEXT_BASE to 0x00108000.
  tegra2: Always build with USE_PRIVATE_LIBGCC=yes.
  tegra2: Plumb in SPI/UART switch code
  tegra2: spi: Support SPI / UART switch
  tegra2: Implement SPI / UART GPIO switch
  tegra2: Enable SPI environment on Seaboard
  tegra2: config: Enable SPI flash on Seaboard
  tegra2: spi: Add SPI driver for Tegra2 SOC
  tegra2: Add UARTB support
  tegra2: Tidy UART selection
  arm, davinci: Fix build warnings for cam_enc_4xx
  Devkit8000: Switch over to enable_gpmc_cs_config
  arm, davinci: Add support for generating AIS images to the Makefile
  mkimage: Fix variable length header support
  arm, da850evm: Add an SPL for SPI boot
  arm, davinci: Add SPL support for DA850 SoCs
  sf: Add spi_boot() to allow booting from SPI flash in an SPL
  spl: display_options.o is required for SPI flash support in SPL
  ARM: omap3: add support to Technexion twister board
  ARM: omap3: added common configuration for Technexion TAM3517
  vision2: Fix checkpatch warning
Diffstat (limited to 'board/nvidia/common/uart-spi-switch.c')
| -rw-r--r-- | board/nvidia/common/uart-spi-switch.c | 138 | 
1 files changed, 138 insertions, 0 deletions
| diff --git a/board/nvidia/common/uart-spi-switch.c b/board/nvidia/common/uart-spi-switch.c new file mode 100644 index 000000000..23aa0b9d1 --- /dev/null +++ b/board/nvidia/common/uart-spi-switch.c @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2011 The Chromium OS Authors. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <ns16550.h> +#include <asm/gpio.h> +#include <asm/arch/pinmux.h> +#include <asm/arch/uart-spi-switch.h> +#include <asm/arch/tegra2.h> +#include <asm/arch/tegra2_spi.h> + + +/* position of the UART/SPI select switch */ +enum spi_uart_switch { +	SWITCH_UNKNOWN, +	SWITCH_SPI, +	SWITCH_UART, +	SWITCH_BOTH +}; + +/* 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 */ +}; + +static struct spi_uart local; +static enum spi_uart_switch switch_pos; /* Current switch position */ + + +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; +#endif +} + +/* + * Init the UART / SPI switch. This can be called before relocation so we must + * not access BSS. + */ +void gpio_early_init_uart(void) +{ +	struct spi_uart config; + +	get_config(&config); +	if (config.gpio != -1) { +		/* Cannot provide a label prior to relocation */ +		gpio_request(config.gpio, NULL); +		gpio_direction_output(config.gpio, 0); +	} +} + +/* + * Configure the UART / SPI switch. + */ +void gpio_config_uart(void) +{ +	get_config(&local); +	if (local.gpio != -1) { +		gpio_direction_output(local.gpio, 0); +		switch_pos = SWITCH_UART; +	} else { +		/* +		 * If we're here we don't have a SPI switch; go ahead and +		 * enable the SPI now.  We didn't in spi_init() so we wouldn't +		 * kill the UART. +		 */ +		pinmux_set_func(PINGRP_GMC, PMUX_FUNC_SFLASH); +		switch_pos = SWITCH_BOTH; +	} +} + +static void spi_uart_switch(struct spi_uart *config, +			      enum spi_uart_switch new_pos) +{ +	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); + +	/* 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. +	*/ +	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) +{ +	/* Also prevents calling spi_uart_switch() before relocation */ +	if (regs == local.regs) +		spi_uart_switch(&local, SWITCH_UART); +} + +void pinmux_select_spi(void) +{ +	spi_uart_switch(&local, SWITCH_SPI); +} |