Commit 4bd8459b authored by Peng Fan's avatar Peng Fan Committed by Viresh Kumar
Browse files

cpufreq: imx6q: read OCOTP through nvmem for imx6q



Directly accessing OCOTP registers should be avoided, because
it could not handle OCOTP clks and could not handle defer
proper. With nvmem API, it is safe to access OCOTP registers.

To make sure old dtb could work, the original code still kept.

Signed-off-by: default avatarPeng Fan <peng.fan@nxp.com>
Signed-off-by: default avatarViresh Kumar <viresh.kumar@linaro.org>
parent 3646f50a
Loading
Loading
Loading
Loading
+38 −29
Original line number Diff line number Diff line
@@ -216,20 +216,27 @@ static struct cpufreq_driver imx6q_cpufreq_driver = {
#define OCOTP_CFG3_SPEED_996MHZ		0x2
#define OCOTP_CFG3_SPEED_852MHZ		0x1

static void imx6q_opp_check_speed_grading(struct device *dev)
static int imx6q_opp_check_speed_grading(struct device *dev)
{
	struct device_node *np;
	void __iomem *base;
	u32 val;
	int ret;

	if (of_find_property(dev->of_node, "nvmem-cells", NULL)) {
		ret = nvmem_cell_read_u32(dev, "speed_grade", &val);
		if (ret)
			return ret;
	} else {
		np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-ocotp");
		if (!np)
		return;
			return -ENOENT;

		base = of_iomap(np, 0);
		of_node_put(np);
		if (!base) {
			dev_err(dev, "failed to map ocotp\n");
		goto put_node;
			return -EFAULT;
		}

		/*
@@ -241,6 +248,9 @@ static void imx6q_opp_check_speed_grading(struct device *dev)
		 * We need to set the max speed of ARM according to fuse map.
		 */
		val = readl_relaxed(base + OCOTP_CFG3);
		iounmap(base);
	}

	val >>= OCOTP_CFG3_SPEED_SHIFT;
	val &= 0x3;

@@ -257,9 +267,8 @@ static void imx6q_opp_check_speed_grading(struct device *dev)
			if (dev_pm_opp_disable(dev, 1200000000))
				dev_warn(dev, "failed to disable 1.2GHz OPP\n");
	}
	iounmap(base);
put_node:
	of_node_put(np);

	return 0;
}

#define OCOTP_CFG3_6UL_SPEED_696MHZ	0x2
@@ -387,6 +396,9 @@ static int imx6q_cpufreq_probe(struct platform_device *pdev)
	if (of_machine_is_compatible("fsl,imx6ul") ||
	    of_machine_is_compatible("fsl,imx6ull")) {
		ret = imx6ul_opp_check_speed_grading(cpu_dev);
	} else {
		ret = imx6q_opp_check_speed_grading(cpu_dev);
	}
	if (ret) {
		if (ret == -EPROBE_DEFER)
			goto out_free_opp;
@@ -395,9 +407,6 @@ static int imx6q_cpufreq_probe(struct platform_device *pdev)
			ret);
		goto out_free_opp;
	}
	} else {
		imx6q_opp_check_speed_grading(cpu_dev);
	}

	num = dev_pm_opp_get_opp_count(cpu_dev);
	if (num < 0) {