From patchwork Mon Oct 7 22:42:53 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tom Warren X-Patchwork-Id: 281284 X-Patchwork-Delegate: twarren@nvidia.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from theia.denx.de (theia.denx.de [85.214.87.163]) by ozlabs.org (Postfix) with ESMTP id 5C5402C00AB for ; Tue, 8 Oct 2013 10:11:07 +1100 (EST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id BD0FD4A09C; Tue, 8 Oct 2013 01:11:00 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id Oo0YOJ2GFKL4; Tue, 8 Oct 2013 01:11:00 +0200 (CEST) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 067914A09F; Tue, 8 Oct 2013 01:10:30 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id C14684A094 for ; Tue, 8 Oct 2013 01:10:19 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id iYmn-MuZE5AE for ; Tue, 8 Oct 2013 01:10:15 +0200 (CEST) X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 BL_NJABL=ERR(-1.5) (only DNSBL check requested) Received: from mail-pb0-f46.google.com (mail-pb0-f46.google.com [209.85.160.46]) by theia.denx.de (Postfix) with ESMTPS id B9E1C4A08A for ; Tue, 8 Oct 2013 01:10:05 +0200 (CEST) Received: by mail-pb0-f46.google.com with SMTP id rq2so7756693pbb.33 for ; Mon, 07 Oct 2013 16:10:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=7VgOQW/EmJaxPoDPDqD2BzVo2veqE3lsZNQF7d5PRJw=; b=Uat7DhmuEPQ6BgCu6tkT6V566UVDIa3XRraA3YIz2WLKepvdMk85W0RyWYrK0oAEVN nefdsuW40l+LbPYIsIw9iAJfUH8z6+5hlF0q0F/0nsa5MGRf2r5wwnLdeuWUPjncLvj/ WtRxAJ0Q3aULVInpy5wSH3Qq/CkdtDjvZGMuPONx6qlbhGcM1t2pH475ElzWoLlQrk9+ 9qNaz/ifk3C3llo4rnUZkYgV8AAhhazjN+47hOCzbqdW2a3LKQaXjRUbEIXvlg+EwQtp DSBrqz6ZqJqspS+DiQCrr5hmm/QXPRriu/qfm2QrOzDcdN4Xy6b94Gd2tECOF3t2DRU6 IGcQ== X-Received: by 10.66.144.102 with SMTP id sl6mr34450pab.96.1381187403722; Mon, 07 Oct 2013 16:10:03 -0700 (PDT) Received: from tom-ubuntu64.nvidia.com ([216.228.120.20]) by mx.google.com with ESMTPSA id yo2sm42436549pab.8.1969.12.31.16.00.00 (version=TLSv1 cipher=RC4-SHA bits=128/128); Mon, 07 Oct 2013 16:10:02 -0700 (PDT) From: Tom Warren To: u-boot@lists.denx.de Date: Mon, 7 Oct 2013 15:42:53 -0700 Message-Id: <1381185778-25722-3-git-send-email-twarren@nvidia.com> X-Mailer: git-send-email 1.8.1.5 In-Reply-To: <1381185778-25722-1-git-send-email-twarren@nvidia.com> References: <1381185778-25722-1-git-send-email-twarren@nvidia.com> X-NVConfidentiality: public Cc: twarren.nvidia@gmail.com, swarren@nvidia.com, jimmzhang@nvidia.com, Tom Warren , treding@nvidia.com Subject: [U-Boot] [PATCH 3/8] Tegra124: Add SPL/AVP (arm720t) cpu files X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.11 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: u-boot-bounces@lists.denx.de Errors-To: u-boot-bounces@lists.denx.de This provides SPL support for T124 boards - AVP early init, plus CPU (A15) init/jump to main U-Boot. Change-Id: I721f83f1d5fa549e0698e0cc76ab3e5ea11ba895 Signed-off-by: Tom Warren --- arch/arm/cpu/arm720t/tegra-common/cpu.c | 63 +++++-- arch/arm/cpu/arm720t/tegra-common/cpu.h | 6 +- arch/arm/cpu/arm720t/tegra124/Makefile | 31 ++++ arch/arm/cpu/arm720t/tegra124/config.mk | 7 + arch/arm/cpu/arm720t/tegra124/cpu.c | 301 ++++++++++++++++++++++++++++++++ 5 files changed, 387 insertions(+), 21 deletions(-) create mode 100644 arch/arm/cpu/arm720t/tegra124/Makefile create mode 100644 arch/arm/cpu/arm720t/tegra124/config.mk create mode 100644 arch/arm/cpu/arm720t/tegra124/cpu.c diff --git a/arch/arm/cpu/arm720t/tegra-common/cpu.c b/arch/arm/cpu/arm720t/tegra-common/cpu.c index 72c69b9..fbe553a 100644 --- a/arch/arm/cpu/arm720t/tegra-common/cpu.c +++ b/arch/arm/cpu/arm720t/tegra-common/cpu.c @@ -1,17 +1,8 @@ /* - * Copyright (c) 2010-2012, NVIDIA CORPORATION. All rights reserved. + * (C) Copyright 2013 + * NVIDIA Corporation * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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, see . + * SPDX-License-Identifier: GPL-2.0+ */ #include @@ -112,6 +103,22 @@ 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) @@ -146,6 +153,18 @@ int pllx_set_rate(struct clk_pll_simple *pll , u32 divn, u32 divm, debug(" pllx_set_rate entry\n"); +#if defined(CONFIG_TEGRA124) + struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; + + /* 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 /* T124 */ + /* 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 +181,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, as per JZ */ + 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; } @@ -208,7 +232,7 @@ void init_pllx(void) 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 */ + /* adjust PLLP_out1-4 on T3x/T1x4 */ if (soc_type >= CHIPID_TEGRA30) { debug(" init_pllx: adjusting PLLP out freqs\n"); adjust_pllp_out_freqs(); @@ -343,13 +367,14 @@ 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/T1x4). * 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) + if (soc_type == CHIPID_TEGRA30 || soc_type == CHIPID_TEGRA114 || + soc_type == CHIPID_TEGRA124) src = CLK_DIVIDER(NVBL_PLLP_KHZ, 204000); else if (soc_type == CHIPID_TEGRA20) src = CLK_DIVIDER(NVBL_PLLP_KHZ, 144000); diff --git a/arch/arm/cpu/arm720t/tegra-common/cpu.h b/arch/arm/cpu/arm720t/tegra-common/cpu.h index 60412c7..7e0b314 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-2013 * NVIDIA Corporation * * SPDX-License-Identifier: GPL-2.0+ @@ -12,7 +12,8 @@ #if defined(CONFIG_TEGRA20) #define NVBL_PLLP_KHZ (216000) -#elif defined(CONFIG_TEGRA30) || defined(CONFIG_TEGRA114) +#elif defined(CONFIG_TEGRA30) || defined(CONFIG_TEGRA114) || \ + defined(CONFIG_TEGRA124) #define NVBL_PLLP_KHZ (408000) #else #error "Unknown Tegra chip!" @@ -68,3 +69,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/tegra124/Makefile b/arch/arm/cpu/arm720t/tegra124/Makefile new file mode 100644 index 0000000..836eca0 --- /dev/null +++ b/arch/arm/cpu/arm720t/tegra124/Makefile @@ -0,0 +1,31 @@ +# +# (C) Copyright 2010-2013 +# NVIDIA Corporation +# (C) Copyright 2000-2008 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +include $(TOPDIR)/config.mk + +LIB = $(obj)lib$(SOC).o + +COBJS-y += cpu.o + +SRCS := $(COBJS-y:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS-y)) + +all: $(obj).depend $(LIB) + +$(LIB): $(OBJS) + $(call cmd_link_o_target, $(OBJS)) + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/arch/arm/cpu/arm720t/tegra124/config.mk b/arch/arm/cpu/arm720t/tegra124/config.mk new file mode 100644 index 0000000..5e10701 --- /dev/null +++ b/arch/arm/cpu/arm720t/tegra124/config.mk @@ -0,0 +1,7 @@ +# +# (C) Copyright 2010-2013 +# NVIDIA Corporation +# +# 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 0000000..b40bc6c --- /dev/null +++ b/arch/arm/cpu/arm720t/tegra124/cpu.c @@ -0,0 +1,301 @@ +/* + * (C) Copyright 2013 + * NVIDIA Corporation + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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 & (1 << 27)) == 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 = readl(&clkrst->crc_clk_cpu_cmplx_clr); + reg |= (CLR_CPU3_CLK_STP + CLR_CPU2_CLK_STP); + reg |= CLR_CPU1_CLK_STP; + writel((reg | CLR_CPU0_CLK_STP), &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); + reg |= (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); + reg |= (CLR_CPURESET1 + CLR_DBGRESET1 + CLR_CORERESET1 + CLR_CXRESET1); + reg |= (CLR_CPURESET2 + CLR_DBGRESET2 + CLR_CORERESET2 + CLR_CXRESET2); + reg |= (CLR_CPURESET3 + CLR_DBGRESET3 + CLR_CORERESET3 + CLR_CXRESET3); + reg |= (CLR_L2RESET + CLR_PRESETDBG); + writel(reg, &clkrst->crc_rst_cpug_cmplx_clr); +} + +/** + * The T1x4 requires some special clock initialization, including setting up + * the DVC I2C, turning on MSELECT and selecting the G CPU cluster + */ +void t1x4_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("t1x4_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("t1x4_init_clocks exit\n"); +} + +static int is_partition_powered(u32 mask) +{ + 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; +} + +static void power_partition(u32 status, u32 partid) +{ + struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE; + + debug("%s: status = %08X, part ID = %08X\n", __func__, status, partid); + /* Is the partition already on? */ + if (!is_partition_powered(status)) { + /* 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); + + /* Wait for the power to come up */ + while (!is_partition_powered(status)) + ; + + /* 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, CRAILID); + + /* Power up the fast cluster non-CPU partition */ + debug("powerup_cpus: C0NC\n"); + power_partition(C0NC, C0NCID); + + /* Power up the fast cluster CPU0 partition */ + debug("powerup_cpus: CE0\n"); + power_partition(CE0, CE0ID); + + 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); + + t1x4_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 VDD_CPU */ + enable_cpu_power_rail(); + + /* Get the CPU(s) running */ + enable_cpu_clocks(); + + /* Enable CoreSight */ + clock_enable_coresight(1); + + /* Take CPU(s) out of reset */ + remove_cpu_resets(); + + /* Set the entry point for CPU execution from reset */ + writel(reset_vector, EXCEP_VECTOR_CPU_RESET_VECTOR); + + /* If the CPU(s) don't already have power, power 'em up */ + powerup_cpus(); + debug("start_cpu exit, should continue @ reset_vector\n"); +} + +/* + * On poweron, AVP clock source (also called system clock) is set to PLLP_out0 + * with frequency set at 1MHz. Before initializing PLLP, we need to move the + * system clock's source to CLK_M temporarily. And then switch it to PLLP_out4 + * (204MHz) at a later time. + */ +void set_avp_clock_to_clkm(void) +{ + struct clk_rst_ctlr *clkrst = + (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; + u32 val; + + val = (SCLK_SOURCE_CLKM << SCLK_SWAKEUP_FIQ_SOURCE_SHIFT) | + (SCLK_SOURCE_CLKM << SCLK_SWAKEUP_IRQ_SOURCE_SHIFT) | + (SCLK_SOURCE_CLKM << SCLK_SWAKEUP_RUN_SOURCE_SHIFT) | + (SCLK_SOURCE_CLKM << SCLK_SWAKEUP_IDLE_SOURCE_SHIFT) | + (SCLK_SYS_STATE_RUN << SCLK_SYS_STATE_SHIFT); + writel(val, &clkrst->crc_sclk_brst_pol); + /* Wait 2-3us for the clock to flush thru the logic as per the TRM */ + udelay(3); +}