Skip to content

Commit 7c2553f

Browse files
MrVanvireshk
authored andcommitted
cpufreq: imx-cpufreq-dt: support i.MX7ULP
i.MX7ULP's ARM core clock design is totally different compared with i.MX7D/8M SoCs which supported by imx-cpufreq-dt. It needs get_intermediate and target_intermedate to configure clk MUX ready, before let OPP configure ARM core clk. |---FIRC |------RUN---...---SCS(MUX2) --------| ARM --(MUX1) |---SPLL_PFD0(CLK_SET_RATE_GATE) |------HSRUN--...--HSRUN_SCS(MUX3)---| |---SRIC FIRC is step clk, SPLL_PFD0 is the normal clk driving ARM core. MUX2 and MUX3 share same inputs. So if MUX2/MUX3 both sources from SPLL_PFD0, both MUXes will lose input when configure SPLL_PFD0. So the target_intermediate will configure MUX2/MUX3 to FIRC, to avoid ARM core lose clk when configure SPLL_PFD0. Signed-off-by: Peng Fan <[email protected]> Signed-off-by: Viresh Kumar <[email protected]>
1 parent a6d1bfa commit 7c2553f

File tree

1 file changed

+82
-2
lines changed

1 file changed

+82
-2
lines changed

drivers/cpufreq/imx-cpufreq-dt.c

Lines changed: 82 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33
* Copyright 2019 NXP
44
*/
55

6+
#include <linux/clk.h>
67
#include <linux/cpu.h>
8+
#include <linux/cpufreq.h>
79
#include <linux/err.h>
810
#include <linux/init.h>
911
#include <linux/kernel.h>
@@ -12,8 +14,11 @@
1214
#include <linux/of.h>
1315
#include <linux/platform_device.h>
1416
#include <linux/pm_opp.h>
17+
#include <linux/regulator/consumer.h>
1518
#include <linux/slab.h>
1619

20+
#include "cpufreq-dt.h"
21+
1722
#define OCOTP_CFG3_SPEED_GRADE_SHIFT 8
1823
#define OCOTP_CFG3_SPEED_GRADE_MASK (0x3 << 8)
1924
#define IMX8MN_OCOTP_CFG3_SPEED_GRADE_MASK (0xf << 8)
@@ -22,20 +27,92 @@
2227
#define IMX8MP_OCOTP_CFG3_MKT_SEGMENT_SHIFT 5
2328
#define IMX8MP_OCOTP_CFG3_MKT_SEGMENT_MASK (0x3 << 5)
2429

30+
#define IMX7ULP_MAX_RUN_FREQ 528000
31+
2532
/* cpufreq-dt device registered by imx-cpufreq-dt */
2633
static struct platform_device *cpufreq_dt_pdev;
2734
static struct opp_table *cpufreq_opp_table;
35+
static struct device *cpu_dev;
36+
37+
enum IMX7ULP_CPUFREQ_CLKS {
38+
ARM,
39+
CORE,
40+
SCS_SEL,
41+
HSRUN_CORE,
42+
HSRUN_SCS_SEL,
43+
FIRC,
44+
};
45+
46+
static struct clk_bulk_data imx7ulp_clks[] = {
47+
{ .id = "arm" },
48+
{ .id = "core" },
49+
{ .id = "scs_sel" },
50+
{ .id = "hsrun_core" },
51+
{ .id = "hsrun_scs_sel" },
52+
{ .id = "firc" },
53+
};
54+
55+
static unsigned int imx7ulp_get_intermediate(struct cpufreq_policy *policy,
56+
unsigned int index)
57+
{
58+
return clk_get_rate(imx7ulp_clks[FIRC].clk);
59+
}
60+
61+
static int imx7ulp_target_intermediate(struct cpufreq_policy *policy,
62+
unsigned int index)
63+
{
64+
unsigned int newfreq = policy->freq_table[index].frequency;
65+
66+
clk_set_parent(imx7ulp_clks[SCS_SEL].clk, imx7ulp_clks[FIRC].clk);
67+
clk_set_parent(imx7ulp_clks[HSRUN_SCS_SEL].clk, imx7ulp_clks[FIRC].clk);
68+
69+
if (newfreq > IMX7ULP_MAX_RUN_FREQ)
70+
clk_set_parent(imx7ulp_clks[ARM].clk,
71+
imx7ulp_clks[HSRUN_CORE].clk);
72+
else
73+
clk_set_parent(imx7ulp_clks[ARM].clk, imx7ulp_clks[CORE].clk);
74+
75+
return 0;
76+
}
77+
78+
static struct cpufreq_dt_platform_data imx7ulp_data = {
79+
.target_intermediate = imx7ulp_target_intermediate,
80+
.get_intermediate = imx7ulp_get_intermediate,
81+
};
2882

2983
static int imx_cpufreq_dt_probe(struct platform_device *pdev)
3084
{
31-
struct device *cpu_dev = get_cpu_device(0);
85+
struct platform_device *dt_pdev;
3286
u32 cell_value, supported_hw[2];
3387
int speed_grade, mkt_segment;
3488
int ret;
3589

90+
cpu_dev = get_cpu_device(0);
91+
3692
if (!of_find_property(cpu_dev->of_node, "cpu-supply", NULL))
3793
return -ENODEV;
3894

95+
if (of_machine_is_compatible("fsl,imx7ulp")) {
96+
ret = clk_bulk_get(cpu_dev, ARRAY_SIZE(imx7ulp_clks),
97+
imx7ulp_clks);
98+
if (ret)
99+
return ret;
100+
101+
dt_pdev = platform_device_register_data(NULL, "cpufreq-dt",
102+
-1, &imx7ulp_data,
103+
sizeof(imx7ulp_data));
104+
if (IS_ERR(dt_pdev)) {
105+
clk_bulk_put(ARRAY_SIZE(imx7ulp_clks), imx7ulp_clks);
106+
ret = PTR_ERR(dt_pdev);
107+
dev_err(&pdev->dev, "Failed to register cpufreq-dt: %d\n", ret);
108+
return ret;
109+
}
110+
111+
cpufreq_dt_pdev = dt_pdev;
112+
113+
return 0;
114+
}
115+
39116
ret = nvmem_cell_read_u32(cpu_dev, "speed_grade", &cell_value);
40117
if (ret)
41118
return ret;
@@ -98,7 +175,10 @@ static int imx_cpufreq_dt_probe(struct platform_device *pdev)
98175
static int imx_cpufreq_dt_remove(struct platform_device *pdev)
99176
{
100177
platform_device_unregister(cpufreq_dt_pdev);
101-
dev_pm_opp_put_supported_hw(cpufreq_opp_table);
178+
if (!of_machine_is_compatible("fsl,imx7ulp"))
179+
dev_pm_opp_put_supported_hw(cpufreq_opp_table);
180+
else
181+
clk_bulk_put(ARRAY_SIZE(imx7ulp_clks), imx7ulp_clks);
102182

103183
return 0;
104184
}

0 commit comments

Comments
 (0)