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

Commit dc2ff9bf authored by Karthik Parsha's avatar Karthik Parsha
Browse files

soc: cpu_pwr_ctl: Add support to configure cpu retention ldo



Add support to configure the cpu retention ldo voltage. This value needs to
be configured when a core is coldbooted. The core will then be able to
enter retention at the programmed retention voltage.

Change-Id: I48e0f19baaf62522cee328437770d601d4f0dfc5
Signed-off-by: default avatarKarthik Parsha <kparsha@codeaurora.org>
parent 81892a2f
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -211,6 +211,11 @@ nodes to be present and contain the properties described below.
		Value type: <phandle>
		Definition: Specifies the ACC[2] node associated with this CPU.

	- qcom,ldo
		Usage: required for systems that need LDO configuration.
		Value type: <phandle>
		Definition: Specifies the LDO reference node associated with
			    this cpu.

Example 1 (dual-cluster big.LITTLE system 32-bit):

+22 −0
Original line number Diff line number Diff line
*8994 CPU LDO Retention Voltage Configuration

This device is used to program the appropriate LDO voltage for 8994 target
from the pre-programmed register.

Required properties:
- compatible:
		Must be "qcom,8994-cpu-ldo-vref"
- reg:
		The register holds the base address to LDO_BHS. Use this
		register base to configure the LDO for all the cpus.
- qcom,ldo-vref-ret:
		Value to which the ldo voltage reference needs to be
		programmed.
		Value to be used is encoded. 0x20 = 0.5V and 0x2a = 0x55V

Example:
	ldo0:ldo-vref@f9070000 {
		compatible = "qcom,8994-cpu-ldo-vref";
		reg = <0xf9070000 0x30>,
		qcom,ldo-vref-ret = <0x20>;
	};
+18 −1
Original line number Diff line number Diff line
@@ -126,6 +126,20 @@ static int __init msm_cpu_prepare(unsigned int cpu)
	return 0;
}


static int __init msm8994_cpu_prepare(unsigned int cpu)
{
	int ret;

	if (per_cpu(cold_boot_done, 0) == false) {
		ret = msm8994_cpu_ldo_config(0);
		if (ret)
			return ret;
	}

	return msm_cpu_prepare(cpu);
}

static int msm_cpu_boot(unsigned int cpu)
{
	int ret = 0;
@@ -159,6 +173,9 @@ static int msm8994_cpu_boot(unsigned int cpu)
			if (ret)
				return ret;
		}
		ret = msm8994_cpu_ldo_config(cpu);
		if (ret)
			return ret;
		per_cpu(cold_boot_done, cpu) = true;
	}
	return secondary_pen_release(cpu);
