Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 820f6f9d authored by Prasad Sodagudi's avatar Prasad Sodagudi
Browse files

msm: cpu: Add l2 and core initialization sequences for titanium



1) msmtitanium has different power on sequence for its ARM cores,
   so add new L2 and core initialization sequences.
2) Add new cpu_ops and enable-method.
3) Also use simple wfi based hotplug call-back.

Change-Id: Ibcaa6f93d3e28924f55e6950498dc6f0d953b548
Signed-off-by: default avatarPrasad Sodagudi <psodagud@codeaurora.org>
parent ff03d8c3
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -185,6 +185,7 @@ nodes to be present and contain the properties described below.
			  be one of:
			     "psci"
			     "spin-table"
			     "qcom,titanium-arm-cortex-acc"

			# On ARM 32-bit systems this property is optional and
			  can be one of:
+1 −0
Original line number Diff line number Diff line
@@ -7,6 +7,7 @@ region per CPU Cluster.
Required properties:
- compatible:	Can be one of:
		"qcom,8916-l2ccc"
		"qcom,titanium-l2ccc"
- reg:		This specifies the base address and size of
		the register region.

+48 −0
Original line number Diff line number Diff line
@@ -126,6 +126,38 @@ static int __init msm_cpu_prepare(unsigned int cpu)
	return 0;
}

static int msmtitanium_cpu_boot(unsigned int cpu)
{
	int ret = 0;

	if (per_cpu(cold_boot_done, cpu) == false) {
		ret = msmtitanium_unclamp_secondary_arm_cpu(cpu);
		if (ret)
			return ret;

		per_cpu(cold_boot_done, cpu) = true;
	}
	return secondary_pen_release(cpu);
}

#ifdef CONFIG_HOTPLUG_CPU
static void msmtitanium_wfi_cpu_die(unsigned int cpu)
{
	if (unlikely(cpu != smp_processor_id())) {
		pr_crit("%s: running on %u, should be %u\n",
			__func__, smp_processor_id(), cpu);
		BUG();
	}
	for (;;) {
		wfi();
		if (secondary_holding_pen_release == cpu_logical_map(cpu))
			break;	/*Proper wake up */

		pr_debug("CPU%u: spurious wakeup call\n", cpu);
		BUG();
	}
}
#endif

static int msm_cpu_boot(unsigned int cpu)
{
@@ -196,3 +228,19 @@ static struct cpu_operations msm_cortex_a_ops = {
};
CPU_METHOD_OF_DECLARE(msm_cortex_a_ops,
		"qcom,arm-cortex-acc", &msm_cortex_a_ops);

static struct cpu_operations msmtitanium_cortex_a_ops = {
	.name		= "qcom,titanium-arm-cortex-acc",
	.cpu_init	= msm_cpu_init,
	.cpu_prepare	= msm_cpu_prepare,
	.cpu_boot	= msmtitanium_cpu_boot,
	.cpu_postboot	= msm_cpu_postboot,
#ifdef CONFIG_HOTPLUG_CPU
	.cpu_die        = msmtitanium_wfi_cpu_die,
#endif
#ifdef CONFIG_ARM64_CPU_SUSPEND
	.cpu_suspend       = msm_pm_collapse,
#endif
};
CPU_METHOD_OF_DECLARE(msmtitanium_cortex_a_ops,
	"qcom,titanium-arm-cortex-acc", &msmtitanium_cortex_a_ops);
+200 −0
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@

#include <asm/barrier.h>
#include <asm/cacheflush.h>
#include <asm/smp_plat.h>

/* CPU power domain register offsets */
#define CPU_PWR_CTL			0x4
@@ -52,6 +53,90 @@ struct msm_l2ccc_of_info {
};


static int power_on_l2_msmtitanium(struct device_node *l2ccc_node, u32 pon_mask,
				int cpu)
{
	u32 pon_status;
	void __iomem *l2_base;

	l2_base = of_iomap(l2ccc_node, 0);
	if (!l2_base)
		return -ENOMEM;

	/* Skip power-on sequence if l2 cache is already powered up */
	pon_status = (__raw_readl(l2_base + L2_PWR_STATUS) & pon_mask)
				== pon_mask;
	if (pon_status) {
		iounmap(l2_base);
		return 0;
	}

	/* Close Few of the head-switches for L2SCU logic */
	writel_relaxed(0x10F700, l2_base + L2_PWR_CTL);
	mb();
	udelay(2);

	/* Close Rest of the head-switches for L2SCU logic */
	writel_relaxed(0x410F700, l2_base + L2_PWR_CTL);
	mb();
	udelay(2);

	/* Assert PRESETDBG */
	writel_relaxed(0x400000, l2_base + L2_PWR_CTL_OVERRIDE);
	mb();
	udelay(2);

	/* De-assert L2/SCU memory Clamp */
	writel_relaxed(0x4103700, l2_base + L2_PWR_CTL);
	mb();
	/* Assert L2 memory slp_nret_n */
	writel_relaxed(0x4103703, l2_base + L2_PWR_CTL);
	mb();
	udelay(4);
	/* Assert L2 memory slp_ret_n */
	writel_relaxed(0x4101703, l2_base + L2_PWR_CTL);
	mb();
	udelay(4);

	/* Assert L2 memory wl_en_clk */
	writel_relaxed(0x4101783, l2_base + L2_PWR_CTL);
	mb();
	udelay(1);
	/* De-assert L2 memory wl_en_clk */
	writel_relaxed(0x4101703, l2_base + L2_PWR_CTL);
	mb();


	/* Enable clocks via SW_CLK_EN */
	writel_relaxed(0x01, l2_base + L2_CORE_CBCR);
	mb();

	/* De-assert L2/SCU logic clamp */
	writel_relaxed(0x4101603, l2_base + L2_PWR_CTL);
	mb();
	udelay(2);

	/* De-assert PRESETDBG */
	writel_relaxed(0x0, l2_base + L2_PWR_CTL_OVERRIDE);
	mb();

	/* De-assert L2/SCU Logic reset */
	writel_relaxed(0x4100203, l2_base + L2_PWR_CTL);
	mb();
	udelay(54);

	/* Turn on the PMIC_APC */
	writel_relaxed(0x14100203, l2_base + L2_PWR_CTL);
	mb();

	/* Set H/W clock control for the cluster CBC block */
	writel_relaxed(0x03, l2_base + L2_CORE_CBCR);
	mb();
	iounmap(l2_base);

	return 0;
}

static int power_on_l2_msm8916(struct device_node *l2ccc_node, u32 pon_mask,
				int cpu)
{
@@ -119,6 +204,11 @@ static const struct msm_l2ccc_of_info l2ccc_info[] = {
		.l2_power_on = power_on_l2_msm8916,
		.l2_power_on_mask = BIT(9),
	},
	{
		.compat = "qcom,titanium-l2ccc",
		.l2_power_on = power_on_l2_msmtitanium,
		.l2_power_on_mask = BIT(9) | BIT(28),
	},
};

static int power_on_l2_cache(struct device_node *l2ccc_node, int cpu)
@@ -141,6 +231,116 @@ static int power_on_l2_cache(struct device_node *l2ccc_node, int cpu)
	return -EIO;
}

