diff options
Diffstat (limited to 'board/nvidia/common')
| -rw-r--r-- | board/nvidia/common/Makefile | 47 | ||||
| -rw-r--r-- | board/nvidia/common/board.c | 73 | ||||
| -rw-r--r-- | board/nvidia/common/board.h | 2 | ||||
| -rw-r--r-- | board/nvidia/common/uart-spi-switch.c | 138 | 
4 files changed, 200 insertions, 60 deletions
diff --git a/board/nvidia/common/Makefile b/board/nvidia/common/Makefile new file mode 100644 index 000000000..3e748fdd2 --- /dev/null +++ b/board/nvidia/common/Makefile @@ -0,0 +1,47 @@ +# 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 $(TOPDIR)/config.mk + +ifneq ($(OBJTREE),$(SRCTREE)) +$(shell mkdir -p $(obj)board/$(VENDOR)/common) +endif + +LIB	= $(obj)lib$(VENDOR).o + +COBJS-y += board.o +COBJS-$(CONFIG_SPI_UART_SWITCH) += uart-spi-switch.o + +COBJS	:= $(COBJS-y) +SRCS	:= $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS	:= $(addprefix $(obj),$(COBJS)) +SOBJS	:= $(addprefix $(obj),$(SOBJS)) + +all:	$(LIB) + +$(LIB):	$(obj).depend $(OBJS) $(SOBJS) +	$(call cmd_link_o_target, $(OBJS) $(SOBJS)) + +######################################################################### +# This is for $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/board/nvidia/common/board.c b/board/nvidia/common/board.c index c806a6b3c..e8253a083 100644 --- a/board/nvidia/common/board.c +++ b/board/nvidia/common/board.c @@ -27,10 +27,12 @@  #include <asm/arch/tegra2.h>  #include <asm/arch/sys_proto.h> +#include <asm/arch/board.h>  #include <asm/arch/clk_rst.h>  #include <asm/arch/clock.h>  #include <asm/arch/pinmux.h>  #include <asm/arch/uart.h> +#include <spi.h>  #include "board.h"  DECLARE_GLOBAL_DATA_PTR; @@ -48,63 +50,22 @@ int timer_init(void)  	return 0;  } -static void enable_uart(enum periph_id pid) -{ -	/* Assert UART reset and enable clock */ -	reset_set_enable(pid, 1); -	clock_enable(pid); -	clock_ll_set_source(pid, 0);	/* UARTx_CLK_SRC = 00, PLLP_OUT0 */ - -	/* wait for 2us */ -	udelay(2); - -	/* De-assert reset to UART */ -	reset_set_enable(pid, 0); -} - -/* - * Routine: clock_init_uart - * Description: init the PLL and clock for the UART(s) - */ -static void clock_init_uart(void) -{ -#if defined(CONFIG_TEGRA2_ENABLE_UARTA) -	enable_uart(PERIPH_ID_UART1); -#endif	/* CONFIG_TEGRA2_ENABLE_UARTA */ -#if defined(CONFIG_TEGRA2_ENABLE_UARTD) -	enable_uart(PERIPH_ID_UART4); -#endif	/* CONFIG_TEGRA2_ENABLE_UARTD */ -} - -/* - * Routine: pin_mux_uart - * Description: setup the pin muxes/tristate values for the UART(s) - */ -static void pin_mux_uart(void) -{ -#if defined(CONFIG_TEGRA2_ENABLE_UARTA) -	pinmux_set_func(PINGRP_IRRX, PMUX_FUNC_UARTA); -	pinmux_set_func(PINGRP_IRTX, PMUX_FUNC_UARTA); - -	pinmux_tristate_disable(PINGRP_IRRX); -	pinmux_tristate_disable(PINGRP_IRTX); -#endif	/* CONFIG_TEGRA2_ENABLE_UARTA */ -#if defined(CONFIG_TEGRA2_ENABLE_UARTD) -	pinmux_set_func(PINGRP_GMC, PMUX_FUNC_UARTD); - -	pinmux_tristate_disable(PINGRP_GMC); -#endif	/* CONFIG_TEGRA2_ENABLE_UARTD */ -} -  /*   * Routine: board_init   * Description: Early hardware init.   */  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  	/* boot param addr */  	gd->bd->bi_boot_params = (NV_PA_SDRAM_BASE + 0x100); @@ -114,20 +75,14 @@ int board_init(void)  #ifdef CONFIG_BOARD_EARLY_INIT_F  int board_early_init_f(void)  { -	/* We didn't do this init in start.S, so do it now */ -	cpu_init_cp15(); - -	/* Initialize essential common plls */ -	clock_early_init(); - -	/* Initialize UART clocks */ -	clock_init_uart(); - -	/* Initialize periph pinmuxes */ -	pin_mux_uart(); +	board_init_uart_f();  	/* Initialize periph GPIOs */ +#ifdef CONFIG_SPI_UART_SWITCH +	gpio_early_init_uart(); +#else  	gpio_config_uart(); +#endif  	return 0;  }  #endif	/* EARLY_INIT */ diff --git a/board/nvidia/common/board.h b/board/nvidia/common/board.h index 1f5708660..a638af204 100644 --- a/board/nvidia/common/board.h +++ b/board/nvidia/common/board.h @@ -25,6 +25,6 @@  #define _BOARD_H_  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/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); +}  |