183d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+ 209f455dcSMasahiro Yamada /* 309f455dcSMasahiro Yamada * (C) Copyright 2013 409f455dcSMasahiro Yamada * NVIDIA Corporation <www.nvidia.com> 509f455dcSMasahiro Yamada */ 609f455dcSMasahiro Yamada 709f455dcSMasahiro Yamada #include <common.h> 809f455dcSMasahiro Yamada #include <asm/io.h> 909f455dcSMasahiro Yamada #include <asm/arch/ahb.h> 1009f455dcSMasahiro Yamada #include <asm/arch/clock.h> 1109f455dcSMasahiro Yamada #include <asm/arch/flow.h> 1209f455dcSMasahiro Yamada #include <asm/arch/pinmux.h> 1309f455dcSMasahiro Yamada #include <asm/arch/tegra.h> 1409f455dcSMasahiro Yamada #include <asm/arch-tegra/clk_rst.h> 1509f455dcSMasahiro Yamada #include <asm/arch-tegra/pmc.h> 1609f455dcSMasahiro Yamada #include <asm/arch-tegra/ap.h> 1709f455dcSMasahiro Yamada #include "../cpu.h" 1809f455dcSMasahiro Yamada 1909f455dcSMasahiro Yamada /* Tegra124-specific CPU init code */ 2009f455dcSMasahiro Yamada 2109f455dcSMasahiro Yamada static void enable_cpu_power_rail(void) 2209f455dcSMasahiro Yamada { 2309f455dcSMasahiro Yamada struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE; 2409f455dcSMasahiro Yamada 25722e000cSTom Warren debug("%s entry\n", __func__); 2609f455dcSMasahiro Yamada 2709f455dcSMasahiro Yamada /* un-tristate PWR_I2C SCL/SDA, rest of the defaults are correct */ 2809f455dcSMasahiro Yamada pinmux_tristate_disable(PMUX_PINGRP_PWR_I2C_SCL_PZ6); 2909f455dcSMasahiro Yamada pinmux_tristate_disable(PMUX_PINGRP_PWR_I2C_SDA_PZ7); 3009f455dcSMasahiro Yamada 3109f455dcSMasahiro Yamada pmic_enable_cpu_vdd(); 3209f455dcSMasahiro Yamada 3309f455dcSMasahiro Yamada /* 3409f455dcSMasahiro Yamada * Set CPUPWRGOOD_TIMER - APB clock is 1/2 of SCLK (102MHz), 3509f455dcSMasahiro Yamada * set it for 5ms as per SysEng (102MHz*5ms = 510000 (7C830h). 3609f455dcSMasahiro Yamada */ 3709f455dcSMasahiro Yamada writel(0x7C830, &pmc->pmc_cpupwrgood_timer); 3809f455dcSMasahiro Yamada 3909f455dcSMasahiro Yamada /* Set polarity to 0 (normal) and enable CPUPWRREQ_OE */ 4009f455dcSMasahiro Yamada clrbits_le32(&pmc->pmc_cntrl, CPUPWRREQ_POL); 4109f455dcSMasahiro Yamada setbits_le32(&pmc->pmc_cntrl, CPUPWRREQ_OE); 4209f455dcSMasahiro Yamada } 4309f455dcSMasahiro Yamada 4409f455dcSMasahiro Yamada static void enable_cpu_clocks(void) 4509f455dcSMasahiro Yamada { 4609f455dcSMasahiro Yamada struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; 47722e000cSTom Warren struct clk_pll_info *pllinfo = &tegra_pll_info_table[CLOCK_ID_XCPU]; 4809f455dcSMasahiro Yamada u32 reg; 4909f455dcSMasahiro Yamada 50722e000cSTom Warren debug("%s entry\n", __func__); 5109f455dcSMasahiro Yamada 5209f455dcSMasahiro Yamada /* Wait for PLL-X to lock */ 5309f455dcSMasahiro Yamada do { 5409f455dcSMasahiro Yamada reg = readl(&clkrst->crc_pll_simple[SIMPLE_PLLX].pll_base); 5509f455dcSMasahiro Yamada debug("%s: PLLX base = 0x%08X\n", __func__, reg); 56722e000cSTom Warren } while ((reg & (1 << pllinfo->lock_det)) == 0); 5709f455dcSMasahiro Yamada 5809f455dcSMasahiro Yamada debug("%s: PLLX locked, delay for stable clocks\n", __func__); 5909f455dcSMasahiro Yamada /* Wait until all clocks are stable */ 6009f455dcSMasahiro Yamada udelay(PLL_STABILIZATION_DELAY); 6109f455dcSMasahiro Yamada 6209f455dcSMasahiro Yamada debug("%s: Setting CCLK_BURST and DIVIDER\n", __func__); 6309f455dcSMasahiro Yamada writel(CCLK_BURST_POLICY, &clkrst->crc_cclk_brst_pol); 6409f455dcSMasahiro Yamada writel(SUPER_CCLK_DIVIDER, &clkrst->crc_super_cclk_div); 6509f455dcSMasahiro Yamada 6609f455dcSMasahiro Yamada debug("%s: Enabling clock to all CPUs\n", __func__); 6709f455dcSMasahiro Yamada /* Enable the clock to all CPUs */ 6809f455dcSMasahiro Yamada reg = CLR_CPU3_CLK_STP | CLR_CPU2_CLK_STP | CLR_CPU1_CLK_STP | 6909f455dcSMasahiro Yamada CLR_CPU0_CLK_STP; 7009f455dcSMasahiro Yamada writel(reg, &clkrst->crc_clk_cpu_cmplx_clr); 7109f455dcSMasahiro Yamada 7209f455dcSMasahiro Yamada debug("%s: Enabling main CPU complex clocks\n", __func__); 7309f455dcSMasahiro Yamada /* Always enable the main CPU complex clocks */ 7409f455dcSMasahiro Yamada clock_enable(PERIPH_ID_CPU); 7509f455dcSMasahiro Yamada clock_enable(PERIPH_ID_CPULP); 7609f455dcSMasahiro Yamada clock_enable(PERIPH_ID_CPUG); 7709f455dcSMasahiro Yamada 7809f455dcSMasahiro Yamada debug("%s: Done\n", __func__); 7909f455dcSMasahiro Yamada } 8009f455dcSMasahiro Yamada 8109f455dcSMasahiro Yamada static void remove_cpu_resets(void) 8209f455dcSMasahiro Yamada { 8309f455dcSMasahiro Yamada struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; 8409f455dcSMasahiro Yamada u32 reg; 8509f455dcSMasahiro Yamada 86722e000cSTom Warren debug("%s entry\n", __func__); 8709f455dcSMasahiro Yamada 8809f455dcSMasahiro Yamada /* Take the slow and fast partitions out of reset */ 8909f455dcSMasahiro Yamada reg = CLR_NONCPURESET; 9009f455dcSMasahiro Yamada writel(reg, &clkrst->crc_rst_cpulp_cmplx_clr); 9109f455dcSMasahiro Yamada writel(reg, &clkrst->crc_rst_cpug_cmplx_clr); 9209f455dcSMasahiro Yamada 9309f455dcSMasahiro Yamada /* Clear the SW-controlled reset of the slow cluster */ 9409f455dcSMasahiro Yamada reg = CLR_CPURESET0 | CLR_DBGRESET0 | CLR_CORERESET0 | CLR_CXRESET0 | 9509f455dcSMasahiro Yamada CLR_L2RESET | CLR_PRESETDBG; 9609f455dcSMasahiro Yamada writel(reg, &clkrst->crc_rst_cpulp_cmplx_clr); 9709f455dcSMasahiro Yamada 9809f455dcSMasahiro Yamada /* Clear the SW-controlled reset of the fast cluster */ 9909f455dcSMasahiro Yamada reg = CLR_CPURESET0 | CLR_DBGRESET0 | CLR_CORERESET0 | CLR_CXRESET0 | 10009f455dcSMasahiro Yamada CLR_CPURESET1 | CLR_DBGRESET1 | CLR_CORERESET1 | CLR_CXRESET1 | 10109f455dcSMasahiro Yamada CLR_CPURESET2 | CLR_DBGRESET2 | CLR_CORERESET2 | CLR_CXRESET2 | 10209f455dcSMasahiro Yamada CLR_CPURESET3 | CLR_DBGRESET3 | CLR_CORERESET3 | CLR_CXRESET3 | 10309f455dcSMasahiro Yamada CLR_L2RESET | CLR_PRESETDBG; 10409f455dcSMasahiro Yamada writel(reg, &clkrst->crc_rst_cpug_cmplx_clr); 10509f455dcSMasahiro Yamada } 10609f455dcSMasahiro Yamada 107*3cc7942aSBibek Basu static void tegra124_ram_repair(void) 108*3cc7942aSBibek Basu { 109*3cc7942aSBibek Basu struct flow_ctlr *flow = (struct flow_ctlr *)NV_PA_FLOW_BASE; 110*3cc7942aSBibek Basu u32 ram_repair_timeout; /*usec*/ 111*3cc7942aSBibek Basu u32 val; 112*3cc7942aSBibek Basu 113*3cc7942aSBibek Basu /* 114*3cc7942aSBibek Basu * Request the Flow Controller perform RAM repair whenever it turns on 115*3cc7942aSBibek Basu * a power rail that requires RAM repair. 116*3cc7942aSBibek Basu */ 117*3cc7942aSBibek Basu clrbits_le32(&flow->ram_repair, RAM_REPAIR_BYPASS_EN); 118*3cc7942aSBibek Basu 119*3cc7942aSBibek Basu /* Request SW trigerred RAM repair by setting req bit */ 120*3cc7942aSBibek Basu /* cluster 0 */ 121*3cc7942aSBibek Basu setbits_le32(&flow->ram_repair, RAM_REPAIR_REQ); 122*3cc7942aSBibek Basu /* Wait for completion (status == 0) */ 123*3cc7942aSBibek Basu ram_repair_timeout = 500; 124*3cc7942aSBibek Basu do { 125*3cc7942aSBibek Basu udelay(1); 126*3cc7942aSBibek Basu val = readl(&flow->ram_repair); 127*3cc7942aSBibek Basu } while (!(val & RAM_REPAIR_STS) && ram_repair_timeout--); 128*3cc7942aSBibek Basu if (!ram_repair_timeout) 129*3cc7942aSBibek Basu debug("Ram Repair cluster0 failed\n"); 130*3cc7942aSBibek Basu 131*3cc7942aSBibek Basu /* cluster 1 */ 132*3cc7942aSBibek Basu setbits_le32(&flow->ram_repair_cluster1, RAM_REPAIR_REQ); 133*3cc7942aSBibek Basu /* Wait for completion (status == 0) */ 134*3cc7942aSBibek Basu ram_repair_timeout = 500; 135*3cc7942aSBibek Basu do { 136*3cc7942aSBibek Basu udelay(1); 137*3cc7942aSBibek Basu val = readl(&flow->ram_repair_cluster1); 138*3cc7942aSBibek Basu } while (!(val & RAM_REPAIR_STS) && ram_repair_timeout--); 139*3cc7942aSBibek Basu 140*3cc7942aSBibek Basu if (!ram_repair_timeout) 141*3cc7942aSBibek Basu debug("Ram Repair cluster1 failed\n"); 142*3cc7942aSBibek Basu } 143*3cc7942aSBibek Basu 14409f455dcSMasahiro Yamada /** 145722e000cSTom Warren * Tegra124 requires some special clock initialization, including setting up 14609f455dcSMasahiro Yamada * the DVC I2C, turning on MSELECT and selecting the G CPU cluster 14709f455dcSMasahiro Yamada */ 14809f455dcSMasahiro Yamada void tegra124_init_clocks(void) 14909f455dcSMasahiro Yamada { 15009f455dcSMasahiro Yamada struct flow_ctlr *flow = (struct flow_ctlr *)NV_PA_FLOW_BASE; 15109f455dcSMasahiro Yamada struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE; 15209f455dcSMasahiro Yamada struct clk_rst_ctlr *clkrst = 15309f455dcSMasahiro Yamada (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; 15409f455dcSMasahiro Yamada u32 val; 15509f455dcSMasahiro Yamada 156722e000cSTom Warren debug("%s entry\n", __func__); 15709f455dcSMasahiro Yamada 15809f455dcSMasahiro Yamada /* Set active CPU cluster to G */ 15909f455dcSMasahiro Yamada clrbits_le32(&flow->cluster_control, 1); 16009f455dcSMasahiro Yamada 16109f455dcSMasahiro Yamada /* Change the oscillator drive strength */ 16209f455dcSMasahiro Yamada val = readl(&clkrst->crc_osc_ctrl); 16309f455dcSMasahiro Yamada val &= ~OSC_XOFS_MASK; 16409f455dcSMasahiro Yamada val |= (OSC_DRIVE_STRENGTH << OSC_XOFS_SHIFT); 16509f455dcSMasahiro Yamada writel(val, &clkrst->crc_osc_ctrl); 16609f455dcSMasahiro Yamada 16709f455dcSMasahiro Yamada /* Update same value in PMC_OSC_EDPD_OVER XOFS field for warmboot */ 16809f455dcSMasahiro Yamada val = readl(&pmc->pmc_osc_edpd_over); 16909f455dcSMasahiro Yamada val &= ~PMC_XOFS_MASK; 17009f455dcSMasahiro Yamada val |= (OSC_DRIVE_STRENGTH << PMC_XOFS_SHIFT); 17109f455dcSMasahiro Yamada writel(val, &pmc->pmc_osc_edpd_over); 17209f455dcSMasahiro Yamada 17309f455dcSMasahiro Yamada /* Set HOLD_CKE_LOW_EN to 1 */ 17409f455dcSMasahiro Yamada setbits_le32(&pmc->pmc_cntrl2, HOLD_CKE_LOW_EN); 17509f455dcSMasahiro Yamada 17609f455dcSMasahiro Yamada debug("Setting up PLLX\n"); 17709f455dcSMasahiro Yamada init_pllx(); 17809f455dcSMasahiro Yamada 17909f455dcSMasahiro Yamada val = (1 << CLK_SYS_RATE_AHB_RATE_SHIFT); 18009f455dcSMasahiro Yamada writel(val, &clkrst->crc_clk_sys_rate); 18109f455dcSMasahiro Yamada 18209f455dcSMasahiro Yamada /* Enable clocks to required peripherals. TBD - minimize this list */ 18309f455dcSMasahiro Yamada debug("Enabling clocks\n"); 18409f455dcSMasahiro Yamada 18509f455dcSMasahiro Yamada clock_set_enable(PERIPH_ID_CACHE2, 1); 18609f455dcSMasahiro Yamada clock_set_enable(PERIPH_ID_GPIO, 1); 18709f455dcSMasahiro Yamada clock_set_enable(PERIPH_ID_TMR, 1); 18809f455dcSMasahiro Yamada clock_set_enable(PERIPH_ID_CPU, 1); 18909f455dcSMasahiro Yamada clock_set_enable(PERIPH_ID_EMC, 1); 19009f455dcSMasahiro Yamada clock_set_enable(PERIPH_ID_I2C5, 1); 19109f455dcSMasahiro Yamada clock_set_enable(PERIPH_ID_APBDMA, 1); 19209f455dcSMasahiro Yamada clock_set_enable(PERIPH_ID_MEM, 1); 19309f455dcSMasahiro Yamada clock_set_enable(PERIPH_ID_CORESIGHT, 1); 19409f455dcSMasahiro Yamada clock_set_enable(PERIPH_ID_MSELECT, 1); 19509f455dcSMasahiro Yamada clock_set_enable(PERIPH_ID_DVFS, 1); 19609f455dcSMasahiro Yamada 19709f455dcSMasahiro Yamada /* 19809f455dcSMasahiro Yamada * Set MSELECT clock source as PLLP (00), and ask for a clock 19909f455dcSMasahiro Yamada * divider that would set the MSELECT clock at 102MHz for a 20009f455dcSMasahiro Yamada * PLLP base of 408MHz. 20109f455dcSMasahiro Yamada */ 20209f455dcSMasahiro Yamada clock_ll_set_source_divisor(PERIPH_ID_MSELECT, 0, 20309f455dcSMasahiro Yamada CLK_DIVIDER(NVBL_PLLP_KHZ, 102000)); 20409f455dcSMasahiro Yamada 20509f455dcSMasahiro Yamada /* Give clock time to stabilize */ 20609f455dcSMasahiro Yamada udelay(IO_STABILIZATION_DELAY); 20709f455dcSMasahiro Yamada 20809f455dcSMasahiro Yamada /* I2C5 (DVC) gets CLK_M and a divisor of 17 */ 20909f455dcSMasahiro Yamada clock_ll_set_source_divisor(PERIPH_ID_I2C5, 3, 16); 21009f455dcSMasahiro Yamada 21109f455dcSMasahiro Yamada /* Give clock time to stabilize */ 21209f455dcSMasahiro Yamada udelay(IO_STABILIZATION_DELAY); 21309f455dcSMasahiro Yamada 21409f455dcSMasahiro Yamada /* Take required peripherals out of reset */ 21509f455dcSMasahiro Yamada debug("Taking periphs out of reset\n"); 21609f455dcSMasahiro Yamada reset_set_enable(PERIPH_ID_CACHE2, 0); 21709f455dcSMasahiro Yamada reset_set_enable(PERIPH_ID_GPIO, 0); 21809f455dcSMasahiro Yamada reset_set_enable(PERIPH_ID_TMR, 0); 21909f455dcSMasahiro Yamada reset_set_enable(PERIPH_ID_COP, 0); 22009f455dcSMasahiro Yamada reset_set_enable(PERIPH_ID_EMC, 0); 22109f455dcSMasahiro Yamada reset_set_enable(PERIPH_ID_I2C5, 0); 22209f455dcSMasahiro Yamada reset_set_enable(PERIPH_ID_APBDMA, 0); 22309f455dcSMasahiro Yamada reset_set_enable(PERIPH_ID_MEM, 0); 22409f455dcSMasahiro Yamada reset_set_enable(PERIPH_ID_CORESIGHT, 0); 22509f455dcSMasahiro Yamada reset_set_enable(PERIPH_ID_MSELECT, 0); 22609f455dcSMasahiro Yamada reset_set_enable(PERIPH_ID_DVFS, 0); 22709f455dcSMasahiro Yamada 228722e000cSTom Warren debug("%s exit\n", __func__); 22909f455dcSMasahiro Yamada } 23009f455dcSMasahiro Yamada 23109f455dcSMasahiro Yamada static bool is_partition_powered(u32 partid) 23209f455dcSMasahiro Yamada { 23309f455dcSMasahiro Yamada struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE; 23409f455dcSMasahiro Yamada u32 reg; 23509f455dcSMasahiro Yamada 23609f455dcSMasahiro Yamada /* Get power gate status */ 23709f455dcSMasahiro Yamada reg = readl(&pmc->pmc_pwrgate_status); 23809f455dcSMasahiro Yamada return !!(reg & (1 << partid)); 23909f455dcSMasahiro Yamada } 24009f455dcSMasahiro Yamada 24109f455dcSMasahiro Yamada static void power_partition(u32 partid) 24209f455dcSMasahiro Yamada { 24309f455dcSMasahiro Yamada struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE; 24409f455dcSMasahiro Yamada 24509f455dcSMasahiro Yamada debug("%s: part ID = %08X\n", __func__, partid); 24609f455dcSMasahiro Yamada /* Is the partition already on? */ 24709f455dcSMasahiro Yamada if (!is_partition_powered(partid)) { 24809f455dcSMasahiro Yamada /* No, toggle the partition power state (OFF -> ON) */ 24909f455dcSMasahiro Yamada debug("power_partition, toggling state\n"); 25009f455dcSMasahiro Yamada writel(START_CP | partid, &pmc->pmc_pwrgate_toggle); 25109f455dcSMasahiro Yamada 25209f455dcSMasahiro Yamada /* Wait for the power to come up */ 25309f455dcSMasahiro Yamada while (!is_partition_powered(partid)) 25409f455dcSMasahiro Yamada ; 25509f455dcSMasahiro Yamada 25609f455dcSMasahiro Yamada /* Give I/O signals time to stabilize */ 25709f455dcSMasahiro Yamada udelay(IO_STABILIZATION_DELAY); 25809f455dcSMasahiro Yamada } 25909f455dcSMasahiro Yamada } 26009f455dcSMasahiro Yamada 26109f455dcSMasahiro Yamada void powerup_cpus(void) 26209f455dcSMasahiro Yamada { 26309f455dcSMasahiro Yamada /* We boot to the fast cluster */ 264722e000cSTom Warren debug("%s entry: G cluster\n", __func__); 26509f455dcSMasahiro Yamada 26609f455dcSMasahiro Yamada /* Power up the fast cluster rail partition */ 267722e000cSTom Warren debug("%s: CRAIL\n", __func__); 26809f455dcSMasahiro Yamada power_partition(CRAIL); 26909f455dcSMasahiro Yamada 27009f455dcSMasahiro Yamada /* Power up the fast cluster non-CPU partition */ 271722e000cSTom Warren debug("%s: C0NC\n", __func__); 27209f455dcSMasahiro Yamada power_partition(C0NC); 27309f455dcSMasahiro Yamada 27409f455dcSMasahiro Yamada /* Power up the fast cluster CPU0 partition */ 275722e000cSTom Warren debug("%s: CE0\n", __func__); 27609f455dcSMasahiro Yamada power_partition(CE0); 27709f455dcSMasahiro Yamada 278722e000cSTom Warren debug("%s: done\n", __func__); 27909f455dcSMasahiro Yamada } 28009f455dcSMasahiro Yamada 28109f455dcSMasahiro Yamada void start_cpu(u32 reset_vector) 28209f455dcSMasahiro Yamada { 28309f455dcSMasahiro Yamada struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE; 28409f455dcSMasahiro Yamada 285722e000cSTom Warren debug("%s entry, reset_vector = %x\n", __func__, reset_vector); 28609f455dcSMasahiro Yamada 28709f455dcSMasahiro Yamada tegra124_init_clocks(); 28809f455dcSMasahiro Yamada 28909f455dcSMasahiro Yamada /* Set power-gating timer multiplier */ 29009f455dcSMasahiro Yamada writel((MULT_8 << TIMER_MULT_SHIFT) | (MULT_8 << TIMER_MULT_CPU_SHIFT), 29109f455dcSMasahiro Yamada &pmc->pmc_pwrgate_timer_mult); 29209f455dcSMasahiro Yamada 29309f455dcSMasahiro Yamada enable_cpu_power_rail(); 294*3cc7942aSBibek Basu powerup_cpus(); 295*3cc7942aSBibek Basu tegra124_ram_repair(); 29609f455dcSMasahiro Yamada enable_cpu_clocks(); 29709f455dcSMasahiro Yamada clock_enable_coresight(1); 29809f455dcSMasahiro Yamada writel(reset_vector, EXCEP_VECTOR_CPU_RESET_VECTOR); 299*3cc7942aSBibek Basu remove_cpu_resets(); 300722e000cSTom Warren debug("%s exit, should continue @ reset_vector\n", __func__); 30109f455dcSMasahiro Yamada } 302