/*
 * (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(PMUX_PINGRP_PWR_I2C_SCL_PZ6);
	pinmux_tristate_disable(PMUX_PINGRP_PWR_I2C_SDA_PZ7);

	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 */
	writel((MULT_8 << TIMER_MULT_SHIFT) | (MULT_8 << TIMER_MULT_CPU_SHIFT),
	       &pmc->pmc_pwrgate_timer_mult);

	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");
}
