board.c 5.9 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
/*
 *  (C) Copyright 2010,2011
 *  NVIDIA Corporation <www.nvidia.com>
 *
 * 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>
26
#include <linux/compiler.h>
27
#include <asm/io.h>
S
Simon Glass 已提交
28
#include <asm/arch/clock.h>
29
#ifdef CONFIG_LCD
30
#include <asm/arch/display.h>
31
#endif
L
Lucas Stach 已提交
32
#include <asm/arch/funcmux.h>
33
#include <asm/arch/pinmux.h>
34
#include <asm/arch/pmu.h>
35
#ifdef CONFIG_PWM_TEGRA
S
Simon Glass 已提交
36
#include <asm/arch/pwm.h>
37
#endif
38 39 40 41 42 43 44
#include <asm/arch/tegra.h>
#include <asm/arch-tegra/board.h>
#include <asm/arch-tegra/clk_rst.h>
#include <asm/arch-tegra/pmc.h>
#include <asm/arch-tegra/sys_proto.h>
#include <asm/arch-tegra/uart.h>
#include <asm/arch-tegra/warmboot.h>
45 46 47 48
#ifdef CONFIG_TEGRA_CLOCK_SCALING
#include <asm/arch/emc.h>
#endif
#ifdef CONFIG_USB_EHCI_TEGRA
49
#include <asm/arch-tegra/usb.h>
50
#include <asm/arch/usb.h>
51
#endif
52
#ifdef CONFIG_TEGRA_MMC
53
#include <asm/arch-tegra/tegra_mmc.h>
54 55
#include <asm/arch-tegra/mmc.h>
#endif
56
#include <i2c.h>
57
#include <spi.h>
58
#include "emc.h"
59 60 61

DECLARE_GLOBAL_DATA_PTR;

62 63
const struct tegra_sysinfo sysinfo = {
	CONFIG_TEGRA_BOARD_STRING
64 65
};

66
#ifndef CONFIG_SPL_BUILD
67 68 69 70 71 72 73 74
/*
 * Routine: timer_init
 * Description: init the timestamp and lastinc value
 */
int timer_init(void)
{
	return 0;
}
75
#endif
76

77 78 79 80 81 82
void __pin_mux_usb(void)
{
}

void pin_mux_usb(void) __attribute__((weak, alias("__pin_mux_usb")));

83 84 85 86 87 88
void __pin_mux_spi(void)
{
}

void pin_mux_spi(void) __attribute__((weak, alias("__pin_mux_spi")));

L
Lucas Stach 已提交
89 90 91 92 93 94 95
void __gpio_early_init_uart(void)
{
}

void gpio_early_init_uart(void)
__attribute__((weak, alias("__gpio_early_init_uart")));

L
Lucas Stach 已提交
96 97 98 99 100 101 102
void __pin_mux_nand(void)
{
	funcmux_select(PERIPH_ID_NDFLASH, FUNCMUX_DEFAULT);
}

void pin_mux_nand(void) __attribute__((weak, alias("__pin_mux_nand")));

M
Marc Dietrich 已提交
103 104 105 106 107 108
void __pin_mux_display(void)
{
}

void pin_mux_display(void) __attribute__((weak, alias("__pin_mux_display")));

109 110 111 112 113 114
/*
 * Routine: power_det_init
 * Description: turn off power detects
 */
static void power_det_init(void)
{
A
Allen Martin 已提交
115
#if defined(CONFIG_TEGRA20)
116
	struct pmc_ctlr *const pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE;
117 118 119 120 121 122 123

	/* turn off power detects */
	writel(0, &pmc->pmc_pwr_det_latch);
	writel(0, &pmc->pmc_pwr_det);
#endif
}

124 125 126 127 128 129
/*
 * Routine: board_init
 * Description: Early hardware init.
 */
