1 /* 2 * Copyright (C) 2013 Freescale Semiconductor, Inc. 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License version 2 as 6 * published by the Free Software Foundation. 7 */ 8 9 #include <linux/clk.h> 10 #include <linux/cpu.h> 11 #include <linux/cpufreq.h> 12 #include <linux/err.h> 13 #include <linux/module.h> 14 #include <linux/of.h> 15 #include <linux/pm_opp.h> 16 #include <linux/platform_device.h> 17 #include <linux/regulator/consumer.h> 18 19 #define PU_SOC_VOLTAGE_NORMAL 1250000 20 #define PU_SOC_VOLTAGE_HIGH 1275000 21 #define FREQ_1P2_GHZ 1200000000 22 23 static struct regulator *arm_reg; 24 static struct regulator *pu_reg; 25 static struct regulator *soc_reg; 26 27 static struct clk *arm_clk; 28 static struct clk *pll1_sys_clk; 29 static struct clk *pll1_sw_clk; 30 static struct clk *step_clk; 31 static struct clk *pll2_pfd2_396m_clk; 32 33 static struct device *cpu_dev; 34 static struct cpufreq_frequency_table *freq_table; 35 static unsigned int transition_latency; 36 37 static u32 *imx6_soc_volt; 38 static u32 soc_opp_count; 39 40 static int imx6q_set_target(struct cpufreq_policy *policy, unsigned int index) 41 { 42 struct dev_pm_opp *opp; 43 unsigned long freq_hz, volt, volt_old; 44 unsigned int old_freq, new_freq; 45 int ret; 46 47 new_freq = freq_table[index].frequency; 48 freq_hz = new_freq * 1000; 49 old_freq = clk_get_rate(arm_clk) / 1000; 50 51 rcu_read_lock(); 52 opp = dev_pm_opp_find_freq_ceil(cpu_dev, &freq_hz); 53 if (IS_ERR(opp)) { 54 rcu_read_unlock(); 55 dev_err(cpu_dev, "failed to find OPP for %ld\n", freq_hz); 56 return PTR_ERR(opp); 57 } 58 59 volt = dev_pm_opp_get_voltage(opp); 60 rcu_read_unlock(); 61 volt_old = regulator_get_voltage(arm_reg); 62 63 dev_dbg(cpu_dev, "%u MHz, %ld mV --> %u MHz, %ld mV\n", 64 old_freq / 1000, volt_old / 1000, 65 new_freq / 1000, volt / 1000); 66 67 /* scaling up? scale voltage before frequency */ 68 if (new_freq > old_freq) { 69 if (!IS_ERR(pu_reg)) { 70 ret = regulator_set_voltage_tol(pu_reg, imx6_soc_volt[index], 0); 71 if (ret) { 72 dev_err(cpu_dev, "failed to scale vddpu up: %d\n", ret); 73 return ret; 74 } 75 } 76 ret = regulator_set_voltage_tol(soc_reg, imx6_soc_volt[index], 0); 77 if (ret) { 78 dev_err(cpu_dev, "failed to scale vddsoc up: %d\n", ret); 79 return ret; 80 } 81 ret = regulator_set_voltage_tol(arm_reg, volt, 0); 82 if (ret) { 83 dev_err(cpu_dev, 84 "failed to scale vddarm up: %d\n", ret); 85 return ret; 86 } 87 } 88 89 /* 90 * The setpoints are selected per PLL/PDF frequencies, so we need to 91 * reprogram PLL for frequency scaling. The procedure of reprogramming 92 * PLL1 is as below. 93 * 94 * - Enable pll2_pfd2_396m_clk and reparent pll1_sw_clk to it 95 * - Reprogram pll1_sys_clk and reparent pll1_sw_clk back to it 96 * - Disable pll2_pfd2_396m_clk 97 */ 98 clk_set_parent(step_clk, pll2_pfd2_396m_clk); 99 clk_set_parent(pll1_sw_clk, step_clk); 100 if (freq_hz > clk_get_rate(pll2_pfd2_396m_clk)) { 101 clk_set_rate(pll1_sys_clk, new_freq * 1000); 102 clk_set_parent(pll1_sw_clk, pll1_sys_clk); 103 } 104 105 /* Ensure the arm clock divider is what we expect */ 106 ret = clk_set_rate(arm_clk, new_freq * 1000); 107 if (ret) { 108 dev_err(cpu_dev, "failed to set clock rate: %d\n", ret); 109 regulator_set_voltage_tol(arm_reg, volt_old, 0); 110 return ret; 111 } 112 113 /* scaling down? scale voltage after frequency */ 114 if (new_freq < old_freq) { 115 ret = regulator_set_voltage_tol(arm_reg, volt, 0); 116 if (ret) { 117 dev_warn(cpu_dev, 118 "failed to scale vddarm down: %d\n", ret); 119 ret = 0; 120 } 121 ret = regulator_set_voltage_tol(soc_reg, imx6_soc_volt[index], 0); 122 if (ret) { 123 dev_warn(cpu_dev, "failed to scale vddsoc down: %d\n", ret); 124 ret = 0; 125 } 126 if (!IS_ERR(pu_reg)) { 127 ret = regulator_set_voltage_tol(pu_reg, imx6_soc_volt[index], 0); 128 if (ret) { 129 dev_warn(cpu_dev, "failed to scale vddpu down: %d\n", ret); 130 ret = 0; 131 } 132 } 133 } 134 135 return 0; 136 } 137 138 static int imx6q_cpufreq_init(struct cpufreq_policy *policy) 139 { 140 policy->clk = arm_clk; 141 return cpufreq_generic_init(policy, freq_table, transition_latency); 142 } 143 144 static struct cpufreq_driver imx6q_cpufreq_driver = { 145 .flags = CPUFREQ_NEED_INITIAL_FREQ_CHECK, 146 .verify = cpufreq_generic_frequency_table_verify, 147 .target_index = imx6q_set_target, 148 .get = cpufreq_generic_get, 149 .init = imx6q_cpufreq_init, 150 .name = "imx6q-cpufreq", 151 .attr = cpufreq_generic_attr, 152 }; 153 154 static int imx6q_cpufreq_probe(struct platform_device *pdev) 155 { 156 struct device_node *np; 157 struct dev_pm_opp *opp; 158 unsigned long min_volt, max_volt; 159 int num, ret; 160 const struct property *prop; 161 const __be32 *val; 162 u32 nr, i, j; 163 164 cpu_dev = get_cpu_device(0); 165 if (!cpu_dev) { 166 pr_err("failed to get cpu0 device\n"); 167 return -ENODEV; 168 } 169 170 np = of_node_get(cpu_dev->of_node); 171 if (!np) { 172 dev_err(cpu_dev, "failed to find cpu0 node\n"); 173 return -ENOENT; 174 } 175 176 arm_clk = clk_get(cpu_dev, "arm"); 177 pll1_sys_clk = clk_get(cpu_dev, "pll1_sys"); 178 pll1_sw_clk = clk_get(cpu_dev, "pll1_sw"); 179 step_clk = clk_get(cpu_dev, "step"); 180 pll2_pfd2_396m_clk = clk_get(cpu_dev, "pll2_pfd2_396m"); 181 if (IS_ERR(arm_clk) || IS_ERR(pll1_sys_clk) || IS_ERR(pll1_sw_clk) || 182 IS_ERR(step_clk) || IS_ERR(pll2_pfd2_396m_clk)) { 183 dev_err(cpu_dev, "failed to get clocks\n"); 184 ret = -ENOENT; 185 goto put_clk; 186 } 187 188 arm_reg = regulator_get(cpu_dev, "arm"); 189 pu_reg = regulator_get_optional(cpu_dev, "pu"); 190 soc_reg = regulator_get(cpu_dev, "soc"); 191 if (IS_ERR(arm_reg) || IS_ERR(soc_reg)) { 192 dev_err(cpu_dev, "failed to get regulators\n"); 193 ret = -ENOENT; 194 goto put_reg; 195 } 196 197 /* 198 * We expect an OPP table supplied by platform. 199 * Just, incase the platform did not supply the OPP 200 * table, it will try to get it. 201 */ 202 num = dev_pm_opp_get_opp_count(cpu_dev); 203 if (num < 0) { 204 ret = of_init_opp_table(cpu_dev); 205 if (ret < 0) { 206 dev_err(cpu_dev, "failed to init OPP table: %d\n", ret); 207 goto put_reg; 208 } 209 210 num = dev_pm_opp_get_opp_count(cpu_dev); 211 if (num < 0) { 212 ret = num; 213 dev_err(cpu_dev, "no OPP table is found: %d\n", ret); 214 goto put_reg; 215 } 216 } 217 218 ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table); 219 if (ret) { 220 dev_err(cpu_dev, "failed to init cpufreq table: %d\n", ret); 221 goto put_reg; 222 } 223 224 /* Make imx6_soc_volt array's size same as arm opp number */ 225 imx6_soc_volt = devm_kzalloc(cpu_dev, sizeof(*imx6_soc_volt) * num, GFP_KERNEL); 226 if (imx6_soc_volt == NULL) { 227 ret = -ENOMEM; 228 goto free_freq_table; 229 } 230 231 prop = of_find_property(np, "fsl,soc-operating-points", NULL); 232 if (!prop || !prop->value) 233 goto soc_opp_out; 234 235 /* 236 * Each OPP is a set of tuples consisting of frequency and 237 * voltage like <freq-kHz vol-uV>. 238 */ 239 nr = prop->length / sizeof(u32); 240 if (nr % 2 || (nr / 2) < num) 241 goto soc_opp_out; 242 243 for (j = 0; j < num; j++) { 244 val = prop->value; 245 for (i = 0; i < nr / 2; i++) { 246 unsigned long freq = be32_to_cpup(val++); 247 unsigned long volt = be32_to_cpup(val++); 248 if (freq_table[j].frequency == freq) { 249 imx6_soc_volt[soc_opp_count++] = volt; 250 break; 251 } 252 } 253 } 254 255 soc_opp_out: 256 /* use fixed soc opp volt if no valid soc opp info found in dtb */ 257 if (soc_opp_count != num) { 258 dev_warn(cpu_dev, "can NOT find valid fsl,soc-operating-points property in dtb, use default value!\n"); 259 for (j = 0; j < num; j++) 260 imx6_soc_volt[j] = PU_SOC_VOLTAGE_NORMAL; 261 if (freq_table[num - 1].frequency * 1000 == FREQ_1P2_GHZ) 262 imx6_soc_volt[num - 1] = PU_SOC_VOLTAGE_HIGH; 263 } 264 265 if (of_property_read_u32(np, "clock-latency", &transition_latency)) 266 transition_latency = CPUFREQ_ETERNAL; 267 268 /* 269 * Calculate the ramp time for max voltage change in the 270 * VDDSOC and VDDPU regulators. 271 */ 272 ret = regulator_set_voltage_time(soc_reg, imx6_soc_volt[0], imx6_soc_volt[num - 1]); 273 if (ret > 0) 274 transition_latency += ret * 1000; 275 if (!IS_ERR(pu_reg)) { 276 ret = regulator_set_voltage_time(pu_reg, imx6_soc_volt[0], imx6_soc_volt[num - 1]); 277 if (ret > 0) 278 transition_latency += ret * 1000; 279 } 280 281 /* 282 * OPP is maintained in order of increasing frequency, and 283 * freq_table initialised from OPP is therefore sorted in the 284 * same order. 285 */ 286 rcu_read_lock(); 287 opp = dev_pm_opp_find_freq_exact(cpu_dev, 288 freq_table[0].frequency * 1000, true); 289 min_volt = dev_pm_opp_get_voltage(opp); 290 opp = dev_pm_opp_find_freq_exact(cpu_dev, 291 freq_table[--num].frequency * 1000, true); 292 max_volt = dev_pm_opp_get_voltage(opp); 293 rcu_read_unlock(); 294 ret = regulator_set_voltage_time(arm_reg, min_volt, max_volt); 295 if (ret > 0) 296 transition_latency += ret * 1000; 297 298 ret = cpufreq_register_driver(&imx6q_cpufreq_driver); 299 if (ret) { 300 dev_err(cpu_dev, "failed register driver: %d\n", ret); 301 goto free_freq_table; 302 } 303 304 of_node_put(np); 305 return 0; 306 307 free_freq_table: 308 dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table); 309 put_reg: 310 if (!IS_ERR(arm_reg)) 311 regulator_put(arm_reg); 312 if (!IS_ERR(pu_reg)) 313 regulator_put(pu_reg); 314 if (!IS_ERR(soc_reg)) 315 regulator_put(soc_reg); 316 put_clk: 317 if (!IS_ERR(arm_clk)) 318 clk_put(arm_clk); 319 if (!IS_ERR(pll1_sys_clk)) 320 clk_put(pll1_sys_clk); 321 if (!IS_ERR(pll1_sw_clk)) 322 clk_put(pll1_sw_clk); 323 if (!IS_ERR(step_clk)) 324 clk_put(step_clk); 325 if (!IS_ERR(pll2_pfd2_396m_clk)) 326 clk_put(pll2_pfd2_396m_clk); 327 of_node_put(np); 328 return ret; 329 } 330 331 static int imx6q_cpufreq_remove(struct platform_device *pdev) 332 { 333 cpufreq_unregister_driver(&imx6q_cpufreq_driver); 334 dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table); 335 regulator_put(arm_reg); 336 if (!IS_ERR(pu_reg)) 337 regulator_put(pu_reg); 338 regulator_put(soc_reg); 339 clk_put(arm_clk); 340 clk_put(pll1_sys_clk); 341 clk_put(pll1_sw_clk); 342 clk_put(step_clk); 343 clk_put(pll2_pfd2_396m_clk); 344 345 return 0; 346 } 347 348 static struct platform_driver imx6q_cpufreq_platdrv = { 349 .driver = { 350 .name = "imx6q-cpufreq", 351 .owner = THIS_MODULE, 352 }, 353 .probe = imx6q_cpufreq_probe, 354 .remove = imx6q_cpufreq_remove, 355 }; 356 module_platform_driver(imx6q_cpufreq_platdrv); 357 358 MODULE_AUTHOR("Shawn Guo <shawn.guo@linaro.org>"); 359 MODULE_DESCRIPTION("Freescale i.MX6Q cpufreq driver"); 360 MODULE_LICENSE("GPL"); 361