summaryrefslogtreecommitdiffstats
path: root/drivers/cpufreq
diff options
context:
space:
mode:
authorPeng Fan <peng.fan@nxp.com>2020-03-03 03:14:50 +0100
committerViresh Kumar <viresh.kumar@linaro.org>2020-03-03 12:16:36 +0100
commit4bd8459b6c3f59eaa93d5e942b58346f1b8c98da (patch)
tree166ff30e196224f75efdb60397e0bc018256a9e8 /drivers/cpufreq
parentcpufreq: imx6q: fix error handling (diff)
downloadlinux-4bd8459b6c3f59eaa93d5e942b58346f1b8c98da.tar.xz
linux-4bd8459b6c3f59eaa93d5e942b58346f1b8c98da.zip
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: Peng Fan <peng.fan@nxp.com> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
Diffstat (limited to 'drivers/cpufreq')
-rw-r--r--drivers/cpufreq/imx6q-cpufreq.c67
1 files changed, 38 insertions, 29 deletions
diff --git a/drivers/cpufreq/imx6q-cpufreq.c b/drivers/cpufreq/imx6q-cpufreq.c
index edef3399c979..285b8e9aa185 100644
--- a/drivers/cpufreq/imx6q-cpufreq.c
+++ b/drivers/cpufreq/imx6q-cpufreq.c
@@ -216,31 +216,41 @@ 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;
- np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-ocotp");
- if (!np)
- return;
+ 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 -ENOENT;
- base = of_iomap(np, 0);
- if (!base) {
- dev_err(dev, "failed to map ocotp\n");
- goto put_node;
+ base = of_iomap(np, 0);
+ of_node_put(np);
+ if (!base) {
+ dev_err(dev, "failed to map ocotp\n");
+ return -EFAULT;
+ }
+
+ /*
+ * SPEED_GRADING[1:0] defines the max speed of ARM:
+ * 2b'11: 1200000000Hz;
+ * 2b'10: 996000000Hz;
+ * 2b'01: 852000000Hz; -- i.MX6Q Only, exclusive with 996MHz.
+ * 2b'00: 792000000Hz;
+ * We need to set the max speed of ARM according to fuse map.
+ */
+ val = readl_relaxed(base + OCOTP_CFG3);
+ iounmap(base);
}
- /*
- * SPEED_GRADING[1:0] defines the max speed of ARM:
- * 2b'11: 1200000000Hz;
- * 2b'10: 996000000Hz;
- * 2b'01: 852000000Hz; -- i.MX6Q Only, exclusive with 996MHz.
- * 2b'00: 792000000Hz;
- * We need to set the max speed of ARM according to fuse map.
- */
- val = readl_relaxed(base + OCOTP_CFG3);
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,16 +396,16 @@ 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);
- if (ret) {
- if (ret == -EPROBE_DEFER)
- goto out_free_opp;
-
- dev_err(cpu_dev, "failed to read ocotp: %d\n",
- ret);
- goto out_free_opp;
- }
} else {
- imx6q_opp_check_speed_grading(cpu_dev);
+ ret = imx6q_opp_check_speed_grading(cpu_dev);
+ }
+ if (ret) {
+ if (ret == -EPROBE_DEFER)
+ goto out_free_opp;
+
+ dev_err(cpu_dev, "failed to read ocotp: %d\n",
+ ret);
+ goto out_free_opp;
}
num = dev_pm_opp_get_opp_count(cpu_dev);