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

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

Merge "qcom: clock-cpu-8994: Populate absolute voltages in CPU-device OPP tables"

parents 4b6f74ad b6acb90f
Loading
Loading
Loading
Loading
+129 −16
Original line number Diff line number Diff line
@@ -1178,11 +1178,39 @@ static void perform_v1_fixup(void)
	__cpu_mux_set_sel(&a53_lf_mux, 1);
}

static int add_opp(struct clk *c, struct device *dev, unsigned long max_rate)
static long corner_to_voltage(unsigned long corner, struct device *dev)
{
	struct opp *oppl;
	long uv;

	rcu_read_lock();
	oppl = dev_pm_opp_find_freq_exact(dev, corner, true);
	rcu_read_unlock();
	if (IS_ERR_OR_NULL(oppl))
		return -EINVAL;

	rcu_read_lock();
	uv = dev_pm_opp_get_voltage(oppl);
	rcu_read_unlock();

	return uv;
}

static int add_opp(struct clk *c, struct device *cpudev, struct device *vregdev,
			unsigned long max_rate)
{
	unsigned long rate = 0;
	int level;
	long ret;
	long ret, uv, corner;
	bool use_voltages = false;
	struct opp *oppl;

	rcu_read_lock();
	/* Check if the regulator driver has already populated OPP tables */
	oppl = dev_pm_opp_find_freq_exact(vregdev, 2, true);
	rcu_read_unlock();
	if (!IS_ERR_OR_NULL(oppl))
		use_voltages = true;

	while (1) {
		ret = clk_round_rate(c, rate + 1);
@@ -1196,11 +1224,43 @@ static int add_opp(struct clk *c, struct device *dev, unsigned long max_rate)
			pr_warn("clock-cpu: no uv for %lu.\n", rate);
			return -EINVAL;
		}
		ret = dev_pm_opp_add(dev, rate, c->vdd_class->vdd_uv[level]);
		uv = corner = c->vdd_class->vdd_uv[level];
		/*
		 * If corner to voltage mapping is available, populate the OPP
		 * table with the voltages rather than corners.
		 */
		if (use_voltages) {
			uv = corner_to_voltage(corner, vregdev);
			if (uv < 0) {
				pr_warn("clock-cpu: no uv for corner %lu\n",
					 corner);
				return uv;
			}
			ret = dev_pm_opp_add(cpudev, rate, uv);
			if (ret) {
				pr_warn("clock-cpu: couldn't add OPP for %lu\n",
					 rate);
				return ret;
			}
		} else {
			/*
			 * Populate both CPU and regulator devices with the
			 * freq-to-corner OPP table to maintain backward
			 * compatibility.
			 */
			ret = dev_pm_opp_add(cpudev, rate, corner);
			if (ret) {
				pr_warn("clock-cpu: couldn't add OPP for %lu\n",
					rate);
				return ret;
			}
			ret = dev_pm_opp_add(vregdev, rate, corner);
			if (ret) {
			pr_warn("clock-cpu: failed to add OPP for %lu\n", rate);
				pr_warn("clock-cpu: couldn't add OPP for %lu\n",
					rate);
				return ret;
			}
		}
		if (rate >= max_rate)
			break;
	}
@@ -1208,20 +1268,52 @@ static int add_opp(struct clk *c, struct device *dev, unsigned long max_rate)
	return 0;
}

static void print_opp_table(int a53_cpu, int a57_cpu)
{
	struct opp *oppfmax, *oppfmin;
	unsigned long apc0_fmax = a53_clk.c.fmax[a53_clk.c.num_fmax - 1];
	unsigned long apc1_fmax = a57_clk.c.fmax[a57_clk.c.num_fmax - 1];
	unsigned long apc0_fmin = a53_clk.c.fmax[1];
	unsigned long apc1_fmin = a57_clk.c.fmax[1];

	rcu_read_lock();
	oppfmax = dev_pm_opp_find_freq_exact(get_cpu_device(a53_cpu), apc0_fmax,
					     true);
	oppfmin = dev_pm_opp_find_freq_exact(get_cpu_device(a53_cpu), apc0_fmin,
					     true);
	/*
	 * One time information during boot. Important to know that this looks
	 * sane since it can eventually make its way to the scheduler.
	 */
	pr_info("clock_cpu: a53: OPP voltage for %lu: %ld\n", apc0_fmin,
		dev_pm_opp_get_voltage(oppfmin));
	pr_info("clock_cpu: a53: OPP voltage for %lu: %ld\n", apc0_fmax,
		dev_pm_opp_get_voltage(oppfmax));

	oppfmax = dev_pm_opp_find_freq_exact(get_cpu_device(a57_cpu), apc1_fmax,
					     true);
	oppfmin = dev_pm_opp_find_freq_exact(get_cpu_device(a57_cpu), apc1_fmin,
					     true);
	pr_info("clock_cpu: a57: OPP voltage for %lu: %lu\n", apc1_fmin,
		dev_pm_opp_get_voltage(oppfmin));
	pr_info("clock_cpu: a57: OPP voltage for %lu: %lu\n", apc1_fmax,
		dev_pm_opp_get_voltage(oppfmax));
	rcu_read_unlock();
}

