Commit c0fe5f278d2ce459c2aee2c26e26c761c72231a4

Authored by Santosh Shilimkar
Committed by Afzal Mohammed
1 parent 3b52353d4d
Exists in master

cpufreq: OMAP: cleanup for multi-SoC support, move into drivers/cpufreq

Move OMAP cpufreq driver from arch/arm/mach-omap2 into
drivers/cpufreq, along with a few cleanups:

- generalize support for better handling of different SoCs in the OMAP
- use OPP layer instead of OMAP clock internals for frequency table init

Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
[khilman@ti.com: move to drivers]
Signed-off-by: Kevin Hilman <khilman@ti.com>
[vaibhav.bedia@ti.com: Pull in for AM33xx]
Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>

Showing 4 changed files with 189 additions and 172 deletions Side-by-side Diff

arch/arm/plat-omap/Makefile
... ... @@ -28,7 +28,6 @@
28 28 obj-$(CONFIG_OMAP_IOMMU) += iommu.o iovmm.o
29 29 obj-$(CONFIG_OMAP_IOMMU_DEBUG) += iommu-debug.o
30 30  
31   -obj-$(CONFIG_CPU_FREQ) += cpu-omap.o
32 31 obj-$(CONFIG_OMAP_DM_TIMER) += dmtimer.o
33 32 obj-$(CONFIG_OMAP_DEBUG_DEVICES) += debug-devices.o
34 33 obj-$(CONFIG_OMAP_DEBUG_LEDS) += debug-leds.o
arch/arm/plat-omap/cpu-omap.c
1   -/*
2   - * linux/arch/arm/plat-omap/cpu-omap.c
3   - *
4   - * CPU frequency scaling for OMAP
5   - *
6   - * Copyright (C) 2005 Nokia Corporation
7   - * Written by Tony Lindgren <tony@atomide.com>
8   - *
9   - * Based on cpu-sa1110.c, Copyright (C) 2001 Russell King
10   - *
11   - * This program is free software; you can redistribute it and/or modify
12   - * it under the terms of the GNU General Public License version 2 as
13   - * published by the Free Software Foundation.
14   - */
15   -#include <linux/types.h>
16   -#include <linux/kernel.h>
17   -#include <linux/sched.h>
18   -#include <linux/cpufreq.h>
19   -#include <linux/delay.h>
20   -#include <linux/init.h>
21   -#include <linux/err.h>
22   -#include <linux/clk.h>
23   -#include <linux/io.h>
24   -
25   -#include <mach/hardware.h>
26   -#include <plat/clock.h>
27   -#include <asm/system.h>
28   -
29   -#define VERY_HI_RATE 900000000
30   -
31   -static struct cpufreq_frequency_table *freq_table;
32   -
33   -#ifdef CONFIG_ARCH_OMAP1
34   -#define MPU_CLK "mpu"
35   -#else
36   -#define MPU_CLK "virt_prcm_set"
37   -#endif
38   -
39   -static struct clk *mpu_clk;
40   -
41   -/* TODO: Add support for SDRAM timing changes */
42   -
43   -static int omap_verify_speed(struct cpufreq_policy *policy)
44   -{
45   - if (freq_table)
46   - return cpufreq_frequency_table_verify(policy, freq_table);
47   -
48   - if (policy->cpu)
49   - return -EINVAL;
50   -
51   - cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
52   - policy->cpuinfo.max_freq);
53   -
54   - policy->min = clk_round_rate(mpu_clk, policy->min * 1000) / 1000;
55   - policy->max = clk_round_rate(mpu_clk, policy->max * 1000) / 1000;
56   - cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
57   - policy->cpuinfo.max_freq);
58   - return 0;
59   -}
60   -
61   -static unsigned int omap_getspeed(unsigned int cpu)
62   -{
63   - unsigned long rate;
64   -
65   - if (cpu)
66   - return 0;
67   -
68   - rate = clk_get_rate(mpu_clk) / 1000;
69   - return rate;
70   -}
71   -
72   -static int omap_target(struct cpufreq_policy *policy,
73   - unsigned int target_freq,
74   - unsigned int relation)
75   -{
76   - struct cpufreq_freqs freqs;
77   - int ret = 0;
78   -
79   - /* Ensure desired rate is within allowed range. Some govenors
80   - * (ondemand) will just pass target_freq=0 to get the minimum. */
81   - if (target_freq < policy->min)
82   - target_freq = policy->min;
83   - if (target_freq > policy->max)
84   - target_freq = policy->max;
85   -
86   - freqs.old = omap_getspeed(0);
87   - freqs.new = clk_round_rate(mpu_clk, target_freq * 1000) / 1000;
88   - freqs.cpu = 0;
89   -
90   - if (freqs.old == freqs.new)
91   - return ret;
92   -
93   - cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
94   -#ifdef CONFIG_CPU_FREQ_DEBUG
95   - printk(KERN_DEBUG "cpufreq-omap: transition: %u --> %u\n",
96   - freqs.old, freqs.new);
97   -#endif
98   - ret = clk_set_rate(mpu_clk, freqs.new * 1000);
99   - cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
100   -
101   - return ret;
102   -}
103   -
104   -static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
105   -{
106   - int result = 0;
107   -
108   - mpu_clk = clk_get(NULL, MPU_CLK);
109   - if (IS_ERR(mpu_clk))
110   - return PTR_ERR(mpu_clk);
111   -
112   - if (policy->cpu != 0)
113   - return -EINVAL;
114   -
115   - policy->cur = policy->min = policy->max = omap_getspeed(0);
116   -
117   - clk_init_cpufreq_table(&freq_table);
118   - if (freq_table) {
119   - result = cpufreq_frequency_table_cpuinfo(policy, freq_table);
120   - if (!result)
121   - cpufreq_frequency_table_get_attr(freq_table,
122   - policy->cpu);
123   - } else {
124   - policy->cpuinfo.min_freq = clk_round_rate(mpu_clk, 0) / 1000;
125   - policy->cpuinfo.max_freq = clk_round_rate(mpu_clk,
126   - VERY_HI_RATE) / 1000;
127   - }
128   -
129   - /* FIXME: what's the actual transition time? */
130   - policy->cpuinfo.transition_latency = 300 * 1000;
131   -
132   - return 0;
133   -}
134   -
135   -static int omap_cpu_exit(struct cpufreq_policy *policy)
136   -{
137   - clk_exit_cpufreq_table(&freq_table);
138   - clk_put(mpu_clk);
139   - return 0;
140   -}
141   -
142   -static struct freq_attr *omap_cpufreq_attr[] = {
143   - &cpufreq_freq_attr_scaling_available_freqs,
144   - NULL,
145   -};
146   -
147   -static struct cpufreq_driver omap_driver = {
148   - .flags = CPUFREQ_STICKY,
149   - .verify = omap_verify_speed,
150   - .target = omap_target,
151   - .get = omap_getspeed,
152   - .init = omap_cpu_init,
153   - .exit = omap_cpu_exit,
154   - .name = "omap",
155   - .attr = omap_cpufreq_attr,
156   -};
157   -
158   -static int __init omap_cpufreq_init(void)
159   -{
160   - return cpufreq_register_driver(&omap_driver);
161   -}
162   -
163   -arch_initcall(omap_cpufreq_init);
164   -
165   -/*
166   - * if ever we want to remove this, upon cleanup call:
167   - *
168   - * cpufreq_unregister_driver()
169   - * cpufreq_frequency_table_put_attr()
170   - */
drivers/cpufreq/Makefile
... ... @@ -43,6 +43,7 @@
43 43 obj-$(CONFIG_ARM_S3C64XX_CPUFREQ) += s3c64xx-cpufreq.o
44 44 obj-$(CONFIG_ARM_S5PV210_CPUFREQ) += s5pv210-cpufreq.o
45 45 obj-$(CONFIG_ARM_EXYNOS4210_CPUFREQ) += exynos4210-cpufreq.o
  46 +obj-$(CONFIG_ARCH_OMAP2PLUS) += omap-cpufreq.o