@@ -217,7 +234,7 @@ CPU_METHOD_OF_DECLARE(msm_cortex_a_ops, &msm_cortex_a_ops);
static const struct cpu_operations msm8994_cortex_a_ops = {
	.name		= "qcom,8994-arm-cortex-acc",
	.cpu_init	= msm_cpu_init,
	.cpu_prepare	= msm_cpu_prepare,
	.cpu_prepare	= msm8994_cpu_prepare,
	.cpu_boot	= msm8994_cpu_boot,
	.cpu_postboot	= msm_cpu_postboot,
#ifdef CONFIG_HOTPLUG_CPU
+85 −0
Original line number Diff line number Diff line
@@ -45,6 +45,10 @@
#define L2_SPM_STS		0xc
#define L2_VREG_CTL		0x1c

#define APC_LDO_CFG1		0xc
#define APC_LDO_CFG2		0x10
#define APC_LDO_VREF_CFG	0x4

/*
 * struct msm_l2ccc_of_info: represents of data for l2 cache clock controller.
 * @compat: compat string for l2 cache clock controller
@@ -288,6 +292,87 @@ static int power_on_l2_cache(struct device_node *l2ccc_node, int cpu)
	return -EIO;
}

int msm8994_cpu_ldo_config(unsigned int cpu)
{
	struct device_node *cpu_node, *ldo_node;
	void __iomem *ldo_bhs_reg_base;
	u32 ldo_vref_ret = 0;
	u32 ref_val = 0;
	int ret = 0;
	u32 val;

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

	ldo_node = of_parse_phandle(cpu_node, "qcom,ldo", 0);
	if (!ldo_node) {
		pr_debug("LDO is not configured to enable retention\n");
		goto exit_cpu_node;
	}

	ldo_bhs_reg_base = of_iomap(ldo_node, 0);
	if (!ldo_bhs_reg_base) {
		pr_err("LDO configuration failed due to iomap failure\n");
		ret = -ENOMEM;
		goto exit_cpu_node;
	}

	ret = of_property_read_u32(ldo_node, "qcom,ldo-vref-ret", &ref_val);
	if (ret) {
		pr_err("Failed to get LDO Reference voltage for CPU%u\n",
			cpu);
		BUG_ON(1);
	}

	/* Program LDO CFG registers */
	val = readl_relaxed(ldo_bhs_reg_base + APC_LDO_CFG1);
	val = (val & 0xffffff00) | 0xc2;
	writel_relaxed(val, ldo_bhs_reg_base + APC_LDO_CFG1);
	val = readl_relaxed(ldo_bhs_reg_base + APC_LDO_CFG1);
	val = (val & 0xffff00ff) | (0x98 << 8);
	writel_relaxed(val, ldo_bhs_reg_base + APC_LDO_CFG1);
	val = readl_relaxed(ldo_bhs_reg_base + APC_LDO_CFG2);
	val = (val & 0xffffff00) | 0x60;
	writel_relaxed(val, ldo_bhs_reg_base + APC_LDO_CFG2);
	val = readl_relaxed(ldo_bhs_reg_base + APC_LDO_CFG2);
	val = (val & 0xff00ffff) | (0x4a << 16);
	writel_relaxed(val, ldo_bhs_reg_base + APC_LDO_CFG2);

	/* Bring LDO out of reset */
	ldo_vref_ret = readl_relaxed(ldo_bhs_reg_base + APC_LDO_VREF_CFG);
	ldo_vref_ret &= ~BIT(16);
	writel_relaxed(ldo_vref_ret, ldo_bhs_reg_base + APC_LDO_VREF_CFG);

	/* Program the retention voltage */
	ldo_vref_ret = readl_relaxed(ldo_bhs_reg_base + APC_LDO_VREF_CFG);
	ldo_vref_ret = (ldo_vref_ret & 0xffff80ff) | (ref_val << 8);
	writel_relaxed(ldo_vref_ret, ldo_bhs_reg_base + APC_LDO_VREF_CFG);

	/* Write the sequence to latch on the LDO voltage */
	writel_relaxed(0x0, ldo_bhs_reg_base);
	writel_relaxed(0x1, ldo_bhs_reg_base);
	/* After writing 1 to the UPDATE register, '1 xo clk cycle' delay
	 * is required for the update to take effect. This delay needs to
	 * start after the reg write is complete. Make sure that the reg
	 * write is complete using a memory barrier */
	mb();
	usleep(1);
	writel_relaxed(0x0, ldo_bhs_reg_base);
	/* Use a memory barrier to make sure the reg write is complete before
	 * the node is unmapped. */
	mb();

	of_node_put(ldo_node);

	iounmap(ldo_bhs_reg_base);

exit_cpu_node:
	of_node_put(cpu_node);

	return ret;
}

int msm8994_unclamp_secondary_arm_cpu(unsigned int cpu)
{

+5 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
int msm_unclamp_secondary_arm_cpu_sim(unsigned int cpu);
int msm_unclamp_secondary_arm_cpu(unsigned int cpu);
int msm8994_unclamp_secondary_arm_cpu(unsigned int cpu);
int msm8994_cpu_ldo_config(unsigned int cpu);
#else
static inline int msm_unclamp_secondary_arm_cpu_sim(unsigned int cpu)
{
@@ -30,5 +31,9 @@ static inline int msm8994_unclamp_secondary_arm_cpu(unsigned int cpu)
{
	return 0;
}
static inline int msm8994_cpu_ldo_config(unsigned int cpu)
{
	return 0;
}
#endif
#endif /*MSM_CPU_SUBSYS_H_*/