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

Commit 435438a0 authored by Vikram Mulukutla's avatar Vikram Mulukutla Committed by Karthik Parsha
Browse files

clk: qcom: clock-cpu-8994: Add support for HW controlled clock trees



The MSM8994V2 SPM can support the disabling and enabling
of the CPU PLLs during power collapse and resume. In order
to ensure exclusivity of hardware versus software control,
perform the following steps before changing the rate of a
target cluster's clock:

1. Use PM QoS to prevent the low power mode that triggers
   hardware control.
2. Schedule an IPI on any core of the target cluster.
3. Wait for the IPI in (2) to finish execution.
4. Perform the clock switch.
5. Remove the PM QoS request in (1).

The steps above ensure that the target cluster does not
enter the low power mode that would enable hardware control
of the PLLs while the rate of the clock tree is being
switched.

Change-Id: I3f8b26a6d74128e63ceccf62462671845912f224
Signed-off-by: default avatarVikram Mulukutla <markivx@codeaurora.org>
parent b55a0de8
Loading
Loading
Loading
Loading
+43 −1
Original line number Original line Diff line number Diff line
@@ -26,6 +26,7 @@
#include <linux/platform_device.h>
#include <linux/platform_device.h>
#include <linux/of_platform.h>
#include <linux/of_platform.h>
#include <linux/pm_opp.h>
#include <linux/pm_opp.h>
#include <linux/pm_qos.h>


#include <soc/qcom/scm.h>
#include <soc/qcom/scm.h>
#include <soc/qcom/clock-pll.h>
#include <soc/qcom/clock-pll.h>
@@ -719,6 +720,8 @@ static struct mux_clk a57_hf_mux_v2 = {


struct cpu_clk_8994 {
struct cpu_clk_8994 {
	u32 cpu_reg_mask;
	u32 cpu_reg_mask;
	cpumask_t cpumask;
	bool hw_low_power_ctrl;
	struct clk c;
	struct clk c;
};
};


@@ -739,9 +742,39 @@ static long cpu_clk_8994_round_rate(struct clk *c, unsigned long rate)
	return clk_round_rate(c->parent, rate);
	return clk_round_rate(c->parent, rate);
}
}


static void do_nothing(void *unused) { }

#define CPU_LATENCY_NO_L2_PC_US (800 - 1)

static int cpu_clk_8994_set_rate(struct clk *c, unsigned long rate)
static int cpu_clk_8994_set_rate(struct clk *c, unsigned long rate)
{
{
	return clk_set_rate(c->parent, rate);
	struct pm_qos_request req = {0};
	int ret;
	struct cpu_clk_8994 *cpuclk = to_cpu_clk_8994(c);
	bool hw_low_power_ctrl = cpuclk->hw_low_power_ctrl;

	/*
	 * If hardware control of the clock tree is enabled during power
	 * collapse, setup a PM QOS request to prevent power collapse and
	 * wake up one of the CPUs in this clock domain, to ensure software
	 * control while the clock rate is being switched.
	 */
	if (hw_low_power_ctrl) {
		req.cpus_affine = cpuclk->cpumask;
		req.type = PM_QOS_REQ_AFFINE_CORES;
		pm_qos_add_request(&req, PM_QOS_CPU_DMA_LATENCY,
				   CPU_LATENCY_NO_L2_PC_US);

		ret = smp_call_function_any(&cpuclk->cpumask, do_nothing,
						NULL, 1);
	}

	ret = clk_set_rate(c->parent, rate);

	if (hw_low_power_ctrl)
		pm_qos_remove_request(&req);

	return ret;
}
}


static struct clk_ops clk_ops_cpu_8994 = {
static struct clk_ops clk_ops_cpu_8994 = {
@@ -1395,6 +1428,8 @@ static void init_v2_data(void)
	a57_div_clk.data.min_div = 8;
	a57_div_clk.data.min_div = 8;
	a57_div_clk.data.max_div = 8;
	a57_div_clk.data.max_div = 8;
	a57_div_clk.data.div = 8;
	a57_div_clk.data.div = 8;
	a53_clk.hw_low_power_ctrl = true;
	a57_clk.hw_low_power_ctrl = true;
}
}


static int a57speedbin;
static int a57speedbin;
@@ -1461,6 +1496,13 @@ static int cpu_clock_8994_driver_probe(struct platform_device *pdev)
		return ret;
		return ret;
	}
	}


	for_each_possible_cpu(cpu) {
		if (logical_cpu_to_clk(cpu) == &a53_clk.c)
			cpumask_set_cpu(cpu, &a53_clk.cpumask);
		if (logical_cpu_to_clk(cpu) == &a57_clk.c)
			cpumask_set_cpu(cpu, &a57_clk.cpumask);
	}

	get_online_cpus();
	get_online_cpus();


	if (!v2)
	if (!v2)