static inline void msmtitanium_unclamp_cpu(void __iomem *reg)
{
	/* Deassert CPU in sleep state */
	writel_relaxed(0x00000033, reg + CPU_PWR_CTL);
	mb();

	/* Program skew between en_few and en_rest to 16 XO clk cycles,
	close Core logic head switch*/
	writel_relaxed(0x10000001, reg + CPU_PWR_GATE_CTL);
	mb();
	udelay(2);

	/* De-assert coremem clamp */
	writel_relaxed(0x00000031, reg + CPU_PWR_CTL);
	mb();

	/* De-assert Core memory slp_nret_n */
	writel_relaxed(0x00000039, reg + CPU_PWR_CTL);
	mb();
	udelay(2);

	/* De-assert Core memory slp_ret_n */
	writel_relaxed(0x00000239, reg + CPU_PWR_CTL);
	mb();
	udelay(2);

	/* Assert WL_EN_CLK */
	writel_relaxed(0x00004239, reg + CPU_PWR_CTL);
	mb();
	udelay(2);

	/* De-assert WL_EN_CLK */
	writel_relaxed(0x00000239, reg + CPU_PWR_CTL);
	mb();

	/* Deassert Clamp */
	writel_relaxed(0x00000238, reg + CPU_PWR_CTL);
	mb();
	udelay(2);

	/* Deassert Core-n reset */
	writel_relaxed(0x00000208, reg + CPU_PWR_CTL);
	mb();

	/* Assert PWRDUP; */
	writel_relaxed(0x00000288, reg + CPU_PWR_CTL);
	mb();
}

int msmtitanium_unclamp_secondary_arm_cpu(unsigned int cpu)
{

	int ret = 0;
	struct device_node *cpu_node, *acc_node, *l2_node, *l2ccc_node;
	void __iomem *reg;

	cpu_node = of_get_cpu_node(cpu, NULL);
	if (!cpu_node)
		return -ENODEV;

	acc_node = of_parse_phandle(cpu_node, "qcom,acc", 0);
	if (!acc_node) {
			ret = -ENODEV;
			goto out_acc;
	}

	l2_node = of_parse_phandle(cpu_node, "next-level-cache", 0);
	if (!l2_node) {
		ret = -ENODEV;
		goto out_l2;
	}

	l2ccc_node = of_parse_phandle(l2_node, "power-domain", 0);
	if (!l2ccc_node) {
		ret = -ENODEV;
		goto out_l2ccc;
	}

	/*
	* Ensure L2-cache of the CPU is powered on before
	* unclamping cpu power rails.
	*/
	ret = power_on_l2_cache(l2ccc_node, cpu);
	if (ret) {
		pr_err("L2 cache power up failed for CPU%d\n", cpu);
		goto out_acc_reg;
	}

	reg = of_iomap(acc_node, 0);
	if (!reg) {
		ret = -ENOMEM;
		goto out_acc_reg;
	}

	msmtitanium_unclamp_cpu(reg);

	/* Secondary CPU-N is now alive */
	iounmap(reg);
out_acc_reg:
	of_node_put(l2ccc_node);
out_l2ccc:
	of_node_put(l2_node);
out_l2:
	of_node_put(acc_node);
out_acc:
	of_node_put(cpu_node);

	return ret;
}

int msm_unclamp_secondary_arm_cpu(unsigned int cpu)
{

+5 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@
#ifdef CONFIG_MSM_CPU_PWR_CTL
int msm_unclamp_secondary_arm_cpu_sim(unsigned int cpu);
int msm_unclamp_secondary_arm_cpu(unsigned int cpu);
int msmtitanium_unclamp_secondary_arm_cpu(unsigned int cpu);
#else
static inline int msm_unclamp_secondary_arm_cpu_sim(unsigned int cpu)
{
@@ -25,5 +26,9 @@ static inline int msm_unclamp_secondary_arm_cpu(unsigned int cpu)
{
	return 0;
}
static inline int msmtitanium_unclamp_secondary_arm_cpu(unsigned int cpu)
{
	return 0;
}
#endif
#endif /*MSM_CPU_SUBSYS_H_*/