int board_init(void)
{
130 131
	__maybe_unused int err;

132
	/* Do clocks and UART first so that printf() works */
S
Simon Glass 已提交
133 134 135
	clock_init();
	clock_verify();

136
#ifdef CONFIG_FDT_SPI
137
	pin_mux_spi();
138
	spi_init();
S
Simon Glass 已提交
139
#endif
A
Allen Martin 已提交
140

S
Simon Glass 已提交
141 142 143
#ifdef CONFIG_PWM_TEGRA
	if (pwm_init(gd->fdt_blob))
		debug("%s: Failed to init pwm\n", __func__);
144 145
#endif
#ifdef CONFIG_LCD
M
Marc Dietrich 已提交
146
	pin_mux_display();
147
	tegra_lcd_check_next_stage(gd->fdt_blob, 0);
148
#endif
149 150
	/* boot param addr */
	gd->bd->bi_boot_params = (NV_PA_SDRAM_BASE + 0x100);
151 152 153

	power_det_init();

154 155 156 157 158
#ifdef CONFIG_TEGRA_I2C
#ifndef CONFIG_SYS_I2C_INIT_BOARD
#error "You must define CONFIG_SYS_I2C_INIT_BOARD to use i2c on Nvidia boards"
#endif
	i2c_init_board();
159 160 161
# ifdef CONFIG_TEGRA_PMU
	if (pmu_set_nominal())
		debug("Failed to select nominal voltages\n");
162 163 164 165 166 167 168
#  ifdef CONFIG_TEGRA_CLOCK_SCALING
	err = board_emc_init();
	if (err)
		debug("Memory controller init failed: %d\n", err);
#  endif
# endif /* CONFIG_TEGRA_PMU */
#endif /* CONFIG_TEGRA_I2C */
169

170 171 172 173
#ifdef CONFIG_USB_EHCI_TEGRA
	pin_mux_usb();
	board_usb_init(gd->fdt_blob);
#endif
174 175 176
#ifdef CONFIG_LCD
	tegra_lcd_check_next_stage(gd->fdt_blob, 0);
#endif
177

L
Lucas Stach 已提交
178 179 180 181
#ifdef CONFIG_TEGRA_NAND
	pin_mux_nand();
#endif

182
#ifdef CONFIG_TEGRA_LP0
183 184 185
	/* save Sdram params to PMC 2, 4, and 24 for WB0 */
	warmboot_save_sdram_params();

186 187 188 189
	/* prepare the WB code to LP0 location */
	warmboot_prepare_code(TEGRA_LP0_ADDR, TEGRA_LP0_SIZE);
#endif

190 191
	return 0;
}
192

S
Simon Glass 已提交
193
#ifdef CONFIG_BOARD_EARLY_INIT_F
194 195 196 197 198 199
static void __gpio_early_init(void)
{
}

void gpio_early_init(void) __attribute__((weak, alias("__gpio_early_init")));

S
Simon Glass 已提交
200 201
int board_early_init_f(void)
{
202
#if !defined(CONFIG_TEGRA20)
203 204
	pinmux_init();
#endif
205
	board_init_uart_f();
S
Simon Glass 已提交
206 207

	/* Initialize periph GPIOs */
208
	gpio_early_init();
209
	gpio_early_init_uart();
210 211 212
#ifdef CONFIG_LCD
	tegra_lcd_early_init(gd->fdt_blob);
#endif
L
Lucas Stach 已提交
213

S
Simon Glass 已提交
214 215 216
	return 0;
}
#endif	/* EARLY_INIT */
217 218 219 220 221 222 223 224 225

int board_late_init(void)
{
#ifdef CONFIG_LCD
	/* Make sure we finish initing the LCD */
	tegra_lcd_check_next_stage(gd->fdt_blob, 1);
#endif
	return 0;
}
226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246

#if defined(CONFIG_TEGRA_MMC)
void __pin_mux_mmc(void)
{
}

void pin_mux_mmc(void) __attribute__((weak, alias("__pin_mux_mmc")));

/* this is a weak define that we are overriding */
int board_mmc_init(bd_t *bd)
{
	debug("%s called\n", __func__);

	/* Enable muxes, etc. for SDMMC controllers */
	pin_mux_mmc();

	debug("%s: init MMC\n", __func__);
	tegra_mmc_init();

	return 0;
}
247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275

void pad_init_mmc(struct mmc_host *host)
{
#if defined(CONFIG_TEGRA30)
	enum periph_id id = host->mmc_id;
	u32 val;

	debug("%s: sdmmc address = %08x, id = %d\n", __func__,
		(unsigned int)host->reg, id);

	/* Set the pad drive strength for SDMMC1 or 3 only */
	if (id != PERIPH_ID_SDMMC1 && id != PERIPH_ID_SDMMC3) {
		debug("%s: settings are only valid for SDMMC1/SDMMC3!\n",
			__func__);
		return;
	}

	val = readl(&host->reg->sdmemcmppadctl);
	val &= 0xFFFFFFF0;
	val |= MEMCOMP_PADCTRL_VREF;
	writel(val, &host->reg->sdmemcmppadctl);

	val = readl(&host->reg->autocalcfg);
	val &= 0xFFFF0000;
	val |= AUTO_CAL_PU_OFFSET | AUTO_CAL_PD_OFFSET | AUTO_CAL_ENABLED;
	writel(val, &host->reg->autocalcfg);
#endif	/* T30 */
}
#endif	/* MMC */