109f455dcSMasahiro Yamada /* 2*7aaa5a60STom Warren * Copyright (c) 2010-2015, NVIDIA CORPORATION. All rights reserved. 309f455dcSMasahiro Yamada * 409f455dcSMasahiro Yamada * This program is free software; you can redistribute it and/or modify it 509f455dcSMasahiro Yamada * under the terms and conditions of the GNU General Public License, 609f455dcSMasahiro Yamada * version 2, as published by the Free Software Foundation. 709f455dcSMasahiro Yamada * 809f455dcSMasahiro Yamada * This program is distributed in the hope it will be useful, but WITHOUT 909f455dcSMasahiro Yamada * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1009f455dcSMasahiro Yamada * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 1109f455dcSMasahiro Yamada * more details. 1209f455dcSMasahiro Yamada * 1309f455dcSMasahiro Yamada * You should have received a copy of the GNU General Public License 1409f455dcSMasahiro Yamada * along with this program. If not, see <http://www.gnu.org/licenses/>. 1509f455dcSMasahiro Yamada */ 1609f455dcSMasahiro Yamada 1709f455dcSMasahiro Yamada #include <common.h> 1809f455dcSMasahiro Yamada #include <asm/io.h> 1909f455dcSMasahiro Yamada #include <asm/arch/clock.h> 2009f455dcSMasahiro Yamada #include <asm/arch/gp_padctrl.h> 2109f455dcSMasahiro Yamada #include <asm/arch/pinmux.h> 2209f455dcSMasahiro Yamada #include <asm/arch/tegra.h> 2309f455dcSMasahiro Yamada #include <asm/arch-tegra/clk_rst.h> 2409f455dcSMasahiro Yamada #include <asm/arch-tegra/pmc.h> 2509f455dcSMasahiro Yamada #include <asm/arch-tegra/scu.h> 2609f455dcSMasahiro Yamada #include "cpu.h" 2709f455dcSMasahiro Yamada 2809f455dcSMasahiro Yamada int get_num_cpus(void) 2909f455dcSMasahiro Yamada { 3009f455dcSMasahiro Yamada struct apb_misc_gp_ctlr *gp; 3109f455dcSMasahiro Yamada uint rev; 32*7aaa5a60STom Warren debug("%s entry\n", __func__); 3309f455dcSMasahiro Yamada 3409f455dcSMasahiro Yamada gp = (struct apb_misc_gp_ctlr *)NV_PA_APB_MISC_GP_BASE; 3509f455dcSMasahiro Yamada rev = (readl(&gp->hidrev) & HIDREV_CHIPID_MASK) >> HIDREV_CHIPID_SHIFT; 3609f455dcSMasahiro Yamada 3709f455dcSMasahiro Yamada switch (rev) { 3809f455dcSMasahiro Yamada case CHIPID_TEGRA20: 3909f455dcSMasahiro Yamada return 2; 4009f455dcSMasahiro Yamada break; 4109f455dcSMasahiro Yamada case CHIPID_TEGRA30: 4209f455dcSMasahiro Yamada case CHIPID_TEGRA114: 43*7aaa5a60STom Warren case CHIPID_TEGRA124: 44*7aaa5a60STom Warren case CHIPID_TEGRA210: 4509f455dcSMasahiro Yamada default: 4609f455dcSMasahiro Yamada return 4; 4709f455dcSMasahiro Yamada break; 4809f455dcSMasahiro Yamada } 4909f455dcSMasahiro Yamada } 5009f455dcSMasahiro Yamada 5109f455dcSMasahiro Yamada /* 5209f455dcSMasahiro Yamada * Timing tables for each SOC for all four oscillator options. 5309f455dcSMasahiro Yamada */ 5409f455dcSMasahiro Yamada struct clk_pll_table tegra_pll_x_table[TEGRA_SOC_CNT][CLOCK_OSC_FREQ_COUNT] = { 5509f455dcSMasahiro Yamada /* 5609f455dcSMasahiro Yamada * T20: 1 GHz 5709f455dcSMasahiro Yamada * 5809f455dcSMasahiro Yamada * Register Field Bits Width 5909f455dcSMasahiro Yamada * ------------------------------ 6009f455dcSMasahiro Yamada * PLLX_BASE p 22:20 3 6109f455dcSMasahiro Yamada * PLLX_BASE n 17: 8 10 6209f455dcSMasahiro Yamada * PLLX_BASE m 4: 0 5 6309f455dcSMasahiro Yamada * PLLX_MISC cpcon 11: 8 4 6409f455dcSMasahiro Yamada */ 6509f455dcSMasahiro Yamada { 6609f455dcSMasahiro Yamada { .n = 1000, .m = 13, .p = 0, .cpcon = 12 }, /* OSC: 13.0 MHz */ 6709f455dcSMasahiro Yamada { .n = 625, .m = 12, .p = 0, .cpcon = 8 }, /* OSC: 19.2 MHz */ 6809f455dcSMasahiro Yamada { .n = 1000, .m = 12, .p = 0, .cpcon = 12 }, /* OSC: 12.0 MHz */ 6909f455dcSMasahiro Yamada { .n = 1000, .m = 26, .p = 0, .cpcon = 12 }, /* OSC: 26.0 MHz */ 7009f455dcSMasahiro Yamada }, 7109f455dcSMasahiro Yamada /* 7209f455dcSMasahiro Yamada * T25: 1.2 GHz 7309f455dcSMasahiro Yamada * 7409f455dcSMasahiro Yamada * Register Field Bits Width 7509f455dcSMasahiro Yamada * ------------------------------ 7609f455dcSMasahiro Yamada * PLLX_BASE p 22:20 3 7709f455dcSMasahiro Yamada * PLLX_BASE n 17: 8 10 7809f455dcSMasahiro Yamada * PLLX_BASE m 4: 0 5 7909f455dcSMasahiro Yamada * PLLX_MISC cpcon 11: 8 4 8009f455dcSMasahiro Yamada */ 8109f455dcSMasahiro Yamada { 8209f455dcSMasahiro Yamada { .n = 923, .m = 10, .p = 0, .cpcon = 12 }, /* OSC: 13.0 MHz */ 8309f455dcSMasahiro Yamada { .n = 750, .m = 12, .p = 0, .cpcon = 8 }, /* OSC: 19.2 MHz */ 8409f455dcSMasahiro Yamada { .n = 600, .m = 6, .p = 0, .cpcon = 12 }, /* OSC: 12.0 MHz */ 8509f455dcSMasahiro Yamada { .n = 600, .m = 13, .p = 0, .cpcon = 12 }, /* OSC: 26.0 MHz */ 8609f455dcSMasahiro Yamada }, 8709f455dcSMasahiro Yamada /* 8809f455dcSMasahiro Yamada * T30: 600 MHz 8909f455dcSMasahiro Yamada * 9009f455dcSMasahiro Yamada * Register Field Bits Width 9109f455dcSMasahiro Yamada * ------------------------------ 9209f455dcSMasahiro Yamada * PLLX_BASE p 22:20 3 9309f455dcSMasahiro Yamada * PLLX_BASE n 17: 8 10 9409f455dcSMasahiro Yamada * PLLX_BASE m 4: 0 5 9509f455dcSMasahiro Yamada * PLLX_MISC cpcon 11: 8 4 9609f455dcSMasahiro Yamada */ 9709f455dcSMasahiro Yamada { 9809f455dcSMasahiro Yamada { .n = 600, .m = 13, .p = 0, .cpcon = 8 }, /* OSC: 13.0 MHz */ 9909f455dcSMasahiro Yamada { .n = 500, .m = 16, .p = 0, .cpcon = 8 }, /* OSC: 19.2 MHz */ 10009f455dcSMasahiro Yamada { .n = 600, .m = 12, .p = 0, .cpcon = 8 }, /* OSC: 12.0 MHz */ 10109f455dcSMasahiro Yamada { .n = 600, .m = 26, .p = 0, .cpcon = 8 }, /* OSC: 26.0 MHz */ 10209f455dcSMasahiro Yamada }, 10309f455dcSMasahiro Yamada /* 10409f455dcSMasahiro Yamada * T114: 700 MHz 10509f455dcSMasahiro Yamada * 10609f455dcSMasahiro Yamada * Register Field Bits Width 10709f455dcSMasahiro Yamada * ------------------------------ 10809f455dcSMasahiro Yamada * PLLX_BASE p 23:20 4 10909f455dcSMasahiro Yamada * PLLX_BASE n 15: 8 8 11009f455dcSMasahiro Yamada * PLLX_BASE m 7: 0 8 11109f455dcSMasahiro Yamada */ 11209f455dcSMasahiro Yamada { 11309f455dcSMasahiro Yamada { .n = 108, .m = 1, .p = 1 }, /* OSC: 13.0 MHz */ 11409f455dcSMasahiro Yamada { .n = 73, .m = 1, .p = 1 }, /* OSC: 19.2 MHz */ 11509f455dcSMasahiro Yamada { .n = 116, .m = 1, .p = 1 }, /* OSC: 12.0 MHz */ 11609f455dcSMasahiro Yamada { .n = 108, .m = 2, .p = 1 }, /* OSC: 26.0 MHz */ 11709f455dcSMasahiro Yamada }, 11809f455dcSMasahiro Yamada 11909f455dcSMasahiro Yamada /* 12009f455dcSMasahiro Yamada * T124: 700 MHz 12109f455dcSMasahiro Yamada * 12209f455dcSMasahiro Yamada * Register Field Bits Width 12309f455dcSMasahiro Yamada * ------------------------------ 12409f455dcSMasahiro Yamada * PLLX_BASE p 23:20 4 12509f455dcSMasahiro Yamada * PLLX_BASE n 15: 8 8 12609f455dcSMasahiro Yamada * PLLX_BASE m 7: 0 8 12709f455dcSMasahiro Yamada */ 12809f455dcSMasahiro Yamada { 12909f455dcSMasahiro Yamada { .n = 108, .m = 1, .p = 1 }, /* OSC: 13.0 MHz */ 13009f455dcSMasahiro Yamada { .n = 73, .m = 1, .p = 1 }, /* OSC: 19.2 MHz */ 13109f455dcSMasahiro Yamada { .n = 116, .m = 1, .p = 1 }, /* OSC: 12.0 MHz */ 13209f455dcSMasahiro Yamada { .n = 108, .m = 2, .p = 1 }, /* OSC: 26.0 MHz */ 13309f455dcSMasahiro Yamada }, 134*7aaa5a60STom Warren 135*7aaa5a60STom Warren /* 136*7aaa5a60STom Warren * T210: 700 MHz 137*7aaa5a60STom Warren * 138*7aaa5a60STom Warren * Register Field Bits Width 139*7aaa5a60STom Warren * ------------------------------ 140*7aaa5a60STom Warren * PLLX_BASE p 24:20 5 141*7aaa5a60STom Warren * PLLX_BASE n 15: 8 8 142*7aaa5a60STom Warren * PLLX_BASE m 7: 0 8 143*7aaa5a60STom Warren */ 144*7aaa5a60STom Warren { 145*7aaa5a60STom Warren { .n = 108, .m = 1, .p = 1 }, /* OSC: 13.0 MHz = 702 MHz*/ 146*7aaa5a60STom Warren { .n = 73, .m = 1, .p = 1 }, /* OSC: 19.2 MHz = 700.8 MHz*/ 147*7aaa5a60STom Warren { .n = 116, .m = 1, .p = 1 }, /* OSC: 12.0 MHz = 696 MHz*/ 148*7aaa5a60STom Warren { .n = 108, .m = 2, .p = 1 }, /* OSC: 26.0 MHz = 702 MHz*/ 149*7aaa5a60STom Warren }, 15009f455dcSMasahiro Yamada }; 15109f455dcSMasahiro Yamada 15209f455dcSMasahiro Yamada static inline void pllx_set_iddq(void) 15309f455dcSMasahiro Yamada { 154*7aaa5a60STom Warren #if defined(CONFIG_TEGRA124) || defined(CONFIG_TEGRA210) 15509f455dcSMasahiro Yamada struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; 15609f455dcSMasahiro Yamada u32 reg; 157*7aaa5a60STom Warren debug("%s entry\n", __func__); 15809f455dcSMasahiro Yamada 15909f455dcSMasahiro Yamada /* Disable IDDQ */ 16009f455dcSMasahiro Yamada reg = readl(&clkrst->crc_pllx_misc3); 16109f455dcSMasahiro Yamada reg &= ~PLLX_IDDQ_MASK; 16209f455dcSMasahiro Yamada writel(reg, &clkrst->crc_pllx_misc3); 16309f455dcSMasahiro Yamada udelay(2); 16409f455dcSMasahiro Yamada debug("%s: IDDQ: PLLX IDDQ = 0x%08X\n", __func__, 16509f455dcSMasahiro Yamada readl(&clkrst->crc_pllx_misc3)); 16609f455dcSMasahiro Yamada #endif 16709f455dcSMasahiro Yamada } 16809f455dcSMasahiro Yamada 16909f455dcSMasahiro Yamada int pllx_set_rate(struct clk_pll_simple *pll , u32 divn, u32 divm, 17009f455dcSMasahiro Yamada u32 divp, u32 cpcon) 17109f455dcSMasahiro Yamada { 17209f455dcSMasahiro Yamada int chip = tegra_get_chip(); 17309f455dcSMasahiro Yamada u32 reg; 174*7aaa5a60STom Warren debug("%s entry\n", __func__); 17509f455dcSMasahiro Yamada 17609f455dcSMasahiro Yamada /* If PLLX is already enabled, just return */ 17709f455dcSMasahiro Yamada if (readl(&pll->pll_base) & PLL_ENABLE_MASK) { 178*7aaa5a60STom Warren debug("%s: PLLX already enabled, returning\n", __func__); 17909f455dcSMasahiro Yamada return 0; 18009f455dcSMasahiro Yamada } 18109f455dcSMasahiro Yamada 18209f455dcSMasahiro Yamada pllx_set_iddq(); 18309f455dcSMasahiro Yamada 18409f455dcSMasahiro Yamada /* Set BYPASS, m, n and p to PLLX_BASE */ 18509f455dcSMasahiro Yamada reg = PLL_BYPASS_MASK | (divm << PLL_DIVM_SHIFT); 18609f455dcSMasahiro Yamada reg |= ((divn << PLL_DIVN_SHIFT) | (divp << PLL_DIVP_SHIFT)); 18709f455dcSMasahiro Yamada writel(reg, &pll->pll_base); 18809f455dcSMasahiro Yamada 18909f455dcSMasahiro Yamada /* Set cpcon to PLLX_MISC */ 19009f455dcSMasahiro Yamada if (chip == CHIPID_TEGRA20 || chip == CHIPID_TEGRA30) 19109f455dcSMasahiro Yamada reg = (cpcon << PLL_CPCON_SHIFT); 19209f455dcSMasahiro Yamada else 19309f455dcSMasahiro Yamada reg = 0; 19409f455dcSMasahiro Yamada 19509f455dcSMasahiro Yamada /* Set dccon to PLLX_MISC if freq > 600MHz */ 19609f455dcSMasahiro Yamada if (divn > 600) 19709f455dcSMasahiro Yamada reg |= (1 << PLL_DCCON_SHIFT); 19809f455dcSMasahiro Yamada writel(reg, &pll->pll_misc); 19909f455dcSMasahiro Yamada 20009f455dcSMasahiro Yamada /* Disable BYPASS */ 20109f455dcSMasahiro Yamada reg = readl(&pll->pll_base); 20209f455dcSMasahiro Yamada reg &= ~PLL_BYPASS_MASK; 20309f455dcSMasahiro Yamada writel(reg, &pll->pll_base); 204*7aaa5a60STom Warren debug("%s: base = 0x%08X\n", __func__, reg); 20509f455dcSMasahiro Yamada 20609f455dcSMasahiro Yamada /* Set lock_enable to PLLX_MISC */ 20709f455dcSMasahiro Yamada reg = readl(&pll->pll_misc); 20809f455dcSMasahiro Yamada reg |= PLL_LOCK_ENABLE_MASK; 20909f455dcSMasahiro Yamada writel(reg, &pll->pll_misc); 210*7aaa5a60STom Warren debug("%s: misc = 0x%08X\n", __func__, reg); 21109f455dcSMasahiro Yamada 21209f455dcSMasahiro Yamada /* Enable PLLX last, once it's all configured */ 21309f455dcSMasahiro Yamada reg = readl(&pll->pll_base); 21409f455dcSMasahiro Yamada reg |= PLL_ENABLE_MASK; 21509f455dcSMasahiro Yamada writel(reg, &pll->pll_base); 216*7aaa5a60STom Warren debug("%s: base final = 0x%08X\n", __func__, reg); 21709f455dcSMasahiro Yamada 21809f455dcSMasahiro Yamada return 0; 21909f455dcSMasahiro Yamada } 22009f455dcSMasahiro Yamada 22109f455dcSMasahiro Yamada void init_pllx(void) 22209f455dcSMasahiro Yamada { 22309f455dcSMasahiro Yamada struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; 22409f455dcSMasahiro Yamada struct clk_pll_simple *pll = &clkrst->crc_pll_simple[SIMPLE_PLLX]; 22509f455dcSMasahiro Yamada int soc_type, sku_info, chip_sku; 22609f455dcSMasahiro Yamada enum clock_osc_freq osc; 22709f455dcSMasahiro Yamada struct clk_pll_table *sel; 228*7aaa5a60STom Warren debug("%s entry\n", __func__); 22909f455dcSMasahiro Yamada 23009f455dcSMasahiro Yamada /* get SOC (chip) type */ 23109f455dcSMasahiro Yamada soc_type = tegra_get_chip(); 232*7aaa5a60STom Warren debug("%s: SoC = 0x%02X\n", __func__, soc_type); 23309f455dcSMasahiro Yamada 23409f455dcSMasahiro Yamada /* get SKU info */ 23509f455dcSMasahiro Yamada sku_info = tegra_get_sku_info(); 236*7aaa5a60STom Warren debug("%s: SKU info byte = 0x%02X\n", __func__, sku_info); 23709f455dcSMasahiro Yamada 23809f455dcSMasahiro Yamada /* get chip SKU, combo of the above info */ 23909f455dcSMasahiro Yamada chip_sku = tegra_get_chip_sku(); 240*7aaa5a60STom Warren debug("%s: Chip SKU = %d\n", __func__, chip_sku); 24109f455dcSMasahiro Yamada 24209f455dcSMasahiro Yamada /* get osc freq */ 24309f455dcSMasahiro Yamada osc = clock_get_osc_freq(); 244*7aaa5a60STom Warren debug("%s: osc = %d\n", __func__, osc); 24509f455dcSMasahiro Yamada 24609f455dcSMasahiro Yamada /* set pllx */ 24709f455dcSMasahiro Yamada sel = &tegra_pll_x_table[chip_sku][osc]; 24809f455dcSMasahiro Yamada pllx_set_rate(pll, sel->n, sel->m, sel->p, sel->cpcon); 24909f455dcSMasahiro Yamada } 25009f455dcSMasahiro Yamada 25109f455dcSMasahiro Yamada void enable_cpu_clock(int enable) 25209f455dcSMasahiro Yamada { 25309f455dcSMasahiro Yamada struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; 25409f455dcSMasahiro Yamada u32 clk; 255*7aaa5a60STom Warren debug("%s entry\n", __func__); 25609f455dcSMasahiro Yamada 25709f455dcSMasahiro Yamada /* 25809f455dcSMasahiro Yamada * NOTE: 25909f455dcSMasahiro Yamada * Regardless of whether the request is to enable or disable the CPU 26009f455dcSMasahiro Yamada * clock, every processor in the CPU complex except the master (CPU 0) 26109f455dcSMasahiro Yamada * will have it's clock stopped because the AVP only talks to the 26209f455dcSMasahiro Yamada * master. 26309f455dcSMasahiro Yamada */ 26409f455dcSMasahiro Yamada 26509f455dcSMasahiro Yamada if (enable) { 26609f455dcSMasahiro Yamada /* Initialize PLLX */ 26709f455dcSMasahiro Yamada init_pllx(); 26809f455dcSMasahiro Yamada 26909f455dcSMasahiro Yamada /* Wait until all clocks are stable */ 27009f455dcSMasahiro Yamada udelay(PLL_STABILIZATION_DELAY); 27109f455dcSMasahiro Yamada 27209f455dcSMasahiro Yamada writel(CCLK_BURST_POLICY, &clkrst->crc_cclk_brst_pol); 27309f455dcSMasahiro Yamada writel(SUPER_CCLK_DIVIDER, &clkrst->crc_super_cclk_div); 27409f455dcSMasahiro Yamada } 27509f455dcSMasahiro Yamada 27609f455dcSMasahiro Yamada /* 27709f455dcSMasahiro Yamada * Read the register containing the individual CPU clock enables and 27809f455dcSMasahiro Yamada * always stop the clocks to CPUs > 0. 27909f455dcSMasahiro Yamada */ 28009f455dcSMasahiro Yamada clk = readl(&clkrst->crc_clk_cpu_cmplx); 28109f455dcSMasahiro Yamada clk |= 1 << CPU1_CLK_STP_SHIFT; 28209f455dcSMasahiro Yamada if (get_num_cpus() == 4) 28309f455dcSMasahiro Yamada clk |= (1 << CPU2_CLK_STP_SHIFT) + (1 << CPU3_CLK_STP_SHIFT); 28409f455dcSMasahiro Yamada 28509f455dcSMasahiro Yamada /* Stop/Unstop the CPU clock */ 28609f455dcSMasahiro Yamada clk &= ~CPU0_CLK_STP_MASK; 28709f455dcSMasahiro Yamada clk |= !enable << CPU0_CLK_STP_SHIFT; 28809f455dcSMasahiro Yamada writel(clk, &clkrst->crc_clk_cpu_cmplx); 28909f455dcSMasahiro Yamada 29009f455dcSMasahiro Yamada clock_enable(PERIPH_ID_CPU); 29109f455dcSMasahiro Yamada } 29209f455dcSMasahiro Yamada 29309f455dcSMasahiro Yamada static int is_cpu_powered(void) 29409f455dcSMasahiro Yamada { 29509f455dcSMasahiro Yamada struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE; 29609f455dcSMasahiro Yamada 29709f455dcSMasahiro Yamada return (readl(&pmc->pmc_pwrgate_status) & CPU_PWRED) ? 1 : 0; 29809f455dcSMasahiro Yamada } 29909f455dcSMasahiro Yamada 30009f455dcSMasahiro Yamada static void remove_cpu_io_clamps(void) 30109f455dcSMasahiro Yamada { 30209f455dcSMasahiro Yamada struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE; 30309f455dcSMasahiro Yamada u32 reg; 304*7aaa5a60STom Warren debug("%s entry\n", __func__); 30509f455dcSMasahiro Yamada 30609f455dcSMasahiro Yamada /* Remove the clamps on the CPU I/O signals */ 30709f455dcSMasahiro Yamada reg = readl(&pmc->pmc_remove_clamping); 30809f455dcSMasahiro Yamada reg |= CPU_CLMP; 30909f455dcSMasahiro Yamada writel(reg, &pmc->pmc_remove_clamping); 31009f455dcSMasahiro Yamada 31109f455dcSMasahiro Yamada /* Give I/O signals time to stabilize */ 31209f455dcSMasahiro Yamada udelay(IO_STABILIZATION_DELAY); 31309f455dcSMasahiro Yamada } 31409f455dcSMasahiro Yamada 31509f455dcSMasahiro Yamada void powerup_cpu(void) 31609f455dcSMasahiro Yamada { 31709f455dcSMasahiro Yamada struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE; 31809f455dcSMasahiro Yamada u32 reg; 31909f455dcSMasahiro Yamada int timeout = IO_STABILIZATION_DELAY; 320*7aaa5a60STom Warren debug("%s entry\n", __func__); 32109f455dcSMasahiro Yamada 32209f455dcSMasahiro Yamada if (!is_cpu_powered()) { 32309f455dcSMasahiro Yamada /* Toggle the CPU power state (OFF -> ON) */ 32409f455dcSMasahiro Yamada reg = readl(&pmc->pmc_pwrgate_toggle); 32509f455dcSMasahiro Yamada reg &= PARTID_CP; 32609f455dcSMasahiro Yamada reg |= START_CP; 32709f455dcSMasahiro Yamada writel(reg, &pmc->pmc_pwrgate_toggle); 32809f455dcSMasahiro Yamada 32909f455dcSMasahiro Yamada /* Wait for the power to come up */ 33009f455dcSMasahiro Yamada while (!is_cpu_powered()) { 33109f455dcSMasahiro Yamada if (timeout-- == 0) 33209f455dcSMasahiro Yamada printf("CPU failed to power up!\n"); 33309f455dcSMasahiro Yamada else 33409f455dcSMasahiro Yamada udelay(10); 33509f455dcSMasahiro Yamada } 33609f455dcSMasahiro Yamada 33709f455dcSMasahiro Yamada /* 33809f455dcSMasahiro Yamada * Remove the I/O clamps from CPU power partition. 33909f455dcSMasahiro Yamada * Recommended only on a Warm boot, if the CPU partition gets 34009f455dcSMasahiro Yamada * power gated. Shouldn't cause any harm when called after a 34109f455dcSMasahiro Yamada * cold boot according to HW, probably just redundant. 34209f455dcSMasahiro Yamada */ 34309f455dcSMasahiro Yamada remove_cpu_io_clamps(); 34409f455dcSMasahiro Yamada } 34509f455dcSMasahiro Yamada } 34609f455dcSMasahiro Yamada 34709f455dcSMasahiro Yamada void reset_A9_cpu(int reset) 34809f455dcSMasahiro Yamada { 34909f455dcSMasahiro Yamada /* 35009f455dcSMasahiro Yamada * NOTE: Regardless of whether the request is to hold the CPU in reset 35109f455dcSMasahiro Yamada * or take it out of reset, every processor in the CPU complex 35209f455dcSMasahiro Yamada * except the master (CPU 0) will be held in reset because the 35309f455dcSMasahiro Yamada * AVP only talks to the master. The AVP does not know that there 35409f455dcSMasahiro Yamada * are multiple processors in the CPU complex. 35509f455dcSMasahiro Yamada */ 35609f455dcSMasahiro Yamada int mask = crc_rst_cpu | crc_rst_de | crc_rst_debug; 35709f455dcSMasahiro Yamada int num_cpus = get_num_cpus(); 35809f455dcSMasahiro Yamada int cpu; 35909f455dcSMasahiro Yamada 360*7aaa5a60STom Warren debug("%s entry\n", __func__); 36109f455dcSMasahiro Yamada /* Hold CPUs 1 onwards in reset, and CPU 0 if asked */ 36209f455dcSMasahiro Yamada for (cpu = 1; cpu < num_cpus; cpu++) 36309f455dcSMasahiro Yamada reset_cmplx_set_enable(cpu, mask, 1); 36409f455dcSMasahiro Yamada reset_cmplx_set_enable(0, mask, reset); 36509f455dcSMasahiro Yamada 36609f455dcSMasahiro Yamada /* Enable/Disable master CPU reset */ 36709f455dcSMasahiro Yamada reset_set_enable(PERIPH_ID_CPU, reset); 36809f455dcSMasahiro Yamada } 36909f455dcSMasahiro Yamada 37009f455dcSMasahiro Yamada void clock_enable_coresight(int enable) 37109f455dcSMasahiro Yamada { 37209f455dcSMasahiro Yamada u32 rst, src = 2; 37309f455dcSMasahiro Yamada 374*7aaa5a60STom Warren debug("%s entry\n", __func__); 37509f455dcSMasahiro Yamada clock_set_enable(PERIPH_ID_CORESIGHT, enable); 37609f455dcSMasahiro Yamada reset_set_enable(PERIPH_ID_CORESIGHT, !enable); 37709f455dcSMasahiro Yamada 37809f455dcSMasahiro Yamada if (enable) { 37909f455dcSMasahiro Yamada /* 38009f455dcSMasahiro Yamada * Put CoreSight on PLLP_OUT0 and divide it down as per 38109f455dcSMasahiro Yamada * PLLP base frequency based on SoC type (T20/T30+). 38209f455dcSMasahiro Yamada * Clock divider request would setup CSITE clock as 144MHz 38309f455dcSMasahiro Yamada * for PLLP base 216MHz and 204MHz for PLLP base 408MHz 38409f455dcSMasahiro Yamada */ 38509f455dcSMasahiro Yamada src = CLK_DIVIDER(NVBL_PLLP_KHZ, CSITE_KHZ); 38609f455dcSMasahiro Yamada clock_ll_set_source_divisor(PERIPH_ID_CSI, 0, src); 38709f455dcSMasahiro Yamada 38809f455dcSMasahiro Yamada /* Unlock the CPU CoreSight interfaces */ 38909f455dcSMasahiro Yamada rst = CORESIGHT_UNLOCK; 39009f455dcSMasahiro Yamada writel(rst, CSITE_CPU_DBG0_LAR); 39109f455dcSMasahiro Yamada writel(rst, CSITE_CPU_DBG1_LAR); 39209f455dcSMasahiro Yamada if (get_num_cpus() == 4) { 39309f455dcSMasahiro Yamada writel(rst, CSITE_CPU_DBG2_LAR); 39409f455dcSMasahiro Yamada writel(rst, CSITE_CPU_DBG3_LAR); 39509f455dcSMasahiro Yamada } 39609f455dcSMasahiro Yamada } 39709f455dcSMasahiro Yamada } 39809f455dcSMasahiro Yamada 39909f455dcSMasahiro Yamada void halt_avp(void) 40009f455dcSMasahiro Yamada { 401*7aaa5a60STom Warren debug("%s entry\n", __func__); 402*7aaa5a60STom Warren 40309f455dcSMasahiro Yamada for (;;) { 40409f455dcSMasahiro Yamada writel(HALT_COP_EVENT_JTAG | (FLOW_MODE_STOP << 29), 40509f455dcSMasahiro Yamada FLOW_CTLR_HALT_COP_EVENTS); 40609f455dcSMasahiro Yamada } 40709f455dcSMasahiro Yamada } 408