0001
0002
0003
0004
0005
0006 #include <linux/clk.h>
0007 #include <linux/cpu.h>
0008 #include <linux/cpufreq.h>
0009 #include <linux/err.h>
0010 #include <linux/module.h>
0011 #include <linux/nvmem-consumer.h>
0012 #include <linux/of.h>
0013 #include <linux/of_address.h>
0014 #include <linux/pm_opp.h>
0015 #include <linux/platform_device.h>
0016 #include <linux/regulator/consumer.h>
0017
0018 #define PU_SOC_VOLTAGE_NORMAL 1250000
0019 #define PU_SOC_VOLTAGE_HIGH 1275000
0020 #define FREQ_1P2_GHZ 1200000000
0021
0022 static struct regulator *arm_reg;
0023 static struct regulator *pu_reg;
0024 static struct regulator *soc_reg;
0025
0026 enum IMX6_CPUFREQ_CLKS {
0027 ARM,
0028 PLL1_SYS,
0029 STEP,
0030 PLL1_SW,
0031 PLL2_PFD2_396M,
0032
0033 PLL2_BUS,
0034 SECONDARY_SEL,
0035 };
0036 #define IMX6Q_CPUFREQ_CLK_NUM 5
0037 #define IMX6UL_CPUFREQ_CLK_NUM 7
0038
0039 static int num_clks;
0040 static struct clk_bulk_data clks[] = {
0041 { .id = "arm" },
0042 { .id = "pll1_sys" },
0043 { .id = "step" },
0044 { .id = "pll1_sw" },
0045 { .id = "pll2_pfd2_396m" },
0046 { .id = "pll2_bus" },
0047 { .id = "secondary_sel" },
0048 };
0049
0050 static struct device *cpu_dev;
0051 static struct cpufreq_frequency_table *freq_table;
0052 static unsigned int max_freq;
0053 static unsigned int transition_latency;
0054
0055 static u32 *imx6_soc_volt;
0056 static u32 soc_opp_count;
0057
0058 static int imx6q_set_target(struct cpufreq_policy *policy, unsigned int index)
0059 {
0060 struct dev_pm_opp *opp;
0061 unsigned long freq_hz, volt, volt_old;
0062 unsigned int old_freq, new_freq;
0063 bool pll1_sys_temp_enabled = false;
0064 int ret;
0065
0066 new_freq = freq_table[index].frequency;
0067 freq_hz = new_freq * 1000;
0068 old_freq = clk_get_rate(clks[ARM].clk) / 1000;
0069
0070 opp = dev_pm_opp_find_freq_ceil(cpu_dev, &freq_hz);
0071 if (IS_ERR(opp)) {
0072 dev_err(cpu_dev, "failed to find OPP for %ld\n", freq_hz);
0073 return PTR_ERR(opp);
0074 }
0075
0076 volt = dev_pm_opp_get_voltage(opp);
0077 dev_pm_opp_put(opp);
0078
0079 volt_old = regulator_get_voltage(arm_reg);
0080
0081 dev_dbg(cpu_dev, "%u MHz, %ld mV --> %u MHz, %ld mV\n",
0082 old_freq / 1000, volt_old / 1000,
0083 new_freq / 1000, volt / 1000);
0084
0085
0086 if (new_freq > old_freq) {
0087 if (!IS_ERR(pu_reg)) {
0088 ret = regulator_set_voltage_tol(pu_reg, imx6_soc_volt[index], 0);
0089 if (ret) {
0090 dev_err(cpu_dev, "failed to scale vddpu up: %d\n", ret);
0091 return ret;
0092 }
0093 }
0094 ret = regulator_set_voltage_tol(soc_reg, imx6_soc_volt[index], 0);
0095 if (ret) {
0096 dev_err(cpu_dev, "failed to scale vddsoc up: %d\n", ret);
0097 return ret;
0098 }
0099 ret = regulator_set_voltage_tol(arm_reg, volt, 0);
0100 if (ret) {
0101 dev_err(cpu_dev,
0102 "failed to scale vddarm up: %d\n", ret);
0103 return ret;
0104 }
0105 }
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118 if (of_machine_is_compatible("fsl,imx6ul") ||
0119 of_machine_is_compatible("fsl,imx6ull")) {
0120
0121
0122
0123
0124
0125
0126
0127 clk_set_rate(clks[ARM].clk, (old_freq >> 1) * 1000);
0128 clk_set_parent(clks[PLL1_SW].clk, clks[PLL1_SYS].clk);
0129 if (freq_hz > clk_get_rate(clks[PLL2_PFD2_396M].clk))
0130 clk_set_parent(clks[SECONDARY_SEL].clk,
0131 clks[PLL2_BUS].clk);
0132 else
0133 clk_set_parent(clks[SECONDARY_SEL].clk,
0134 clks[PLL2_PFD2_396M].clk);
0135 clk_set_parent(clks[STEP].clk, clks[SECONDARY_SEL].clk);
0136 clk_set_parent(clks[PLL1_SW].clk, clks[STEP].clk);
0137 if (freq_hz > clk_get_rate(clks[PLL2_BUS].clk)) {
0138 clk_set_rate(clks[PLL1_SYS].clk, new_freq * 1000);
0139 clk_set_parent(clks[PLL1_SW].clk, clks[PLL1_SYS].clk);
0140 }
0141 } else {
0142 clk_set_parent(clks[STEP].clk, clks[PLL2_PFD2_396M].clk);
0143 clk_set_parent(clks[PLL1_SW].clk, clks[STEP].clk);
0144 if (freq_hz > clk_get_rate(clks[PLL2_PFD2_396M].clk)) {
0145 clk_set_rate(clks[PLL1_SYS].clk, new_freq * 1000);
0146 clk_set_parent(clks[PLL1_SW].clk, clks[PLL1_SYS].clk);
0147 } else {
0148
0149 pll1_sys_temp_enabled = true;
0150 clk_prepare_enable(clks[PLL1_SYS].clk);
0151 }
0152 }
0153
0154
0155 ret = clk_set_rate(clks[ARM].clk, new_freq * 1000);
0156 if (ret) {
0157 int ret1;
0158
0159 dev_err(cpu_dev, "failed to set clock rate: %d\n", ret);
0160 ret1 = regulator_set_voltage_tol(arm_reg, volt_old, 0);
0161 if (ret1)
0162 dev_warn(cpu_dev,
0163 "failed to restore vddarm voltage: %d\n", ret1);
0164 return ret;
0165 }
0166
0167
0168 if (pll1_sys_temp_enabled)
0169 clk_disable_unprepare(clks[PLL1_SYS].clk);
0170
0171
0172 if (new_freq < old_freq) {
0173 ret = regulator_set_voltage_tol(arm_reg, volt, 0);
0174 if (ret)
0175 dev_warn(cpu_dev,
0176 "failed to scale vddarm down: %d\n", ret);
0177 ret = regulator_set_voltage_tol(soc_reg, imx6_soc_volt[index], 0);
0178 if (ret)
0179 dev_warn(cpu_dev, "failed to scale vddsoc down: %d\n", ret);
0180 if (!IS_ERR(pu_reg)) {
0181 ret = regulator_set_voltage_tol(pu_reg, imx6_soc_volt[index], 0);
0182 if (ret)
0183 dev_warn(cpu_dev, "failed to scale vddpu down: %d\n", ret);
0184 }
0185 }
0186
0187 return 0;
0188 }
0189
0190 static int imx6q_cpufreq_init(struct cpufreq_policy *policy)
0191 {
0192 policy->clk = clks[ARM].clk;
0193 cpufreq_generic_init(policy, freq_table, transition_latency);
0194 policy->suspend_freq = max_freq;
0195
0196 return 0;
0197 }
0198
0199 static struct cpufreq_driver imx6q_cpufreq_driver = {
0200 .flags = CPUFREQ_NEED_INITIAL_FREQ_CHECK |
0201 CPUFREQ_IS_COOLING_DEV,
0202 .verify = cpufreq_generic_frequency_table_verify,
0203 .target_index = imx6q_set_target,
0204 .get = cpufreq_generic_get,
0205 .init = imx6q_cpufreq_init,
0206 .register_em = cpufreq_register_em_with_opp,
0207 .name = "imx6q-cpufreq",
0208 .attr = cpufreq_generic_attr,
0209 .suspend = cpufreq_generic_suspend,
0210 };
0211
0212 #define OCOTP_CFG3 0x440
0213 #define OCOTP_CFG3_SPEED_SHIFT 16
0214 #define OCOTP_CFG3_SPEED_1P2GHZ 0x3
0215 #define OCOTP_CFG3_SPEED_996MHZ 0x2
0216 #define OCOTP_CFG3_SPEED_852MHZ 0x1
0217
0218 static int imx6q_opp_check_speed_grading(struct device *dev)
0219 {
0220 struct device_node *np;
0221 void __iomem *base;
0222 u32 val;
0223 int ret;
0224
0225 if (of_find_property(dev->of_node, "nvmem-cells", NULL)) {
0226 ret = nvmem_cell_read_u32(dev, "speed_grade", &val);
0227 if (ret)
0228 return ret;
0229 } else {
0230 np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-ocotp");
0231 if (!np)
0232 return -ENOENT;
0233
0234 base = of_iomap(np, 0);
0235 of_node_put(np);
0236 if (!base) {
0237 dev_err(dev, "failed to map ocotp\n");
0238 return -EFAULT;
0239 }
0240
0241
0242
0243
0244
0245
0246
0247
0248
0249 val = readl_relaxed(base + OCOTP_CFG3);
0250 iounmap(base);
0251 }
0252
0253 val >>= OCOTP_CFG3_SPEED_SHIFT;
0254 val &= 0x3;
0255
0256 if (val < OCOTP_CFG3_SPEED_996MHZ)
0257 if (dev_pm_opp_disable(dev, 996000000))
0258 dev_warn(dev, "failed to disable 996MHz OPP\n");
0259
0260 if (of_machine_is_compatible("fsl,imx6q") ||
0261 of_machine_is_compatible("fsl,imx6qp")) {
0262 if (val != OCOTP_CFG3_SPEED_852MHZ)
0263 if (dev_pm_opp_disable(dev, 852000000))
0264 dev_warn(dev, "failed to disable 852MHz OPP\n");
0265 if (val != OCOTP_CFG3_SPEED_1P2GHZ)
0266 if (dev_pm_opp_disable(dev, 1200000000))
0267 dev_warn(dev, "failed to disable 1.2GHz OPP\n");
0268 }
0269
0270 return 0;
0271 }
0272
0273 #define OCOTP_CFG3_6UL_SPEED_696MHZ 0x2
0274 #define OCOTP_CFG3_6ULL_SPEED_792MHZ 0x2
0275 #define OCOTP_CFG3_6ULL_SPEED_900MHZ 0x3
0276
0277 static int imx6ul_opp_check_speed_grading(struct device *dev)
0278 {
0279 u32 val;
0280 int ret = 0;
0281
0282 if (of_find_property(dev->of_node, "nvmem-cells", NULL)) {
0283 ret = nvmem_cell_read_u32(dev, "speed_grade", &val);
0284 if (ret)
0285 return ret;
0286 } else {
0287 struct device_node *np;
0288 void __iomem *base;
0289
0290 np = of_find_compatible_node(NULL, NULL, "fsl,imx6ul-ocotp");
0291 if (!np)
0292 np = of_find_compatible_node(NULL, NULL,
0293 "fsl,imx6ull-ocotp");
0294 if (!np)
0295 return -ENOENT;
0296
0297 base = of_iomap(np, 0);
0298 of_node_put(np);
0299 if (!base) {
0300 dev_err(dev, "failed to map ocotp\n");
0301 return -EFAULT;
0302 }
0303
0304 val = readl_relaxed(base + OCOTP_CFG3);
0305 iounmap(base);
0306 }
0307
0308
0309
0310
0311
0312
0313
0314
0315
0316 val >>= OCOTP_CFG3_SPEED_SHIFT;
0317 val &= 0x3;
0318
0319 if (of_machine_is_compatible("fsl,imx6ul")) {
0320 if (val != OCOTP_CFG3_6UL_SPEED_696MHZ)
0321 if (dev_pm_opp_disable(dev, 696000000))
0322 dev_warn(dev, "failed to disable 696MHz OPP\n");
0323 }
0324
0325 if (of_machine_is_compatible("fsl,imx6ull")) {
0326 if (val != OCOTP_CFG3_6ULL_SPEED_792MHZ)
0327 if (dev_pm_opp_disable(dev, 792000000))
0328 dev_warn(dev, "failed to disable 792MHz OPP\n");
0329
0330 if (val != OCOTP_CFG3_6ULL_SPEED_900MHZ)
0331 if (dev_pm_opp_disable(dev, 900000000))
0332 dev_warn(dev, "failed to disable 900MHz OPP\n");
0333 }
0334
0335 return ret;
0336 }
0337
0338 static int imx6q_cpufreq_probe(struct platform_device *pdev)
0339 {
0340 struct device_node *np;
0341 struct dev_pm_opp *opp;
0342 unsigned long min_volt, max_volt;
0343 int num, ret;
0344 const struct property *prop;
0345 const __be32 *val;
0346 u32 nr, i, j;
0347
0348 cpu_dev = get_cpu_device(0);
0349 if (!cpu_dev) {
0350 pr_err("failed to get cpu0 device\n");
0351 return -ENODEV;
0352 }
0353
0354 np = of_node_get(cpu_dev->of_node);
0355 if (!np) {
0356 dev_err(cpu_dev, "failed to find cpu0 node\n");
0357 return -ENOENT;
0358 }
0359
0360 if (of_machine_is_compatible("fsl,imx6ul") ||
0361 of_machine_is_compatible("fsl,imx6ull"))
0362 num_clks = IMX6UL_CPUFREQ_CLK_NUM;
0363 else
0364 num_clks = IMX6Q_CPUFREQ_CLK_NUM;
0365
0366 ret = clk_bulk_get(cpu_dev, num_clks, clks);
0367 if (ret)
0368 goto put_node;
0369
0370 arm_reg = regulator_get(cpu_dev, "arm");
0371 pu_reg = regulator_get_optional(cpu_dev, "pu");
0372 soc_reg = regulator_get(cpu_dev, "soc");
0373 if (PTR_ERR(arm_reg) == -EPROBE_DEFER ||
0374 PTR_ERR(soc_reg) == -EPROBE_DEFER ||
0375 PTR_ERR(pu_reg) == -EPROBE_DEFER) {
0376 ret = -EPROBE_DEFER;
0377 dev_dbg(cpu_dev, "regulators not ready, defer\n");
0378 goto put_reg;
0379 }
0380 if (IS_ERR(arm_reg) || IS_ERR(soc_reg)) {
0381 dev_err(cpu_dev, "failed to get regulators\n");
0382 ret = -ENOENT;
0383 goto put_reg;
0384 }
0385
0386 ret = dev_pm_opp_of_add_table(cpu_dev);
0387 if (ret < 0) {
0388 dev_err(cpu_dev, "failed to init OPP table: %d\n", ret);
0389 goto put_reg;
0390 }
0391
0392 if (of_machine_is_compatible("fsl,imx6ul") ||
0393 of_machine_is_compatible("fsl,imx6ull")) {
0394 ret = imx6ul_opp_check_speed_grading(cpu_dev);
0395 } else {
0396 ret = imx6q_opp_check_speed_grading(cpu_dev);
0397 }
0398 if (ret) {
0399 if (ret != -EPROBE_DEFER)
0400 dev_err(cpu_dev, "failed to read ocotp: %d\n",
0401 ret);
0402 goto out_free_opp;
0403 }
0404
0405 num = dev_pm_opp_get_opp_count(cpu_dev);
0406 if (num < 0) {
0407 ret = num;
0408 dev_err(cpu_dev, "no OPP table is found: %d\n", ret);
0409 goto out_free_opp;
0410 }
0411
0412 ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table);
0413 if (ret) {
0414 dev_err(cpu_dev, "failed to init cpufreq table: %d\n", ret);
0415 goto out_free_opp;
0416 }
0417
0418
0419 imx6_soc_volt = devm_kcalloc(cpu_dev, num, sizeof(*imx6_soc_volt),
0420 GFP_KERNEL);
0421 if (imx6_soc_volt == NULL) {
0422 ret = -ENOMEM;
0423 goto free_freq_table;
0424 }
0425
0426 prop = of_find_property(np, "fsl,soc-operating-points", NULL);
0427 if (!prop || !prop->value)
0428 goto soc_opp_out;
0429
0430
0431
0432
0433
0434 nr = prop->length / sizeof(u32);
0435 if (nr % 2 || (nr / 2) < num)
0436 goto soc_opp_out;
0437
0438 for (j = 0; j < num; j++) {
0439 val = prop->value;
0440 for (i = 0; i < nr / 2; i++) {
0441 unsigned long freq = be32_to_cpup(val++);
0442 unsigned long volt = be32_to_cpup(val++);
0443 if (freq_table[j].frequency == freq) {
0444 imx6_soc_volt[soc_opp_count++] = volt;
0445 break;
0446 }
0447 }
0448 }
0449
0450 soc_opp_out:
0451
0452 if (soc_opp_count != num) {
0453 dev_warn(cpu_dev, "can NOT find valid fsl,soc-operating-points property in dtb, use default value!\n");
0454 for (j = 0; j < num; j++)
0455 imx6_soc_volt[j] = PU_SOC_VOLTAGE_NORMAL;
0456 if (freq_table[num - 1].frequency * 1000 == FREQ_1P2_GHZ)
0457 imx6_soc_volt[num - 1] = PU_SOC_VOLTAGE_HIGH;
0458 }
0459
0460 if (of_property_read_u32(np, "clock-latency", &transition_latency))
0461 transition_latency = CPUFREQ_ETERNAL;
0462
0463
0464
0465
0466
0467 ret = regulator_set_voltage_time(soc_reg, imx6_soc_volt[0], imx6_soc_volt[num - 1]);
0468 if (ret > 0)
0469 transition_latency += ret * 1000;
0470 if (!IS_ERR(pu_reg)) {
0471 ret = regulator_set_voltage_time(pu_reg, imx6_soc_volt[0], imx6_soc_volt[num - 1]);
0472 if (ret > 0)
0473 transition_latency += ret * 1000;
0474 }
0475
0476
0477
0478
0479
0480
0481 max_freq = freq_table[--num].frequency;
0482 opp = dev_pm_opp_find_freq_exact(cpu_dev,
0483 freq_table[0].frequency * 1000, true);
0484 min_volt = dev_pm_opp_get_voltage(opp);
0485 dev_pm_opp_put(opp);
0486 opp = dev_pm_opp_find_freq_exact(cpu_dev, max_freq * 1000, true);
0487 max_volt = dev_pm_opp_get_voltage(opp);
0488 dev_pm_opp_put(opp);
0489
0490 ret = regulator_set_voltage_time(arm_reg, min_volt, max_volt);
0491 if (ret > 0)
0492 transition_latency += ret * 1000;
0493
0494 ret = cpufreq_register_driver(&imx6q_cpufreq_driver);
0495 if (ret) {
0496 dev_err(cpu_dev, "failed register driver: %d\n", ret);
0497 goto free_freq_table;
0498 }
0499
0500 of_node_put(np);
0501 return 0;
0502
0503 free_freq_table:
0504 dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table);
0505 out_free_opp:
0506 dev_pm_opp_of_remove_table(cpu_dev);
0507 put_reg:
0508 if (!IS_ERR(arm_reg))
0509 regulator_put(arm_reg);
0510 if (!IS_ERR(pu_reg))
0511 regulator_put(pu_reg);
0512 if (!IS_ERR(soc_reg))
0513 regulator_put(soc_reg);
0514
0515 clk_bulk_put(num_clks, clks);
0516 put_node:
0517 of_node_put(np);
0518
0519 return ret;
0520 }
0521
0522 static int imx6q_cpufreq_remove(struct platform_device *pdev)
0523 {
0524 cpufreq_unregister_driver(&imx6q_cpufreq_driver);
0525 dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table);
0526 dev_pm_opp_of_remove_table(cpu_dev);
0527 regulator_put(arm_reg);
0528 if (!IS_ERR(pu_reg))
0529 regulator_put(pu_reg);
0530 regulator_put(soc_reg);
0531
0532 clk_bulk_put(num_clks, clks);
0533
0534 return 0;
0535 }
0536
0537 static struct platform_driver imx6q_cpufreq_platdrv = {
0538 .driver = {
0539 .name = "imx6q-cpufreq",
0540 },
0541 .probe = imx6q_cpufreq_probe,
0542 .remove = imx6q_cpufreq_remove,
0543 };
0544 module_platform_driver(imx6q_cpufreq_platdrv);
0545
0546 MODULE_ALIAS("platform:imx6q-cpufreq");
0547 MODULE_AUTHOR("Shawn Guo <shawn.guo@linaro.org>");
0548 MODULE_DESCRIPTION("Freescale i.MX6Q cpufreq driver");
0549 MODULE_LICENSE("GPL");