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

Commit eda782e1 authored by Deepak Katragadda's avatar Deepak Katragadda
Browse files

clk: qcom: clk-cpu-osm: Rework the OPP table filling logic



Add support to allow filling the L3 clock OPP tables for more
than one device.
Additionally, merge the l3-dev0 and l3-dev4 properties to
l3_devs.

Change-Id: Id6ef4164f1f9efb399c43222c1126718f5358e61
Signed-off-by: default avatarDeepak Katragadda <dkatraga@codeaurora.org>
parent 43db9370
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -23,6 +23,13 @@ Properties:
		    "osm_perfcl_base".
		    Must be specified in the same order as the corresponding
		    addresses are specified in the reg property.

- l3-devs
	Usage: optional
	Value type: <phandle>
	Definition: List of phandles to devices that the OPP tables with the L3
		    frequency and voltage mappings are loaded for.

- clock-names
	Usage:      required
	Value type: <string>
@@ -41,6 +48,8 @@ Example:
			<0x17d45800 0x1400>;
		reg-names = "osm_l3_base", "osm_pwrcl_base", "osm_perfcl_base";

		l3-devs = <&phandle0 &phandle1 &phandle2>;

		clock-names = "xo_ao";
		clocks = <&clock_rpmh RPMH_CXO_CLK_A>;
		#clock-cells = <1>;
+1 −2
Original line number Diff line number Diff line
@@ -1210,8 +1210,7 @@
			<0x17d45800 0x1400>;
		reg-names = "osm_l3_base", "osm_pwrcl_base", "osm_perfcl_base";

		l3-dev0 = <&l3_cpu0>;
		l3-dev4 = <&l3_cpu4>;
		l3-devs = <&l3_cpu0 &l3_cpu4>;

		clock-names = "xo_ao";
		clocks = <&clock_rpmh RPMH_CXO_CLK_A>;
+78 −43
Original line number Diff line number Diff line
@@ -637,12 +637,12 @@ static u32 find_voltage(struct clk_osm *c, unsigned long rate)
	return -EINVAL;
}

static int add_opp(struct clk_osm *c, struct device *dev)
static int add_opp(struct clk_osm *c, struct device **device_list, int count)
{
	unsigned long rate = 0;
	u32 uv;
	long rc;
	int j = 0;
	int i, j = 0;
	unsigned long min_rate = c->hw.init->rate_max[0];
	unsigned long max_rate =
			c->hw.init->rate_max[c->hw.init->num_rate_max - 1];
@@ -655,11 +655,13 @@ static int add_opp(struct clk_osm *c, struct device *dev)
			return -EINVAL;
		}

		rc = dev_pm_opp_add(dev, rate, uv);
		for (i = 0; i < count; i++) {
			rc = dev_pm_opp_add(device_list[i], rate, uv);
			if (rc) {
				pr_warn("failed to add OPP for %lu\n", rate);
				return rc;
			}
		}

		/*
		 * Print the OPP pair for the lowest and highest frequency for
@@ -667,13 +669,18 @@ static int add_opp(struct clk_osm *c, struct device *dev)
		 * this information will be used by thermal mitigation and the
		 * scheduler.
		 */
		if (rate == min_rate)
		if (rate == min_rate) {
			for (i = 0; i < count; i++) {
				pr_info("Set OPP pair (%lu Hz, %d uv) on %s\n",
				rate, uv, dev_name(dev));
					rate, uv, dev_name(device_list[i]));
			}
		}

		if (rate == max_rate && max_rate != min_rate) {
			for (i = 0; i < count; i++) {
				pr_info("Set OPP pair (%lu Hz, %d uv) on %s\n",
				rate, uv, dev_name(dev));
					rate, uv, dev_name(device_list[i]));
			}
			break;
		}

@@ -683,14 +690,70 @@ static int add_opp(struct clk_osm *c, struct device *dev)
	return 0;
}

static int derive_device_list(struct device **device_list,
				struct device_node *np,
				char *phandle_name, int count)
{
	int i;
	struct platform_device *pdev;
	struct device_node *dev_node;

	for (i = 0; i < count; i++) {
		dev_node = of_parse_phandle(np, phandle_name, i);
		if (!dev_node) {
			pr_err("Unable to get device_node pointer for opp-handle (%s)\n",
					phandle_name);
			return -ENODEV;
		}

		pdev = of_find_device_by_node(dev_node);
		if (!pdev) {
			pr_err("Unable to find platform_device node for opp-handle (%s)\n",
						phandle_name);
			return -ENODEV;
		}
		device_list[i] = &pdev->dev;
	}
	return 0;
}

static void populate_l3_opp_table(struct device_node *np, char *phandle_name)
{
	struct device **device_list;
	int len, count, ret = 0;

	if (of_find_property(np, phandle_name, &len)) {
		count = len / sizeof(u32);

		device_list = kcalloc(count, sizeof(struct device *),
							GFP_KERNEL);
		if (!device_list)
			return;

		ret = derive_device_list(device_list, np, phandle_name, count);
		if (ret < 0) {
			pr_err("Failed to fill device_list for %s\n",
							phandle_name);
			return;
		}
	} else {
		pr_debug("Unable to find %s\n", phandle_name);
		return;
	}

	if (add_opp(&l3_clk, device_list, count))
		pr_err("Failed to add OPP levels for %s\n", phandle_name);

	kfree(device_list);
}

static void populate_opp_table(struct platform_device *pdev)
{
	int cpu;
	struct device *cpu_dev;
	struct clk_osm *c, *parent;
	struct clk_hw *hw_parent;
	struct device_node *l3_node_0, *l3_node_4;
	struct platform_device *l3_dev_0, *l3_dev_4;
	struct device_node *np = pdev->dev.of_node;

	for_each_possible_cpu(cpu) {
		c = logical_cpu_to_clk(cpu);
@@ -703,40 +766,12 @@ static void populate_opp_table(struct platform_device *pdev)
		parent = to_clk_osm(hw_parent);
		cpu_dev = get_cpu_device(cpu);
		if (cpu_dev)
			if (add_opp(parent, cpu_dev))
			if (add_opp(parent, &cpu_dev, 1))
				pr_err("Failed to add OPP levels for %s\n",
					dev_name(cpu_dev));
	}

	l3_node_0 = of_parse_phandle(pdev->dev.of_node, "l3-dev0", 0);
	if (!l3_node_0) {
		pr_err("can't find the L3 cluster 0 dt node\n");
		return;
	}

	l3_dev_0 = of_find_device_by_node(l3_node_0);
	if (!l3_dev_0) {
		pr_err("can't find the L3 cluster 0 dt device\n");
		return;
	}

	if (add_opp(&l3_clk, &l3_dev_0->dev))
		pr_err("Failed to add OPP levels for L3 cluster 0\n");

	l3_node_4 = of_parse_phandle(pdev->dev.of_node, "l3-dev4", 0);
	if (!l3_node_4) {
		pr_err("can't find the L3 cluster 1 dt node\n");
		return;
	}

	l3_dev_4 = of_find_device_by_node(l3_node_4);
	if (!l3_dev_4) {
		pr_err("can't find the L3 cluster 1 dt device\n");
		return;
	}

	if (add_opp(&l3_clk, &l3_dev_4->dev))
		pr_err("Failed to add OPP levels for L3 cluster 1\n");
	populate_l3_opp_table(np, "l3-devs");
}

static u64 clk_osm_get_cpu_cycle_counter(int cpu)