Skip to content

Commit 2733fb0

Browse files
Anson-Huangrafaeljw
authored andcommitted
cpufreq: imx6q: read OCOTP through nvmem for imx6ul/imx6ull
On i.MX6UL/i.MX6ULL, accessing OCOTP directly is wrong because the ocotp clock needs to be enabled first. Add support for reading OCOTP through the nvmem API, and keep the old method there to support old dtb. Signed-off-by: Anson Huang <[email protected]> Acked-by: Viresh Kumar <[email protected]> Signed-off-by: Rafael J. Wysocki <[email protected]>
1 parent 9d21d33 commit 2733fb0

1 file changed

Lines changed: 35 additions & 17 deletions

File tree

drivers/cpufreq/imx6q-cpufreq.c

Lines changed: 35 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <linux/cpu_cooling.h>
1313
#include <linux/err.h>
1414
#include <linux/module.h>
15+
#include <linux/nvmem-consumer.h>
1516
#include <linux/of.h>
1617
#include <linux/of_address.h>
1718
#include <linux/pm_opp.h>
@@ -290,20 +291,32 @@ static void imx6q_opp_check_speed_grading(struct device *dev)
290291
#define OCOTP_CFG3_6ULL_SPEED_792MHZ 0x2
291292
#define OCOTP_CFG3_6ULL_SPEED_900MHZ 0x3
292293

293-
static void imx6ul_opp_check_speed_grading(struct device *dev)
294+
static int imx6ul_opp_check_speed_grading(struct device *dev)
294295
{
295-
struct device_node *np;
296-
void __iomem *base;
297296
u32 val;
297+
int ret = 0;
298298

299-
np = of_find_compatible_node(NULL, NULL, "fsl,imx6ul-ocotp");
300-
if (!np)
301-
return;
299+
if (of_find_property(dev->of_node, "nvmem-cells", NULL)) {
300+
ret = nvmem_cell_read_u32(dev, "speed_grade", &val);
301+
if (ret)
302+
return ret;
303+
} else {
304+
struct device_node *np;
305+
void __iomem *base;
306+
307+
np = of_find_compatible_node(NULL, NULL, "fsl,imx6ul-ocotp");
308+
if (!np)
309+
return -ENOENT;
310+
311+
base = of_iomap(np, 0);
312+
of_node_put(np);
313+
if (!base) {
314+
dev_err(dev, "failed to map ocotp\n");
315+
return -EFAULT;
316+
}
302317

303-
base = of_iomap(np, 0);
304-
if (!base) {
305-
dev_err(dev, "failed to map ocotp\n");
306-
goto put_node;
318+
val = readl_relaxed(base + OCOTP_CFG3);
319+
iounmap(base);
307320
}
308321

309322
/*
@@ -314,7 +327,6 @@ static void imx6ul_opp_check_speed_grading(struct device *dev)
314327
* 2b'11: 900000000Hz on i.MX6ULL only;
315328
* We need to set the max speed of ARM according to fuse map.
316329
*/
317-
val = readl_relaxed(base + OCOTP_CFG3);
318330
val >>= OCOTP_CFG3_SPEED_SHIFT;
319331
val &= 0x3;
320332

@@ -334,9 +346,7 @@ static void imx6ul_opp_check_speed_grading(struct device *dev)
334346
dev_warn(dev, "failed to disable 900MHz OPP\n");
335347
}
336348

337-
iounmap(base);
338-
put_node:
339-
of_node_put(np);
349+
return ret;
340350
}
341351

342352
static int imx6q_cpufreq_probe(struct platform_device *pdev)
@@ -394,10 +404,18 @@ static int imx6q_cpufreq_probe(struct platform_device *pdev)
394404
}
395405

396406
if (of_machine_is_compatible("fsl,imx6ul") ||
397-
of_machine_is_compatible("fsl,imx6ull"))
398-
imx6ul_opp_check_speed_grading(cpu_dev);
399-
else
407+
of_machine_is_compatible("fsl,imx6ull")) {
408+
ret = imx6ul_opp_check_speed_grading(cpu_dev);
409+
if (ret == -EPROBE_DEFER)
410+
return ret;
411+
if (ret) {
412+
dev_err(cpu_dev, "failed to read ocotp: %d\n",
413+
ret);
414+
return ret;
415+
}
416+
} else {
400417
imx6q_opp_check_speed_grading(cpu_dev);
418+
}
401419

402420
/* Because we have added the OPPs here, we must free them */
403421
free_opp = true;

0 commit comments

Comments
 (0)