diff options
Diffstat (limited to 'drivers/cpufreq/exynos4x12-cpufreq.c')
-rw-r--r-- | drivers/cpufreq/exynos4x12-cpufreq.c | 40 |
1 files changed, 34 insertions, 6 deletions
diff --git a/drivers/cpufreq/exynos4x12-cpufreq.c b/drivers/cpufreq/exynos4x12-cpufreq.c index 63a3907ce578..351a2074cfea 100644 --- a/drivers/cpufreq/exynos4x12-cpufreq.c +++ b/drivers/cpufreq/exynos4x12-cpufreq.c | |||
@@ -16,6 +16,8 @@ | |||
16 | #include <linux/io.h> | 16 | #include <linux/io.h> |
17 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
18 | #include <linux/cpufreq.h> | 18 | #include <linux/cpufreq.h> |
19 | #include <linux/of.h> | ||
20 | #include <linux/of_address.h> | ||
19 | 21 | ||
20 | #include "exynos-cpufreq.h" | 22 | #include "exynos-cpufreq.h" |
21 | 23 | ||
@@ -23,6 +25,7 @@ static struct clk *cpu_clk; | |||
23 | static struct clk *moutcore; | 25 | static struct clk *moutcore; |
24 | static struct clk *mout_mpll; | 26 | static struct clk *mout_mpll; |
25 | static struct clk *mout_apll; | 27 | static struct clk *mout_apll; |
28 | static struct exynos_dvfs_info *cpufreq; | ||
26 | 29 | ||
27 | static unsigned int exynos4x12_volt_table[] = { | 30 | static unsigned int exynos4x12_volt_table[] = { |
28 | 1350000, 1287500, 1250000, 1187500, 1137500, 1087500, 1037500, | 31 | 1350000, 1287500, 1250000, 1187500, 1137500, 1087500, 1037500, |
@@ -105,19 +108,20 @@ static void exynos4x12_set_clkdiv(unsigned int div_index) | |||
105 | 108 | ||
106 | tmp = apll_freq_4x12[div_index].clk_div_cpu0; | 109 | tmp = apll_freq_4x12[div_index].clk_div_cpu0; |
107 | 110 | ||
108 | __raw_writel(tmp, EXYNOS4_CLKDIV_CPU); | 111 | __raw_writel(tmp, cpufreq->cmu_regs + EXYNOS4_CLKDIV_CPU); |
109 | 112 | ||
110 | while (__raw_readl(EXYNOS4_CLKDIV_STATCPU) & 0x11111111) | 113 | while (__raw_readl(cpufreq->cmu_regs + EXYNOS4_CLKDIV_STATCPU) |
114 | & 0x11111111) | ||
111 | cpu_relax(); | 115 | cpu_relax(); |
112 | 116 | ||
113 | /* Change Divider - CPU1 */ | 117 | /* Change Divider - CPU1 */ |
114 | tmp = apll_freq_4x12[div_index].clk_div_cpu1; | 118 | tmp = apll_freq_4x12[div_index].clk_div_cpu1; |
115 | 119 | ||
116 | __raw_writel(tmp, EXYNOS4_CLKDIV_CPU1); | 120 | __raw_writel(tmp, cpufreq->cmu_regs + EXYNOS4_CLKDIV_CPU1); |
117 | 121 | ||
118 | do { | 122 | do { |
119 | cpu_relax(); | 123 | cpu_relax(); |
120 | tmp = __raw_readl(EXYNOS4_CLKDIV_STATCPU1); | 124 | tmp = __raw_readl(cpufreq->cmu_regs + EXYNOS4_CLKDIV_STATCPU1); |
121 | } while (tmp != 0x0); | 125 | } while (tmp != 0x0); |
122 | } | 126 | } |
123 | 127 | ||
@@ -130,7 +134,7 @@ static void exynos4x12_set_apll(unsigned int index) | |||
130 | 134 | ||
131 | do { | 135 | do { |
132 | cpu_relax(); | 136 | cpu_relax(); |
133 | tmp = (__raw_readl(EXYNOS4_CLKMUX_STATCPU) | 137 | tmp = (__raw_readl(cpufreq->cmu_regs + EXYNOS4_CLKMUX_STATCPU) |
134 | >> EXYNOS4_CLKSRC_CPU_MUXCORE_SHIFT); | 138 | >> EXYNOS4_CLKSRC_CPU_MUXCORE_SHIFT); |
135 | tmp &= 0x7; | 139 | tmp &= 0x7; |
136 | } while (tmp != 0x2); | 140 | } while (tmp != 0x2); |
@@ -142,7 +146,7 @@ static void exynos4x12_set_apll(unsigned int index) | |||
142 | 146 | ||
143 | do { | 147 | do { |
144 | cpu_relax(); | 148 | cpu_relax(); |
145 | tmp = __raw_readl(EXYNOS4_CLKMUX_STATCPU); | 149 | tmp = __raw_readl(cpufreq->cmu_regs + EXYNOS4_CLKMUX_STATCPU); |
146 | tmp &= EXYNOS4_CLKMUX_STATCPU_MUXCORE_MASK; | 150 | tmp &= EXYNOS4_CLKMUX_STATCPU_MUXCORE_MASK; |
147 | } while (tmp != (0x1 << EXYNOS4_CLKSRC_CPU_MUXCORE_SHIFT)); | 151 | } while (tmp != (0x1 << EXYNOS4_CLKSRC_CPU_MUXCORE_SHIFT)); |
148 | } | 152 | } |
@@ -161,8 +165,30 @@ static void exynos4x12_set_frequency(unsigned int old_index, | |||
161 | 165 | ||
162 | int exynos4x12_cpufreq_init(struct exynos_dvfs_info *info) | 166 | int exynos4x12_cpufreq_init(struct exynos_dvfs_info *info) |
163 | { | 167 | { |
168 | struct device_node *np; | ||
164 | unsigned long rate; | 169 | unsigned long rate; |
165 | 170 | ||
171 | /* | ||
172 | * HACK: This is a temporary workaround to get access to clock | ||
173 | * controller registers directly and remove static mappings and | ||
174 | * dependencies on platform headers. It is necessary to enable | ||
175 | * Exynos multi-platform support and will be removed together with | ||
176 | * this whole driver as soon as Exynos gets migrated to use | ||
177 | * cpufreq-cpu0 driver. | ||
178 | */ | ||
179 | np = of_find_compatible_node(NULL, NULL, "samsung,exynos4412-clock"); | ||
180 | if (!np) { | ||
181 | pr_err("%s: failed to find clock controller DT node\n", | ||
182 | __func__); | ||
183 | return -ENODEV; | ||
184 | } | ||
185 | |||
186 | info->cmu_regs = of_iomap(np, 0); | ||
187 | if (!info->cmu_regs) { | ||
188 | pr_err("%s: failed to map CMU registers\n", __func__); | ||
189 | return -EFAULT; | ||
190 | } | ||
191 | |||
166 | cpu_clk = clk_get(NULL, "armclk"); | 192 | cpu_clk = clk_get(NULL, "armclk"); |
167 | if (IS_ERR(cpu_clk)) | 193 | if (IS_ERR(cpu_clk)) |
168 | return PTR_ERR(cpu_clk); | 194 | return PTR_ERR(cpu_clk); |
@@ -194,6 +220,8 @@ int exynos4x12_cpufreq_init(struct exynos_dvfs_info *info) | |||
194 | info->freq_table = exynos4x12_freq_table; | 220 | info->freq_table = exynos4x12_freq_table; |
195 | info->set_freq = exynos4x12_set_frequency; | 221 | info->set_freq = exynos4x12_set_frequency; |
196 | 222 | ||
223 | cpufreq = info; | ||
224 | |||
197 | return 0; | 225 | return 0; |
198 | 226 | ||
199 | err_mout_apll: | 227 | err_mout_apll: |