aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFabio Estevam <fabio.estevam@nxp.com>2017-09-30 11:16:46 -0400
committerShawn Guo <shawnguo@kernel.org>2017-10-17 22:08:21 -0400
commit8e2b04b019c824186548eadd70243dbb97a1675b (patch)
tree3477e4f642370096f9e8d4f18756705992d9f704
parent6879452a883bc985ef9a8f70eb55e870cfb0bb79 (diff)
cpufreq: imx6q: Move speed grading check to cpufreq driver
On some i.MX6 SoCs (like i.MX6SL, i.MX6SX and i.MX6UL) that do not have speed grading check, opp table will not be created in platform code, so cpufreq driver prints the following error message: cpu cpu0: dev_pm_opp_get_opp_count: OPP table not found (-19) However, this is not really an error in this case because the imx6q-cpufreq driver first calls dev_pm_opp_get_opp_count() and if it fails, it means that platform code does not provide OPP and then dev_pm_opp_of_add_table() will be called. In order to avoid such confusing error message, move the speed grading check from platform code to the imx6q-cpufreq driver. This way the imx6q-cpufreq no longer has to check whether OPP table is supplied by platform code. Tested on a i.MX6Q and i.MX6UL based boards. Signed-off-by: Fabio Estevam <fabio.estevam@nxp.com> Acked-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Shawn Guo <shawnguo@kernel.org>
-rw-r--r--arch/arm/mach-imx/mach-imx6q.c88
-rw-r--r--drivers/cpufreq/imx6q-cpufreq.c85
2 files changed, 67 insertions, 106 deletions
diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c
index 57071135415b..7d80a0ae723c 100644
--- a/arch/arm/mach-imx/mach-imx6q.c
+++ b/arch/arm/mach-imx/mach-imx6q.c
@@ -286,88 +286,6 @@ static void __init imx6q_init_machine(void)
286 imx6q_axi_init(); 286 imx6q_axi_init();
287} 287}
288 288
289#define OCOTP_CFG3 0x440
290#define OCOTP_CFG3_SPEED_SHIFT 16
291#define OCOTP_CFG3_SPEED_1P2GHZ 0x3
292#define OCOTP_CFG3_SPEED_996MHZ 0x2
293#define OCOTP_CFG3_SPEED_852MHZ 0x1
294
295static void __init imx6q_opp_check_speed_grading(struct device *cpu_dev)
296{
297 struct device_node *np;
298 void __iomem *base;
299 u32 val;
300
301 np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-ocotp");
302 if (!np) {
303 pr_warn("failed to find ocotp node\n");
304 return;
305 }
306
307 base = of_iomap(np, 0);
308 if (!base) {
309 pr_warn("failed to map ocotp\n");
310 goto put_node;
311 }
312
313 /*
314 * SPEED_GRADING[1:0] defines the max speed of ARM:
315 * 2b'11: 1200000000Hz;
316 * 2b'10: 996000000Hz;
317 * 2b'01: 852000000Hz; -- i.MX6Q Only, exclusive with 996MHz.
318 * 2b'00: 792000000Hz;
319 * We need to set the max speed of ARM according to fuse map.
320 */
321 val = readl_relaxed(base + OCOTP_CFG3);
322 val >>= OCOTP_CFG3_SPEED_SHIFT;
323 val &= 0x3;
324
325 if ((val != OCOTP_CFG3_SPEED_1P2GHZ) && cpu_is_imx6q())
326 if (dev_pm_opp_disable(cpu_dev, 1200000000))
327 pr_warn("failed to disable 1.2 GHz OPP\n");
328 if (val < OCOTP_CFG3_SPEED_996MHZ)
329 if (dev_pm_opp_disable(cpu_dev, 996000000))
330 pr_warn("failed to disable 996 MHz OPP\n");
331 if (cpu_is_imx6q()) {
332 if (val != OCOTP_CFG3_SPEED_852MHZ)
333 if (dev_pm_opp_disable(cpu_dev, 852000000))
334 pr_warn("failed to disable 852 MHz OPP\n");
335 }
336 iounmap(base);
337put_node:
338 of_node_put(np);
339}
340
341static void __init imx6q_opp_init(void)
342{
343 struct device_node *np;
344 struct device *cpu_dev = get_cpu_device(0);
345
346 if (!cpu_dev) {
347 pr_warn("failed to get cpu0 device\n");
348 return;
349 }
350 np = of_node_get(cpu_dev->of_node);
351 if (!np) {
352 pr_warn("failed to find cpu0 node\n");
353 return;
354 }
355
356 if (dev_pm_opp_of_add_table(cpu_dev)) {
357 pr_warn("failed to init OPP table\n");
358 goto put_node;
359 }
360
361 imx6q_opp_check_speed_grading(cpu_dev);
362
363put_node:
364 of_node_put(np);
365}
366
367static struct platform_device imx6q_cpufreq_pdev = {
368 .name = "imx6q-cpufreq",
369};
370
371static void __init imx6q_init_late(void) 289static void __init imx6q_init_late(void)
372{ 290{
373 /* 291 /*
@@ -380,10 +298,8 @@ static void __init imx6q_init_late(void)
380 (cpu_is_imx6dl() && imx_get_soc_revision() > IMX_CHIP_REVISION_1_0)) 298 (cpu_is_imx6dl() && imx_get_soc_revision() > IMX_CHIP_REVISION_1_0))
381 imx6q_cpuidle_init(); 299 imx6q_cpuidle_init();
382 300
383 if (IS_ENABLED(CONFIG_ARM_IMX6Q_CPUFREQ)) { 301 if (IS_ENABLED(CONFIG_ARM_IMX6Q_CPUFREQ))
384 imx6q_opp_init(); 302 platform_device_register_simple("imx6q-cpufreq", -1, NULL, 0);
385 platform_device_register(&imx6q_cpufreq_pdev);
386 }
387} 303}
388 304
389static void __init imx6q_map_io(void) 305static void __init imx6q_map_io(void)
diff --git a/drivers/cpufreq/imx6q-cpufreq.c b/drivers/cpufreq/imx6q-cpufreq.c
index 14466a9b01c0..628fe899cb48 100644
--- a/drivers/cpufreq/imx6q-cpufreq.c
+++ b/drivers/cpufreq/imx6q-cpufreq.c
@@ -12,6 +12,7 @@
12#include <linux/err.h> 12#include <linux/err.h>
13#include <linux/module.h> 13#include <linux/module.h>
14#include <linux/of.h> 14#include <linux/of.h>
15#include <linux/of_address.h>
15#include <linux/pm_opp.h> 16#include <linux/pm_opp.h>
16#include <linux/platform_device.h> 17#include <linux/platform_device.h>
17#include <linux/regulator/consumer.h> 18#include <linux/regulator/consumer.h>
@@ -191,6 +192,57 @@ static struct cpufreq_driver imx6q_cpufreq_driver = {
191 .suspend = cpufreq_generic_suspend, 192 .suspend = cpufreq_generic_suspend,
192}; 193};
193 194
195#define OCOTP_CFG3 0x440
196#define OCOTP_CFG3_SPEED_SHIFT 16
197#define OCOTP_CFG3_SPEED_1P2GHZ 0x3
198#define OCOTP_CFG3_SPEED_996MHZ 0x2
199#define OCOTP_CFG3_SPEED_852MHZ 0x1
200
201static void imx6q_opp_check_speed_grading(struct device *dev)
202{
203 struct device_node *np;
204 void __iomem *base;
205 u32 val;
206
207 np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-ocotp");
208 if (!np)
209 return;
210
211 base = of_iomap(np, 0);
212 if (!base) {
213 dev_err(dev, "failed to map ocotp\n");
214 goto put_node;
215 }
216
217 /*
218 * SPEED_GRADING[1:0] defines the max speed of ARM:
219 * 2b'11: 1200000000Hz;
220 * 2b'10: 996000000Hz;
221 * 2b'01: 852000000Hz; -- i.MX6Q Only, exclusive with 996MHz.
222 * 2b'00: 792000000Hz;
223 * We need to set the max speed of ARM according to fuse map.
224 */
225 val = readl_relaxed(base + OCOTP_CFG3);
226 val >>= OCOTP_CFG3_SPEED_SHIFT;
227 val &= 0x3;
228
229 if ((val != OCOTP_CFG3_SPEED_1P2GHZ) &&
230 of_machine_is_compatible("fsl,imx6q"))
231 if (dev_pm_opp_disable(dev, 1200000000))
232 dev_warn(dev, "failed to disable 1.2GHz OPP\n");
233 if (val < OCOTP_CFG3_SPEED_996MHZ)
234 if (dev_pm_opp_disable(dev, 996000000))
235 dev_warn(dev, "failed to disable 996MHz OPP\n");
236 if (of_machine_is_compatible("fsl,imx6q")) {
237 if (val != OCOTP_CFG3_SPEED_852MHZ)
238 if (dev_pm_opp_disable(dev, 852000000))
239 dev_warn(dev, "failed to disable 852MHz OPP\n");
240 }
241 iounmap(base);
242put_node:
243 of_node_put(np);
244}
245
194static int imx6q_cpufreq_probe(struct platform_device *pdev) 246static int imx6q_cpufreq_probe(struct platform_device *pdev)
195{ 247{
196 struct device_node *np; 248 struct device_node *np;
@@ -252,28 +304,21 @@ static int imx6q_cpufreq_probe(struct platform_device *pdev)
252 goto put_reg; 304 goto put_reg;
253 } 305 }
254 306
255 /* 307 ret = dev_pm_opp_of_add_table(cpu_dev);
256 * We expect an OPP table supplied by platform. 308 if (ret < 0) {
257 * Just, incase the platform did not supply the OPP 309 dev_err(cpu_dev, "failed to init OPP table: %d\n", ret);
258 * table, it will try to get it. 310 goto put_reg;
259 */ 311 }
260 num = dev_pm_opp_get_opp_count(cpu_dev);
261 if (num < 0) {
262 ret = dev_pm_opp_of_add_table(cpu_dev);
263 if (ret < 0) {
264 dev_err(cpu_dev, "failed to init OPP table: %d\n", ret);
265 goto put_reg;
266 }
267 312
268 /* Because we have added the OPPs here, we must free them */ 313 imx6q_opp_check_speed_grading(cpu_dev);
269 free_opp = true;
270 314
271 num = dev_pm_opp_get_opp_count(cpu_dev); 315 /* Because we have added the OPPs here, we must free them */
272 if (num < 0) { 316 free_opp = true;
273 ret = num; 317 num = dev_pm_opp_get_opp_count(cpu_dev);
274 dev_err(cpu_dev, "no OPP table is found: %d\n", ret); 318 if (num < 0) {
275 goto out_free_opp; 319 ret = num;
276 } 320 dev_err(cpu_dev, "no OPP table is found: %d\n", ret);
321 goto out_free_opp;
277 } 322 }
278 323
279 ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table); 324 ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table);