diff options
Diffstat (limited to 'arch/arm/cpu/arm720t')
-rw-r--r-- | arch/arm/cpu/arm720t/start.S | 26 | ||||
-rw-r--r-- | arch/arm/cpu/arm720t/tegra-common/cpu.c | 75 | ||||
-rw-r--r-- | arch/arm/cpu/arm720t/tegra-common/cpu.h | 12 | ||||
-rw-r--r-- | arch/arm/cpu/arm720t/tegra114/cpu.c | 48 | ||||
-rw-r--r-- | arch/arm/cpu/arm720t/tegra124/Makefile | 8 | ||||
-rw-r--r-- | arch/arm/cpu/arm720t/tegra124/config.mk | 7 | ||||
-rw-r--r-- | arch/arm/cpu/arm720t/tegra124/cpu.c | 265 | ||||
-rw-r--r-- | arch/arm/cpu/arm720t/tegra30/cpu.c | 14 |
8 files changed, 346 insertions, 109 deletions
diff --git a/arch/arm/cpu/arm720t/start.S b/arch/arm/cpu/arm720t/start.S index f180eb8aa6..1a34842690 100644 --- a/arch/arm/cpu/arm720t/start.S +++ b/arch/arm/cpu/arm720t/start.S @@ -67,32 +67,6 @@ _pad: .word 0x12345678 /* now 16*4=64 */ ************************************************************************* */ -.globl _TEXT_BASE -_TEXT_BASE: -#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_TEXT_BASE) - .word CONFIG_SPL_TEXT_BASE -#else - .word CONFIG_SYS_TEXT_BASE -#endif - -/* - * These are defined in the board-specific linker script. - * Subtracting _start from them lets the linker put their - * relative position in the executable instead of leaving - * them null. - */ -.globl _bss_start_ofs -_bss_start_ofs: - .word __bss_start - _start - -.globl _bss_end_ofs -_bss_end_ofs: - .word __bss_end - _start - -.globl _end_ofs -_end_ofs: - .word _end - _start - #ifdef CONFIG_USE_IRQ /* IRQ stack memory (calculated at run-time) */ .globl IRQ_STACK_START diff --git a/arch/arm/cpu/arm720t/tegra-common/cpu.c b/arch/arm/cpu/arm720t/tegra-common/cpu.c index 72c69b914c..2c5cd63917 100644 --- a/arch/arm/cpu/arm720t/tegra-common/cpu.c +++ b/arch/arm/cpu/arm720t/tegra-common/cpu.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2012, 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, @@ -112,24 +112,38 @@ struct clk_pll_table tegra_pll_x_table[TEGRA_SOC_CNT][CLOCK_OSC_FREQ_COUNT] = { { .n = 116, .m = 1, .p = 1 }, /* OSC: 12.0 MHz */ { .n = 108, .m = 2, .p = 1 }, /* OSC: 26.0 MHz */ }, + + /* + * T124: 700 MHz + * + * Register Field Bits Width + * ------------------------------ + * PLLX_BASE p 23:20 4 + * PLLX_BASE n 15: 8 8 + * PLLX_BASE m 7: 0 8 + */ + { + { .n = 108, .m = 1, .p = 1 }, /* OSC: 13.0 MHz */ + { .n = 73, .m = 1, .p = 1 }, /* OSC: 19.2 MHz */ + { .n = 116, .m = 1, .p = 1 }, /* OSC: 12.0 MHz */ + { .n = 108, .m = 2, .p = 1 }, /* OSC: 26.0 MHz */ + }, }; -void adjust_pllp_out_freqs(void) +static inline void pllx_set_iddq(void) { +#if defined(CONFIG_TEGRA124) struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; - struct clk_pll *pll = &clkrst->crc_pll[CLOCK_ID_PERIPH]; u32 reg; - /* Set T30 PLLP_OUT1, 2, 3 & 4 freqs to 9.6, 48, 102 & 204MHz */ - reg = readl(&pll->pll_out[0]); /* OUTA, contains OUT2 / OUT1 */ - reg |= (IN_408_OUT_48_DIVISOR << PLLP_OUT2_RATIO) | PLLP_OUT2_OVR - | (IN_408_OUT_9_6_DIVISOR << PLLP_OUT1_RATIO) | PLLP_OUT1_OVR; - writel(reg, &pll->pll_out[0]); - - reg = readl(&pll->pll_out[1]); /* OUTB, contains OUT4 / OUT3 */ - reg |= (IN_408_OUT_204_DIVISOR << PLLP_OUT4_RATIO) | PLLP_OUT4_OVR - | (IN_408_OUT_102_DIVISOR << PLLP_OUT3_RATIO) | PLLP_OUT3_OVR; - writel(reg, &pll->pll_out[1]); + /* Disable IDDQ */ + reg = readl(&clkrst->crc_pllx_misc3); + reg &= ~PLLX_IDDQ_MASK; + writel(reg, &clkrst->crc_pllx_misc3); + udelay(2); + debug("%s: IDDQ: PLLX IDDQ = 0x%08X\n", __func__, + readl(&clkrst->crc_pllx_misc3)); +#endif } int pllx_set_rate(struct clk_pll_simple *pll , u32 divn, u32 divm, @@ -146,6 +160,8 @@ int pllx_set_rate(struct clk_pll_simple *pll , u32 divn, u32 divm, debug(" pllx_set_rate entry\n"); + pllx_set_iddq(); + /* Set BYPASS, m, n and p to PLLX_BASE */ reg = PLL_BYPASS_MASK | (divm << PLL_DIVM_SHIFT); reg |= ((divn << PLL_DIVN_SHIFT) | (divp << PLL_DIVP_SHIFT)); @@ -162,18 +178,23 @@ int pllx_set_rate(struct clk_pll_simple *pll , u32 divn, u32 divm, reg |= (1 << PLL_DCCON_SHIFT); writel(reg, &pll->pll_misc); - /* Enable PLLX */ - reg = readl(&pll->pll_base); - reg |= PLL_ENABLE_MASK; - /* Disable BYPASS */ + reg = readl(&pll->pll_base); reg &= ~PLL_BYPASS_MASK; writel(reg, &pll->pll_base); + debug("pllx_set_rate: base = 0x%08X\n", reg); /* Set lock_enable to PLLX_MISC */ reg = readl(&pll->pll_misc); reg |= PLL_LOCK_ENABLE_MASK; writel(reg, &pll->pll_misc); + debug("pllx_set_rate: misc = 0x%08X\n", reg); + + /* Enable PLLX last, once it's all configured */ + reg = readl(&pll->pll_base); + reg |= PLL_ENABLE_MASK; + writel(reg, &pll->pll_base); + debug("pllx_set_rate: base final = 0x%08X\n", reg); return 0; } @@ -207,12 +228,6 @@ void init_pllx(void) /* set pllx */ sel = &tegra_pll_x_table[chip_sku][osc]; pllx_set_rate(pll, sel->n, sel->m, sel->p, sel->cpcon); - - /* adjust PLLP_out1-4 on T3x/T114 */ - if (soc_type >= CHIPID_TEGRA30) { - debug(" init_pllx: adjusting PLLP out freqs\n"); - adjust_pllp_out_freqs(); - } } void enable_cpu_clock(int enable) @@ -334,7 +349,6 @@ void reset_A9_cpu(int reset) void clock_enable_coresight(int enable) { u32 rst, src = 2; - int soc_type; debug("clock_enable_coresight entry\n"); clock_set_enable(PERIPH_ID_CORESIGHT, enable); @@ -343,20 +357,11 @@ void clock_enable_coresight(int enable) if (enable) { /* * Put CoreSight on PLLP_OUT0 and divide it down as per - * PLLP base frequency based on SoC type (T20/T30/T114). + * PLLP base frequency based on SoC type (T20/T30+). * Clock divider request would setup CSITE clock as 144MHz * for PLLP base 216MHz and 204MHz for PLLP base 408MHz */ - - soc_type = tegra_get_chip(); - if (soc_type == CHIPID_TEGRA30 || soc_type == CHIPID_TEGRA114) - src = CLK_DIVIDER(NVBL_PLLP_KHZ, 204000); - else if (soc_type == CHIPID_TEGRA20) - src = CLK_DIVIDER(NVBL_PLLP_KHZ, 144000); - else - printf("%s: Unknown SoC type %X!\n", - __func__, soc_type); - + src = CLK_DIVIDER(NVBL_PLLP_KHZ, CSITE_KHZ); clock_ll_set_source_divisor(PERIPH_ID_CSI, 0, src); /* Unlock the CPU CoreSight interfaces */ diff --git a/arch/arm/cpu/arm720t/tegra-common/cpu.h b/arch/arm/cpu/arm720t/tegra-common/cpu.h index 60412c7f87..b4ca44fce1 100644 --- a/arch/arm/cpu/arm720t/tegra-common/cpu.h +++ b/arch/arm/cpu/arm720t/tegra-common/cpu.h @@ -1,5 +1,5 @@ /* - * (C) Copyright 2010-2011 + * (C) Copyright 2010-2014 * NVIDIA Corporation <www.nvidia.com> * * SPDX-License-Identifier: GPL-2.0+ @@ -11,9 +11,12 @@ #define IO_STABILIZATION_DELAY (1000) #if defined(CONFIG_TEGRA20) -#define NVBL_PLLP_KHZ (216000) -#elif defined(CONFIG_TEGRA30) || defined(CONFIG_TEGRA114) -#define NVBL_PLLP_KHZ (408000) +#define NVBL_PLLP_KHZ 216000 +#define CSITE_KHZ 144000 +#elif defined(CONFIG_TEGRA30) || defined(CONFIG_TEGRA114) || \ + defined(CONFIG_TEGRA124) +#define NVBL_PLLP_KHZ 408000 +#define CSITE_KHZ 204000 #else #error "Unknown Tegra chip!" #endif @@ -68,3 +71,4 @@ int tegra_get_chip(void); int tegra_get_sku_info(void); int tegra_get_chip_sku(void); void adjust_pllp_out_freqs(void); +void pmic_enable_cpu_vdd(void); diff --git a/arch/arm/cpu/arm720t/tegra114/cpu.c b/arch/arm/cpu/arm720t/tegra114/cpu.c index 51ecff794f..d10b96a1d4 100644 --- a/arch/arm/cpu/arm720t/tegra114/cpu.c +++ b/arch/arm/cpu/arm720t/tegra114/cpu.c @@ -1,5 +1,5 @@ /* - * 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, @@ -68,7 +68,7 @@ static void enable_cpu_clocks(void) /* 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); @@ -126,18 +126,6 @@ void t114_init_clocks(void) /* 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"); @@ -204,45 +192,43 @@ void t114_init_clocks(void) 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 */ @@ -257,13 +243,13 @@ void powerup_cpus(void) /* 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) diff --git a/arch/arm/cpu/arm720t/tegra124/Makefile b/arch/arm/cpu/arm720t/tegra124/Makefile new file mode 100644 index 0000000000..61abf45d3d --- /dev/null +++ b/arch/arm/cpu/arm720t/tegra124/Makefile @@ -0,0 +1,8 @@ +# +# (C) Copyright 2013-2014 +# NVIDIA Corporation <www.nvidia.com> +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y += cpu.o diff --git a/arch/arm/cpu/arm720t/tegra124/config.mk b/arch/arm/cpu/arm720t/tegra124/config.mk new file mode 100644 index 0000000000..5e10701f0e --- /dev/null +++ b/arch/arm/cpu/arm720t/tegra124/config.mk @@ -0,0 +1,7 @@ +# +# (C) Copyright 2010-2013 +# NVIDIA Corporation <www.nvidia.com> +# +# SPDX-License-Identifier: GPL-2.0+ +#/ +USE_PRIVATE_LIBGCC = yes diff --git a/arch/arm/cpu/arm720t/tegra124/cpu.c b/arch/arm/cpu/arm720t/tegra124/cpu.c new file mode 100644 index 0000000000..c03aaf17e9 --- /dev/null +++ b/arch/arm/cpu/arm720t/tegra124/cpu.c @@ -0,0 +1,265 @@ +/* + * (C) Copyright 2013 + * NVIDIA Corporation <www.nvidia.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/ahb.h> +#include <asm/arch/clock.h> +#include <asm/arch/flow.h> +#include <asm/arch/pinmux.h> +#include <asm/arch/tegra.h> +#include <asm/arch-tegra/clk_rst.h> +#include <asm/arch-tegra/pmc.h> +#include <asm/arch-tegra/ap.h> +#include "../tegra-common/cpu.h" + +/* Tegra124-specific CPU init code */ + +static void enable_cpu_power_rail(void) +{ + struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE; + + 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); + + pmic_enable_cpu_vdd(); + + /* + * Set CPUPWRGOOD_TIMER - APB clock is 1/2 of SCLK (102MHz), + * set it for 5ms as per SysEng (102MHz*5ms = 510000 (7C830h). + */ + writel(0x7C830, &pmc->pmc_cpupwrgood_timer); + + /* Set polarity to 0 (normal) and enable CPUPWRREQ_OE */ + clrbits_le32(&pmc->pmc_cntrl, CPUPWRREQ_POL); + setbits_le32(&pmc->pmc_cntrl, CPUPWRREQ_OE); +} + +static void enable_cpu_clocks(void) +{ + struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; + u32 reg; + + debug("enable_cpu_clocks entry\n"); + + /* Wait for PLL-X to lock */ + do { + reg = readl(&clkrst->crc_pll_simple[SIMPLE_PLLX].pll_base); + debug("%s: PLLX base = 0x%08X\n", __func__, reg); + } while ((reg & PLL_LOCK_MASK) == 0); + + debug("%s: PLLX locked, delay for stable clocks\n", __func__); + /* Wait until all clocks are stable */ + udelay(PLL_STABILIZATION_DELAY); + + debug("%s: Setting CCLK_BURST and DIVIDER\n", __func__); + writel(CCLK_BURST_POLICY, &clkrst->crc_cclk_brst_pol); + writel(SUPER_CCLK_DIVIDER, &clkrst->crc_super_cclk_div); + + debug("%s: Enabling clock to all CPUs\n", __func__); + /* Enable the clock to all CPUs */ + reg = CLR_CPU3_CLK_STP | CLR_CPU2_CLK_STP | CLR_CPU1_CLK_STP | + CLR_CPU0_CLK_STP; + writel(reg, &clkrst->crc_clk_cpu_cmplx_clr); + + debug("%s: Enabling main CPU complex clocks\n", __func__); + /* Always enable the main CPU complex clocks */ + clock_enable(PERIPH_ID_CPU); + clock_enable(PERIPH_ID_CPULP); + clock_enable(PERIPH_ID_CPUG); + + debug("%s: Done\n", __func__); +} + +static void remove_cpu_resets(void) +{ + struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; + u32 reg; + + debug("remove_cpu_resets entry\n"); + + /* Take the slow and fast partitions out of reset */ + reg = CLR_NONCPURESET; + writel(reg, &clkrst->crc_rst_cpulp_cmplx_clr); + writel(reg, &clkrst->crc_rst_cpug_cmplx_clr); + + /* Clear the SW-controlled reset of the slow cluster */ + reg = CLR_CPURESET0 | CLR_DBGRESET0 | CLR_CORERESET0 | CLR_CXRESET0 | + CLR_L2RESET | CLR_PRESETDBG; + writel(reg, &clkrst->crc_rst_cpulp_cmplx_clr); + + /* Clear the SW-controlled reset of the fast cluster */ + reg = CLR_CPURESET0 | CLR_DBGRESET0 | CLR_CORERESET0 | CLR_CXRESET0 | + CLR_CPURESET1 | CLR_DBGRESET1 | CLR_CORERESET1 | CLR_CXRESET1 | + CLR_CPURESET2 | CLR_DBGRESET2 | CLR_CORERESET2 | CLR_CXRESET2 | + CLR_CPURESET3 | CLR_DBGRESET3 | CLR_CORERESET3 | CLR_CXRESET3 | + CLR_L2RESET | CLR_PRESETDBG; + writel(reg, &clkrst->crc_rst_cpug_cmplx_clr); +} + +/** + * The Tegra124 requires some special clock initialization, including setting up + * the DVC I2C, turning on MSELECT and selecting the G CPU cluster + */ +void tegra124_init_clocks(void) +{ + struct flow_ctlr *flow = (struct flow_ctlr *)NV_PA_FLOW_BASE; + struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE; + struct clk_rst_ctlr *clkrst = + (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; + u32 val; + + debug("tegra124_init_clocks entry\n"); + + /* Set active CPU cluster to G */ + clrbits_le32(&flow->cluster_control, 1); + + /* Change the oscillator drive strength */ + val = readl(&clkrst->crc_osc_ctrl); + val &= ~OSC_XOFS_MASK; + val |= (OSC_DRIVE_STRENGTH << OSC_XOFS_SHIFT); + writel(val, &clkrst->crc_osc_ctrl); + + /* Update same value in PMC_OSC_EDPD_OVER XOFS field for warmboot */ + val = readl(&pmc->pmc_osc_edpd_over); + val &= ~PMC_XOFS_MASK; + val |= (OSC_DRIVE_STRENGTH << PMC_XOFS_SHIFT); + writel(val, &pmc->pmc_osc_edpd_over); + + /* Set HOLD_CKE_LOW_EN to 1 */ + setbits_le32(&pmc->pmc_cntrl2, HOLD_CKE_LOW_EN); + + debug("Setting up PLLX\n"); + init_pllx(); + + val = (1 << CLK_SYS_RATE_AHB_RATE_SHIFT); + writel(val, &clkrst->crc_clk_sys_rate); + + /* Enable clocks to required peripherals. TBD - minimize this list */ + debug("Enabling clocks\n"); + + clock_set_enable(PERIPH_ID_CACHE2, 1); + clock_set_enable(PERIPH_ID_GPIO, 1); + clock_set_enable(PERIPH_ID_TMR, 1); + clock_set_enable(PERIPH_ID_CPU, 1); + clock_set_enable(PERIPH_ID_EMC, 1); + clock_set_enable(PERIPH_ID_I2C5, 1); + clock_set_enable(PERIPH_ID_APBDMA, 1); + clock_set_enable(PERIPH_ID_MEM, 1); + clock_set_enable(PERIPH_ID_CORESIGHT, 1); + clock_set_enable(PERIPH_ID_MSELECT, 1); + clock_set_enable(PERIPH_ID_DVFS, 1); + + /* + * 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, + CLK_DIVIDER(NVBL_PLLP_KHZ, 102000)); + + /* Give clock time to stabilize */ + udelay(IO_STABILIZATION_DELAY); + + /* I2C5 (DVC) gets CLK_M and a divisor of 17 */ + clock_ll_set_source_divisor(PERIPH_ID_I2C5, 3, 16); + + /* Give clock time to stabilize */ + udelay(IO_STABILIZATION_DELAY); + + /* Take required peripherals out of reset */ + debug("Taking periphs out of reset\n"); + reset_set_enable(PERIPH_ID_CACHE2, 0); + reset_set_enable(PERIPH_ID_GPIO, 0); + reset_set_enable(PERIPH_ID_TMR, 0); + reset_set_enable(PERIPH_ID_COP, 0); + reset_set_enable(PERIPH_ID_EMC, 0); + reset_set_enable(PERIPH_ID_I2C5, 0); + reset_set_enable(PERIPH_ID_APBDMA, 0); + reset_set_enable(PERIPH_ID_MEM, 0); + reset_set_enable(PERIPH_ID_CORESIGHT, 0); + reset_set_enable(PERIPH_ID_MSELECT, 0); + reset_set_enable(PERIPH_ID_DVFS, 0); + + debug("tegra124_init_clocks exit\n"); +} + +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 & (1 << partid)); +} + +static void power_partition(u32 partid) +{ + struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE; + + debug("%s: part ID = %08X\n", __func__, partid); + /* Is the partition already on? */ + if (!is_partition_powered(partid)) { + /* No, toggle the partition power state (OFF -> ON) */ + debug("power_partition, toggling state\n"); + writel(START_CP | partid, &pmc->pmc_pwrgate_toggle); + + /* Wait for the power to come up */ + while (!is_partition_powered(partid)) + ; + + /* Give I/O signals time to stabilize */ + udelay(IO_STABILIZATION_DELAY); + } +} + +void powerup_cpus(void) +{ + debug("powerup_cpus entry\n"); + + /* We boot to the fast cluster */ + debug("powerup_cpus entry: G cluster\n"); + + /* Power up the fast cluster rail partition */ + debug("powerup_cpus: CRAIL\n"); + power_partition(CRAIL); + + /* Power up the fast cluster non-CPU partition */ + debug("powerup_cpus: C0NC\n"); + power_partition(C0NC); + + /* Power up the fast cluster CPU0 partition */ + debug("powerup_cpus: CE0\n"); + power_partition(CE0); + + debug("powerup_cpus: done\n"); +} + +void start_cpu(u32 reset_vector) +{ + struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE; + + debug("start_cpu entry, reset_vector = %x\n", reset_vector); + + tegra124_init_clocks(); + + /* Set power-gating timer multiplier */ + clrbits_le32(&pmc->pmc_pwrgate_timer_mult, TIMER_MULT_MASK); + setbits_le32(&pmc->pmc_pwrgate_timer_mult, MULT_8); + + enable_cpu_power_rail(); + enable_cpu_clocks(); + clock_enable_coresight(1); + remove_cpu_resets(); + writel(reset_vector, EXCEP_VECTOR_CPU_RESET_VECTOR); + powerup_cpus(); + debug("start_cpu exit, should continue @ reset_vector\n"); +} diff --git a/arch/arm/cpu/arm720t/tegra30/cpu.c b/arch/arm/cpu/arm720t/tegra30/cpu.c index e162357484..a80648389c 100644 --- a/arch/arm/cpu/arm720t/tegra30/cpu.c +++ b/arch/arm/cpu/arm720t/tegra30/cpu.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2012, 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, @@ -84,18 +84,6 @@ void t30_init_clocks(void) /* Set active CPU cluster to G */ clrbits_le32(flow->cluster_control, 1 << 0); - /* - * 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); val = (0 << CLK_SYS_RATE_HCLK_DISABLE_SHIFT) | |