static void populate_opp_table(struct platform_device *pdev)
{
	struct platform_device *apc0_dev, *apc1_dev;
	struct device_node *apc0_node, *apc1_node;
	unsigned long apc0_fmax, apc1_fmax;
	int cpu, a53_cpu, a57_cpu;

	apc0_node = of_parse_phandle(pdev->dev.of_node, "vdd-a53-supply", 0);
	apc1_node = of_parse_phandle(pdev->dev.of_node, "vdd-a57-supply", 0);

	if (!apc0_node) {
		pr_err("can't find the apc0 dt node.\n");
		return;
	}

	if (!apc1_node) {
		pr_err("can't find the apc1 dt node.\n");
		return;
@@ -1229,12 +1321,10 @@ static void populate_opp_table(struct platform_device *pdev)

	apc0_dev = of_find_device_by_node(apc0_node);
	apc1_dev = of_find_device_by_node(apc1_node);

	if (!apc0_dev) {
		pr_err("can't find the apc0 device node.\n");
		return;
	}

	if (!apc1_dev) {
		pr_err("can't find the apc1 device node.\n");
		return;
@@ -1243,16 +1333,30 @@ static void populate_opp_table(struct platform_device *pdev)
	apc0_fmax = a53_clk.c.fmax[a53_clk.c.num_fmax - 1];
	apc1_fmax = a57_clk.c.fmax[a57_clk.c.num_fmax - 1];

	WARN(add_opp(&a53_clk.c, &apc0_dev->dev, apc0_fmax),
	for_each_possible_cpu(cpu) {
		if (logical_cpu_to_clk(cpu) == &a53_clk.c) {
			a53_cpu = cpu;
			WARN(add_opp(&a53_clk.c, get_cpu_device(cpu),
				     &apc0_dev->dev, apc0_fmax),
				     "Failed to add OPP levels for A53\n");
	WARN(add_opp(&a57_clk.c, &apc1_dev->dev, apc1_fmax),
		}
		if (logical_cpu_to_clk(cpu) == &a57_clk.c) {
			a57_cpu = cpu;
			WARN(add_opp(&a57_clk.c, get_cpu_device(cpu),
				     &apc1_dev->dev, apc1_fmax),
				     "Failed to add OPP levels for A57\n");
		}
	}

	/* One time print during bootup */
	pr_info("clock-cpu-8994: OPP tables populated.\n");
	pr_info("clock-cpu-8994: OPP tables populated (cpu %d and %d)",
		a53_cpu, a57_cpu);

	print_opp_table(a53_cpu, a57_cpu);
}

static int a57speedbin;
struct platform_device *cpu_clock_8994_dev;

static int cpu_clock_8994_driver_probe(struct platform_device *pdev)
{
@@ -1264,6 +1368,7 @@ static int cpu_clock_8994_driver_probe(struct platform_device *pdev)
	char a57speedbinstr[] = "qcom,a57-speedbinXX-vXX";

	v2 = msm8994_v2;
	cpu_clock_8994_dev = pdev;

	a53_pll0_main.c.flags = CLKFLAG_NO_RATE_CACHE;
	a57_pll0_main.c.flags = CLKFLAG_NO_RATE_CACHE;
@@ -1395,7 +1500,6 @@ static int cpu_clock_8994_driver_probe(struct platform_device *pdev)
		clk_set_rate(&cci_clk.c, 300000000);
	}

	populate_opp_table(pdev);

	put_online_cpus();

@@ -1417,6 +1521,15 @@ static struct platform_driver cpu_clock_8994_driver = {
	},
};

/* CPU devices are not currently available in arch_initcall */
static int __init cpu_clock_8994_init_opp(void)
{
	if (cpu_clock_8994_dev)
		populate_opp_table(cpu_clock_8994_dev);
	return 0;
}
module_init(cpu_clock_8994_init_opp);

static int __init cpu_clock_8994_init(void)
{
	return platform_driver_register(&cpu_clock_8994_driver);