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
#endif
51
#ifdef CONFIG_TEGRA_MMC
52
#include <asm/arch-tegra/tegra_mmc.h>
53 54
#include <asm/arch-tegra/mmc.h>
#endif
55
#include <i2c.h>
56
#include <spi.h>
57
#include "emc.h"
58 59 60

DECLARE_GLOBAL_DATA_PTR;

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

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

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

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

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

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

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

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

L
Lucas Stach 已提交
95 96 97 98 99 100 101
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 已提交
102 103 104 105 106 107
void __pin_mux_display(void)
{
}

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

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

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

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

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

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

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

	power_det_init();

153 154 155 156 157
#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();
158 159 160
# ifdef CONFIG_TEGRA_PMU
	if (pmu_set_nominal())
		debug("Failed to select nominal voltages\n");
161 162 163 164 165 166 167
#  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 */
168

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

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

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

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

189 190
	return 0;
}
191

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

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

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

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

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

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;
}
225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245

#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;
}
246 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

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 */