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

Commit 1a5da77f authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

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

parents e9171fb6 820f6f9d
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_*/