46 47  
47 48 ##################################################################################
48 49 # PowerPC platform drivers
drivers/cpufreq/omap-cpufreq.c
  1 +/*
  2 + * CPU frequency scaling for OMAP
  3 + *
  4 + * Copyright (C) 2005 Nokia Corporation
  5 + * Written by Tony Lindgren <tony@atomide.com>
  6 + *
  7 + * Based on cpu-sa1110.c, Copyright (C) 2001 Russell King
  8 + *
  9 + * Copyright (C) 2007-2011 Texas Instruments, Inc.
  10 + * - OMAP3/4 support by Rajendra Nayak, Santosh Shilimkar
  11 + *
  12 + * This program is free software; you can redistribute it and/or modify
  13 + * it under the terms of the GNU General Public License version 2 as
  14 + * published by the Free Software Foundation.
  15 + */
  16 +#include <linux/types.h>
  17 +#include <linux/kernel.h>
  18 +#include <linux/sched.h>
  19 +#include <linux/cpufreq.h>
  20 +#include <linux/delay.h>
  21 +#include <linux/init.h>
  22 +#include <linux/err.h>
  23 +#include <linux/clk.h>
  24 +#include <linux/io.h>
  25 +#include <linux/opp.h>
  26 +
  27 +#include <asm/system.h>
  28 +#include <asm/smp_plat.h>
  29 +
  30 +#include <plat/clock.h>
  31 +#include <plat/omap-pm.h>
  32 +#include <plat/common.h>
  33 +
  34 +#include <mach/hardware.h>
  35 +
  36 +#define VERY_HI_RATE 900000000
  37 +
  38 +static struct cpufreq_frequency_table *freq_table;
  39 +static struct clk *mpu_clk;
  40 +
  41 +static int omap_verify_speed(struct cpufreq_policy *policy)
  42 +{
  43 + if (freq_table)
  44 + return cpufreq_frequency_table_verify(policy, freq_table);
  45 +
  46 + if (policy->cpu)
  47 + return -EINVAL;
  48 +
  49 + cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
  50 + policy->cpuinfo.max_freq);
  51 +
  52 + policy->min = clk_round_rate(mpu_clk, policy->min * 1000) / 1000;
  53 + policy->max = clk_round_rate(mpu_clk, policy->max * 1000) / 1000;
  54 + cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
  55 + policy->cpuinfo.max_freq);
  56 + return 0;
  57 +}
  58 +
  59 +static unsigned int omap_getspeed(unsigned int cpu)
  60 +{
  61 + unsigned long rate;
  62 +
  63 + if (cpu)
  64 + return 0;
  65 +
  66 + rate = clk_get_rate(mpu_clk) / 1000;
  67 + return rate;
  68 +}
  69 +
  70 +static int omap_target(struct cpufreq_policy *policy,
  71 + unsigned int target_freq,
  72 + unsigned int relation)
  73 +{
  74 + int ret = 0;
  75 + struct cpufreq_freqs freqs;
  76 +
  77 + /* Ensure desired rate is within allowed range. Some govenors
  78 + * (ondemand) will just pass target_freq=0 to get the minimum. */
  79 + if (target_freq < policy->min)
  80 + target_freq = policy->min;
  81 + if (target_freq > policy->max)
  82 + target_freq = policy->max;
  83 +
  84 + freqs.old = omap_getspeed(0);
  85 + freqs.new = clk_round_rate(mpu_clk, target_freq * 1000) / 1000;
  86 + freqs.cpu = 0;
  87 +
  88 + if (freqs.old == freqs.new)
  89 + return ret;
  90 +
  91 + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
  92 +
  93 +#ifdef CONFIG_CPU_FREQ_DEBUG
  94 + pr_info("cpufreq-omap: transition: %u --> %u\n", freqs.old, freqs.new);
  95 +#endif
  96 +
  97 + ret = clk_set_rate(mpu_clk, freqs.new * 1000);
  98 +
  99 + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
  100 +
  101 + return ret;
  102 +}
  103 +
  104 +static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
  105 +{
  106 + int result = 0;
  107 + struct device *mpu_dev;
  108 +
  109 + if (cpu_is_omap24xx())
  110 + mpu_clk = clk_get(NULL, "virt_prcm_set");
  111 + else if (cpu_is_omap34xx())
  112 + mpu_clk = clk_get(NULL, "dpll1_ck");
  113 + else if (cpu_is_omap44xx())
  114 + mpu_clk = clk_get(NULL, "dpll_mpu_ck");
  115 +
  116 + if (IS_ERR(mpu_clk))
  117 + return PTR_ERR(mpu_clk);
  118 +
  119 + if (policy->cpu != 0)
  120 + return -EINVAL;
  121 +
  122 + policy->cur = policy->min = policy->max = omap_getspeed(0);
  123 +
  124 + mpu_dev = omap2_get_mpuss_device();
  125 + if (!mpu_dev) {
  126 + pr_warning("%s: unable to get the mpu device\n", __func__);
  127 + return -EINVAL;
  128 + }
  129 + opp_init_cpufreq_table(mpu_dev, &freq_table);
  130 +
  131 + if (freq_table) {
  132 + result = cpufreq_frequency_table_cpuinfo(policy, freq_table);
  133 + if (!result)
  134 + cpufreq_frequency_table_get_attr(freq_table,
  135 + policy->cpu);
  136 + } else {
  137 + policy->cpuinfo.min_freq = clk_round_rate(mpu_clk, 0) / 1000;
  138 + policy->cpuinfo.max_freq = clk_round_rate(mpu_clk,
  139 + VERY_HI_RATE) / 1000;
  140 + }
  141 +
  142 + policy->min = policy->cpuinfo.min_freq;
  143 + policy->max = policy->cpuinfo.max_freq;
  144 + policy->cur = omap_getspeed(0);
  145 +
  146 + /* FIXME: what's the actual transition time? */
  147 + policy->cpuinfo.transition_latency = 300 * 1000;
  148 +
  149 + return 0;
  150 +}
  151 +
  152 +static int omap_cpu_exit(struct cpufreq_policy *policy)
  153 +{
  154 + clk_exit_cpufreq_table(&freq_table);
  155 + clk_put(mpu_clk);
  156 + return 0;
  157 +}
  158 +
  159 +static struct freq_attr *omap_cpufreq_attr[] = {
  160 + &cpufreq_freq_attr_scaling_available_freqs,
  161 + NULL,
  162 +};
  163 +
  164 +static struct cpufreq_driver omap_driver = {
  165 + .flags = CPUFREQ_STICKY,
  166 + .verify = omap_verify_speed,
  167 + .target = omap_target,
  168 + .get = omap_getspeed,
  169 + .init = omap_cpu_init,
  170 + .exit = omap_cpu_exit,
  171 + .name = "omap",
  172 + .attr = omap_cpufreq_attr,
  173 +};
  174 +
  175 +static int __init omap_cpufreq_init(void)
  176 +{
  177 + return cpufreq_register_driver(&omap_driver);
  178 +}
  179 +
  180 +static void __exit omap_cpufreq_exit(void)
  181 +{
  182 + cpufreq_unregister_driver(&omap_driver);
  183 +}
  184 +
  185 +MODULE_DESCRIPTION("cpufreq driver for OMAP SoCs");
  186 +MODULE_LICENSE("GPL");
  187 +module_init(omap_cpufreq_init);
  188 +module_exit(omap_cpufreq_exit);