9
0
Fork 0

tegra: add lowlevel delay function

For proper startup we need to give clocks and IO signals some time to
stabilize. Tegra2 got away without them, but Tegra3 seems to be a bit
pickier.

Signed-off-by: Lucas Stach <dev@lynxeye.de>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
This commit is contained in:
Lucas Stach 2014-02-17 21:27:37 +01:00 committed by Sascha Hauer
parent 0de758b2ee
commit af155f74aa
2 changed files with 49 additions and 0 deletions

View File

@ -173,6 +173,49 @@ int tegra_get_osc_clock(void)
}
}
#define TIMER_CNTR_1US 0x00
#define TIMER_USEC_CFG 0x04
static __always_inline
void tegra_ll_delay_setup(void)
{
u32 reg;
/*
* calibrate timer to run at 1MHz
* TIMERUS_USEC_CFG selects the scale down factor with bits [0:7]
* representing the divisor and bits [8:15] representing the dividend
* each in n+1 form.
*/
switch (tegra_get_osc_clock()) {
case 12000000:
reg = 0x000b;
break;
case 13000000:
reg = 0x000c;
break;
case 19200000:
reg = 0x045f;
break;
case 26000000:
reg = 0x0019;
break;
default:
reg = 0;
break;
}
writel(reg, TEGRA_TMRUS_BASE + TIMER_USEC_CFG);
}
static __always_inline
void tegra_ll_delay_usec(int delay)
{
int timeout = (int)readl(TEGRA_TMRUS_BASE + TIMER_CNTR_1US) + delay;
while ((int)readl(TEGRA_TMRUS_BASE + TIMER_CNTR_1US) - timeout < 0);
}
static __always_inline
void tegra_cpu_lowlevel_setup(void)
{
@ -183,6 +226,7 @@ void tegra_cpu_lowlevel_setup(void)
r &= ~0x1f;
r |= 0xd3;
__asm__ __volatile__("msr cpsr, %0" : : "r"(r));
tegra_ll_delay_setup();
}
/* reset vector for the AVP, to be called from board reset vector */

View File

@ -158,6 +158,9 @@ static void start_cpu0_clocks(void)
reg = readl(TEGRA_CLK_RESET_BASE + CRC_CLK_OUT_ENB_L);
reg |= CRC_CLK_OUT_ENB_L_CPU;
writel(reg, TEGRA_CLK_RESET_BASE + CRC_CLK_OUT_ENB_L);
/* give clocks some time to settle */
tegra_ll_delay_usec(300);
}
static void maincomplex_powerup(void)
@ -175,6 +178,8 @@ static void maincomplex_powerup(void)
reg = readl(TEGRA_PMC_BASE + PMC_REMOVE_CLAMPING_CMD);
reg |= PMC_REMOVE_CLAMPING_CMD_CPU;
writel(reg, TEGRA_PMC_BASE + PMC_REMOVE_CLAMPING_CMD);
tegra_ll_delay_usec(1000);
}
}
void tegra_avp_reset_vector(uint32_t boarddata)