|
3 | 3 | * Copyright 2019 NXP
|
4 | 4 | */
|
5 | 5 |
|
| 6 | +#include <linux/clk.h> |
6 | 7 | #include <linux/cpu.h>
|
| 8 | +#include <linux/cpufreq.h> |
7 | 9 | #include <linux/err.h>
|
8 | 10 | #include <linux/init.h>
|
9 | 11 | #include <linux/kernel.h>
|
|
12 | 14 | #include <linux/of.h>
|
13 | 15 | #include <linux/platform_device.h>
|
14 | 16 | #include <linux/pm_opp.h>
|
| 17 | +#include <linux/regulator/consumer.h> |
15 | 18 | #include <linux/slab.h>
|
16 | 19 |
|
| 20 | +#include "cpufreq-dt.h" |
| 21 | + |
17 | 22 | #define OCOTP_CFG3_SPEED_GRADE_SHIFT 8
|
18 | 23 | #define OCOTP_CFG3_SPEED_GRADE_MASK (0x3 << 8)
|
19 | 24 | #define IMX8MN_OCOTP_CFG3_SPEED_GRADE_MASK (0xf << 8)
|
|
22 | 27 | #define IMX8MP_OCOTP_CFG3_MKT_SEGMENT_SHIFT 5
|
23 | 28 | #define IMX8MP_OCOTP_CFG3_MKT_SEGMENT_MASK (0x3 << 5)
|
24 | 29 |
|
| 30 | +#define IMX7ULP_MAX_RUN_FREQ 528000 |
| 31 | + |
25 | 32 | /* cpufreq-dt device registered by imx-cpufreq-dt */
|
26 | 33 | static struct platform_device *cpufreq_dt_pdev;
|
27 | 34 | 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 | +}; |
28 | 82 |
|
29 | 83 | static int imx_cpufreq_dt_probe(struct platform_device *pdev)
|
30 | 84 | {
|
31 |
| - struct device *cpu_dev = get_cpu_device(0); |
| 85 | + struct platform_device *dt_pdev; |
32 | 86 | u32 cell_value, supported_hw[2];
|
33 | 87 | int speed_grade, mkt_segment;
|
34 | 88 | int ret;
|
35 | 89 |
|
| 90 | + cpu_dev = get_cpu_device(0); |
| 91 | + |
36 | 92 | if (!of_find_property(cpu_dev->of_node, "cpu-supply", NULL))
|
37 | 93 | return -ENODEV;
|
38 | 94 |
|
| 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 | + |
39 | 116 | ret = nvmem_cell_read_u32(cpu_dev, "speed_grade", &cell_value);
|
40 | 117 | if (ret)
|
41 | 118 | return ret;
|
@@ -98,7 +175,10 @@ static int imx_cpufreq_dt_probe(struct platform_device *pdev)
|
98 | 175 | static int imx_cpufreq_dt_remove(struct platform_device *pdev)
|
99 | 176 | {
|
100 | 177 | 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); |
102 | 182 |
|
103 | 183 | return 0;
|
104 | 184 | }
|
|
0 commit comments