/*
- * Copyright (c) 2010-2013, NVIDIA CORPORATION. All rights reserved.
+ * Copyright (c) 2010-2014, NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
debug("enable_cpu_power_rail entry\n");
/* un-tristate PWR_I2C SCL/SDA, rest of the defaults are correct */
- pinmux_tristate_disable(PINGRP_PWR_I2C_SCL);
- pinmux_tristate_disable(PINGRP_PWR_I2C_SDA);
+ pinmux_tristate_disable(PMUX_PINGRP_PWR_I2C_SCL_PZ6);
+ pinmux_tristate_disable(PMUX_PINGRP_PWR_I2C_SDA_PZ7);
/*
* Set CPUPWRGOOD_TIMER - APB clock is 1/2 of SCLK (102MHz),
/* Wait for PLL-X to lock */
do {
reg = readl(&clkrst->crc_pll_simple[SIMPLE_PLLX].pll_base);
- } while ((reg & (1 << 27)) == 0);
+ } while ((reg & PLL_LOCK_MASK) == 0);
/* Wait until all clocks are stable */
udelay(PLL_STABILIZATION_DELAY);
/* Set active CPU cluster to G */
clrbits_le32(&flow->cluster_control, 1);
- /*
- * Switch system clock to PLLP_OUT4 (108 MHz), AVP will now run
- * at 108 MHz. This is glitch free as only the source is changed, no
- * special precaution needed.
- */
- val = (SCLK_SOURCE_PLLP_OUT4 << SCLK_SWAKEUP_FIQ_SOURCE_SHIFT) |
- (SCLK_SOURCE_PLLP_OUT4 << SCLK_SWAKEUP_IRQ_SOURCE_SHIFT) |
- (SCLK_SOURCE_PLLP_OUT4 << SCLK_SWAKEUP_RUN_SOURCE_SHIFT) |
- (SCLK_SOURCE_PLLP_OUT4 << SCLK_SWAKEUP_IDLE_SOURCE_SHIFT) |
- (SCLK_SYS_STATE_RUN << SCLK_SYS_STATE_SHIFT);
- writel(val, &clkrst->crc_sclk_brst_pol);
-
writel(SUPER_SCLK_ENB_MASK, &clkrst->crc_super_sclk_div);
debug("Setting up PLLX\n");
clock_set_enable(PERIPH_ID_MC1, 1);
clock_set_enable(PERIPH_ID_DVFS, 1);
- /* Switch MSELECT clock to PLLP (00) */
- clock_ll_set_source(PERIPH_ID_MSELECT, 0);
-
/*
- * Clock divider request for 102MHz would setup MSELECT clock as
- * 102MHz for PLLP base 408MHz
+ * Set MSELECT clock source as PLLP (00), and ask for a clock
+ * divider that would set the MSELECT clock at 102MHz for a
+ * PLLP base of 408MHz.
*/
clock_ll_set_source_divisor(PERIPH_ID_MSELECT, 0,
- (NVBL_PLLP_KHZ/102000));
+ CLK_DIVIDER(NVBL_PLLP_KHZ, 102000));
/* I2C5 (DVC) gets CLK_M and a divisor of 17 */
clock_ll_set_source_divisor(PERIPH_ID_I2C5, 3, 16);
reset_set_enable(PERIPH_ID_MSELECT, 0);
reset_set_enable(PERIPH_ID_EMC1, 0);
reset_set_enable(PERIPH_ID_MC1, 0);
+ reset_set_enable(PERIPH_ID_DVFS, 0);
debug("t114_init_clocks exit\n");
}
-static int is_partition_powered(u32 mask)
+static bool is_partition_powered(u32 partid)
{
struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE;
u32 reg;
/* Get power gate status */
reg = readl(&pmc->pmc_pwrgate_status);
- return (reg & mask) == mask;
+ return !!(reg & (1 << partid));
}
-static int is_clamp_enabled(u32 mask)
+static bool is_clamp_enabled(u32 partid)
{
struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE;
u32 reg;
- /* Get clamp status. TODO: Add pmc_clamp_status alias to pmc.h */
- reg = readl(&pmc->pmc_pwrgate_timer_on);
- return (reg & mask) == mask;
+ /* Get clamp status. */
+ reg = readl(&pmc->pmc_clamp_status);
+ return !!(reg & (1 << partid));
}
-static void power_partition(u32 status, u32 partid)
+static void power_partition(u32 partid)
{
struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE;
- debug("%s: status = %08X, part ID = %08X\n", __func__, status, partid);
+ debug("%s: part ID = %08X\n", __func__, partid);
/* Is the partition already on? */
- if (!is_partition_powered(status)) {
+ if (!is_partition_powered(partid)) {
/* No, toggle the partition power state (OFF -> ON) */
debug("power_partition, toggling state\n");
- clrbits_le32(&pmc->pmc_pwrgate_toggle, 0x1F);
- setbits_le32(&pmc->pmc_pwrgate_toggle, partid);
- setbits_le32(&pmc->pmc_pwrgate_toggle, START_CP);
+ writel(START_CP | partid, &pmc->pmc_pwrgate_toggle);
/* Wait for the power to come up */
- while (!is_partition_powered(status))
+ while (!is_partition_powered(partid))
;
/* Wait for the clamp status to be cleared */
- while (is_clamp_enabled(status))
+ while (is_clamp_enabled(partid))
;
/* Give I/O signals time to stabilize */
/* We boot to the fast cluster */
debug("powerup_cpus entry: G cluster\n");
/* Power up the fast cluster rail partition */
- power_partition(CRAIL, CRAILID);
+ power_partition(CRAIL);
/* Power up the fast cluster non-CPU partition */
- power_partition(C0NC, C0NCID);
+ power_partition(C0NC);
/* Power up the fast cluster CPU0 partition */
- power_partition(CE0, CE0ID);
+ power_partition(CE0);
}
void start_cpu(u32 reset_vector)
{
+ u32 imme, inst;
+
debug("start_cpu entry, reset_vector = %x\n", reset_vector);
t114_init_clocks();
/* Take CPU(s) out of reset */
remove_cpu_resets();
+ /* Set the entry point for CPU execution from reset */
+
/*
- * Set the entry point for CPU execution from reset,
- * if it's a non-zero value.
+ * A01P with patched boot ROM; vector hard-coded to 0x4003fffc.
+ * See nvbug 1193357 for details.
*/
- if (reset_vector)
- writel(reset_vector, EXCEP_VECTOR_CPU_RESET_VECTOR);
+
+ /* mov r0, #lsb(reset_vector) */
+ imme = reset_vector & 0xffff;
+ inst = imme & 0xfff;
+ inst |= ((imme >> 12) << 16);
+ inst |= 0xe3000000;
+ writel(inst, 0x4003fff0);
+
+ /* movt r0, #msb(reset_vector) */
+ imme = (reset_vector >> 16) & 0xffff;
+ inst = imme & 0xfff;
+ inst |= ((imme >> 12) << 16);
+ inst |= 0xe3400000;
+ writel(inst, 0x4003fff4);
+
+ /* bx r0 */
+ writel(0xe12fff10, 0x4003fff8);
+
+ /* b -12 */
+ imme = (u32)-20;
+ inst = (imme >> 2) & 0xffffff;
+ inst |= 0xea000000;
+ writel(inst, 0x4003fffc);
+
+ /* Write to orignal location for compatibility */
+ writel(reset_vector, EXCEP_VECTOR_CPU_RESET_VECTOR);
/* If the CPU(s) don't already have power, power 'em up */
powerup_cpus();