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

Commit 436c553c authored by Osvaldo Banuelos's avatar Osvaldo Banuelos
Browse files

clk: msm: osm: add support for speed-bin fuses



Add support for reading a speed-bin fuse for each cluster.
This allows for the selection of different OSM look-up tables
and thus different frequency configurations based upon device
fused values.

CRs-Fixed: 1057115
Change-Id: I9a864a2abb655e26fff5982b592b4f3c5dbfca24
Signed-off-by: default avatarOsvaldo Banuelos <osvaldob@codeaurora.org>
parent ab26d098
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -16,12 +16,14 @@ Properties:
	Value type: <prop-encoded-array>
	Definition: Addresses and sizes for the memory of the OSM controller,
		    cluster PLL management, and APCS common register regions.

		    Optionally, the address of the efuse registers used to
		    determine the pwrcl or perfcl speed-bins.
- reg-names
	Usage:      required
	Value type: <stringlist>
	Definition: Address names. Must be "osm", "pwrcl_pll", "perfcl_pll",
		    and "apcs_common".
		    and "apcs_common". Optionally, "pwrcl_efuse" or
		    "perfcl_efuse".
		    Must be specified in the same order as the corresponding
		    addresses are specified in the reg property.

+63 −2
Original line number Diff line number Diff line
@@ -48,6 +48,7 @@
enum clk_osm_bases {
	OSM_BASE,
	PLL_BASE,
	EFUSE_BASE,
	NUM_BASES,
};

@@ -208,6 +209,11 @@ enum clk_osm_trace_packet_id {
#define PLL_DD_D0_USER_CTL_LO		0x17916208
#define PLL_DD_D1_USER_CTL_LO		0x17816208

#define PWRCL_EFUSE_SHIFT	0
#define PWRCL_EFUSE_MASK	0
#define PERFCL_EFUSE_SHIFT	29
#define PERFCL_EFUSE_MASK	0x7

static void __iomem *virt_base;

#define lmh_lite_clk_src_source_val 1
@@ -913,6 +919,35 @@ static int clk_osm_resources_init(struct platform_device *pdev)
		return -ENOMEM;
	}

	/* efuse speed bin fuses are optional */
	res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
					   "pwrcl_efuse");
	if (res) {
		pbase = (unsigned long)res->start;
		vbase = devm_ioremap(&pdev->dev, res->start,
				     resource_size(res));
		if (!vbase) {
			dev_err(&pdev->dev, "Unable to map in pwrcl_efuse base\n");
			return -ENOMEM;
		}
		pwrcl_clk.pbases[EFUSE_BASE] = pbase;
		pwrcl_clk.vbases[EFUSE_BASE] = vbase;
	}

	res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
					   "perfcl_efuse");
	if (res) {
		pbase = (unsigned long)res->start;
		vbase = devm_ioremap(&pdev->dev, res->start,
				     resource_size(res));
		if (!vbase) {
			dev_err(&pdev->dev, "Unable to map in perfcl_efuse base\n");
			return -ENOMEM;
		}
		perfcl_clk.pbases[EFUSE_BASE] = pbase;
		perfcl_clk.vbases[EFUSE_BASE] = vbase;
	}

	vdd_pwrcl = devm_regulator_get(&pdev->dev, "vdd-pwrcl");
	if (IS_ERR(vdd_pwrcl)) {
		rc = PTR_ERR(vdd_pwrcl);
@@ -2441,9 +2476,11 @@ static unsigned long osm_clk_init_rate = 200000000;

static int cpu_clock_osm_driver_probe(struct platform_device *pdev)
{
	char perfclspeedbinstr[] = "qcom,perfcl-speedbin0-v0";
	char pwrclspeedbinstr[] = "qcom,pwrcl-speedbin0-v0";
	int rc, cpu;
	int speedbin = 0, pvs_ver = 0;
	u32 pte_efuse;
	char pwrclspeedbinstr[] = "qcom,pwrcl-speedbin0-v0";
	char perfclspeedbinstr[] = "qcom,perfcl-speedbin0-v0";
	struct cpu_cycle_counter_cb cb = {
		.get_cpu_cycle_counter = clk_osm_get_cpu_cycle_counter,
	};
@@ -2462,6 +2499,18 @@ static int cpu_clock_osm_driver_probe(struct platform_device *pdev)
		return rc;
	}

	if (pwrcl_clk.vbases[EFUSE_BASE]) {
		/* Multiple speed-bins are supported */
		pte_efuse = readl_relaxed(pwrcl_clk.vbases[EFUSE_BASE]);
		speedbin = ((pte_efuse >> PWRCL_EFUSE_SHIFT) &
			    PWRCL_EFUSE_MASK);
		snprintf(pwrclspeedbinstr, ARRAY_SIZE(pwrclspeedbinstr),
			 "qcom,pwrcl-speedbin%d-v%d", speedbin, pvs_ver);
	}

	dev_info(&pdev->dev, "using pwrcl speed bin %u and pvs_ver %d\n",
		 speedbin, pvs_ver);

	rc = clk_osm_get_lut(pdev, &pwrcl_clk,
			     pwrclspeedbinstr);
	if (rc) {
@@ -2470,6 +2519,18 @@ static int cpu_clock_osm_driver_probe(struct platform_device *pdev)
		return rc;
	}

	if (perfcl_clk.vbases[EFUSE_BASE]) {
		/* Multiple speed-bins are supported */
		pte_efuse = readl_relaxed(perfcl_clk.vbases[EFUSE_BASE]);
		speedbin = ((pte_efuse >> PERFCL_EFUSE_SHIFT) &
			    PERFCL_EFUSE_MASK);
		snprintf(perfclspeedbinstr, ARRAY_SIZE(perfclspeedbinstr),
			 "qcom,perfcl-speedbin%d-v%d", speedbin, pvs_ver);
	}

	dev_info(&pdev->dev, "using perfcl speed bin %u and pvs_ver %d\n",
		 speedbin, pvs_ver);

	rc = clk_osm_get_lut(pdev, &perfcl_clk, perfclspeedbinstr);
	if (rc) {
		dev_err(&pdev->dev, "Unable to get OSM LUT for perf cluster, rc=%d\n",