blob: f2818afa0d80ee5423d53de69078c0a0bf99996e [file] [log] [blame]
Patrick Daly985c14b2012-12-03 17:12:37 -08001/*
2 * Copyright (c) 2013, The Linux Foundation. All rights reserved.
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 and
6 * only version 2 as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13
14#define pr_fmt(fmt) "%s: " fmt, __func__
15
16#include <linux/kernel.h>
17#include <linux/module.h>
18#include <linux/init.h>
19#include <linux/io.h>
20#include <linux/delay.h>
21#include <linux/mutex.h>
22#include <linux/spinlock.h>
23#include <linux/errno.h>
24#include <linux/cpufreq.h>
25#include <linux/clk.h>
26#include <linux/platform_device.h>
27#include <linux/iopoll.h>
28
29#include <mach/board.h>
30#include <mach/msm_iomap.h>
31#include <mach/msm_bus.h>
32#include <mach/msm_bus_board.h>
33#include <mach/rpm-regulator.h>
34#include <mach/clk-provider.h>
35#include <mach/rpm-regulator-smd.h>
36
37#include "acpuclock.h"
38#include "acpuclock-cortex.h"
39
40#define POLL_INTERVAL_US 1
41#define APCS_RCG_UPDATE_TIMEOUT_US 20
42
Patrick Daly9196ed42013-03-13 15:59:03 -070043static struct acpuclk_drv_data *priv;
Patrick Daly985c14b2012-12-03 17:12:37 -080044static uint32_t bus_perf_client;
45
46/* Update the bus bandwidth request. */
47static void set_bus_bw(unsigned int bw)
48{
49 int ret;
50
Patrick Daly9196ed42013-03-13 15:59:03 -070051 if (bw >= priv->bus_scale->num_usecases) {
Patrick Daly985c14b2012-12-03 17:12:37 -080052 pr_err("invalid bandwidth request (%d)\n", bw);
53 return;
54 }
55
56 /* Update bandwidth if request has changed. This may sleep. */
57 ret = msm_bus_scale_client_update_request(bus_perf_client, bw);
58 if (ret)
59 pr_err("bandwidth request failed (%d)\n", ret);
60
61 return;
62}
63
64/* Apply any voltage increases. */
65static int increase_vdd(unsigned int vdd_cpu, unsigned int vdd_mem)
66{
67 int rc = 0;
68
Patrick Daly18748a72013-04-24 18:59:22 -070069 if (priv->vdd_mem) {
70 /*
71 * Increase vdd_mem before vdd_cpu. vdd_mem should
72 * be >= vdd_cpu.
73 */
74 rc = regulator_set_voltage(priv->vdd_mem, vdd_mem,
75 priv->vdd_max_mem);
76 if (rc) {
77 pr_err("vdd_mem increase failed (%d)\n", rc);
78 return rc;
79 }
Patrick Daly985c14b2012-12-03 17:12:37 -080080 }
81
Patrick Daly9196ed42013-03-13 15:59:03 -070082 rc = regulator_set_voltage(priv->vdd_cpu, vdd_cpu, priv->vdd_max_cpu);
Patrick Daly985c14b2012-12-03 17:12:37 -080083 if (rc)
84 pr_err("vdd_cpu increase failed (%d)\n", rc);
85
86 return rc;
87}
88
89/* Apply any per-cpu voltage decreases. */
90static void decrease_vdd(unsigned int vdd_cpu, unsigned int vdd_mem)
91{
92 int ret;
93
94 /* Update CPU voltage. */
Patrick Daly9196ed42013-03-13 15:59:03 -070095 ret = regulator_set_voltage(priv->vdd_cpu, vdd_cpu, priv->vdd_max_cpu);
Patrick Daly985c14b2012-12-03 17:12:37 -080096 if (ret) {
97 pr_err("vdd_cpu decrease failed (%d)\n", ret);
98 return;
99 }
100
Patrick Daly18748a72013-04-24 18:59:22 -0700101 if (!priv->vdd_mem)
102 return;
103
Patrick Daly985c14b2012-12-03 17:12:37 -0800104 /* Decrease vdd_mem after vdd_cpu. vdd_mem should be >= vdd_cpu. */
Patrick Daly9196ed42013-03-13 15:59:03 -0700105 ret = regulator_set_voltage(priv->vdd_mem, vdd_mem, priv->vdd_max_mem);
Patrick Daly985c14b2012-12-03 17:12:37 -0800106 if (ret)
107 pr_err("vdd_mem decrease failed (%d)\n", ret);
108}
109
110static void select_clk_source_div(struct acpuclk_drv_data *drv_data,
111 struct clkctl_acpu_speed *s)
112{
113 u32 regval, rc, src_div;
114 void __iomem *apcs_rcg_config = drv_data->apcs_rcg_config;
115 void __iomem *apcs_rcg_cmd = drv_data->apcs_rcg_cmd;
116 struct acpuclk_reg_data *r = &drv_data->reg_data;
117
118 src_div = s->src_div ? ((2 * s->src_div) - 1) : s->src_div;
119
120 regval = readl_relaxed(apcs_rcg_config);
121 regval &= ~r->cfg_src_mask;
122 regval |= s->src_sel << r->cfg_src_shift;
123 regval &= ~r->cfg_div_mask;
124 regval |= src_div << r->cfg_div_shift;
125 writel_relaxed(regval, apcs_rcg_config);
126
127 /* Update the configuration */
128 regval = readl_relaxed(apcs_rcg_cmd);
129 regval |= r->update_mask;
130 writel_relaxed(regval, apcs_rcg_cmd);
131
132 /* Wait for the update to take effect */
Patrick Daly6bda5912013-04-03 16:06:07 -0700133 rc = readl_poll_timeout_noirq(apcs_rcg_cmd, regval,
Patrick Daly985c14b2012-12-03 17:12:37 -0800134 !(regval & r->poll_mask),
135 POLL_INTERVAL_US,
136 APCS_RCG_UPDATE_TIMEOUT_US);
137 if (rc)
138 pr_warn("acpu rcg didn't update its configuration\n");
139}
140
Patrick Daly8016dca2013-05-28 20:05:17 -0700141static struct clkctl_acpu_speed *__init find_cur_cpu_level(void)
142{
143 struct clkctl_acpu_speed *f, *max = priv->freq_tbl;
144 void __iomem *apcs_rcg_config = priv->apcs_rcg_config;
145 struct acpuclk_reg_data *r = &priv->reg_data;
146 u32 regval, div, src;
147 unsigned long rate;
148 struct clk *parent;
149
150 regval = readl_relaxed(apcs_rcg_config);
151 src = regval & r->cfg_src_mask;
152 src >>= r->cfg_src_shift;
153
154 div = regval & r->cfg_div_mask;
155 div >>= r->cfg_div_shift;
156 /* No support for half-integer dividers */
157 div = div > 1 ? (div + 1) / 2 : 0;
158
159 for (f = priv->freq_tbl; f->khz; f++) {
160 if (f->use_for_scaling)
161 max = f;
162
163 if (f->src_sel != src || f->src_div != div)
164 continue;
165
166 parent = priv->src_clocks[f->src].clk;
167 rate = parent->rate / (div ? div : 1);
168 if (f->khz * 1000 == rate)
169 break;
170 }
171
172 if (f->khz)
173 return f;
174
175 pr_err("CPUs are running at an unknown rate. Defaulting to %u KHz.\n",
176 max->khz);
177
178 /* Change to a safe frequency */
179 select_clk_source_div(priv, priv->freq_tbl);
180 /* Default to largest frequency */
181 return max;
182}
183
Patrick Daly57d87e62013-04-09 18:51:51 -0700184static int set_speed_atomic(struct clkctl_acpu_speed *tgt_s)
185{
186 struct clkctl_acpu_speed *strt_s = priv->current_speed;
187 struct clk *strt = priv->src_clocks[strt_s->src].clk;
188 struct clk *tgt = priv->src_clocks[tgt_s->src].clk;
189 int rc = 0;
190
191 WARN(strt_s->src == ACPUPLL && tgt_s->src == ACPUPLL,
192 "can't reprogram ACPUPLL during atomic context\n");
193 rc = clk_enable(tgt);
194 if (rc)
195 return rc;
196
197 select_clk_source_div(priv, tgt_s);
198 clk_disable(strt);
199
200 return rc;
201}
202
203static int set_speed(struct clkctl_acpu_speed *tgt_s)
Patrick Daly985c14b2012-12-03 17:12:37 -0800204{
205 int rc = 0;
Patrick Daly83806032013-03-25 15:18:24 -0700206 unsigned int div = tgt_s->src_div ? tgt_s->src_div : 1;
207 unsigned int tgt_freq_hz = tgt_s->khz * 1000 * div;
Patrick Daly9196ed42013-03-13 15:59:03 -0700208 struct clkctl_acpu_speed *strt_s = priv->current_speed;
209 struct clkctl_acpu_speed *cxo_s = &priv->freq_tbl[0];
210 struct clk *strt = priv->src_clocks[strt_s->src].clk;
211 struct clk *tgt = priv->src_clocks[tgt_s->src].clk;
Patrick Daly985c14b2012-12-03 17:12:37 -0800212
213 if (strt_s->src == ACPUPLL && tgt_s->src == ACPUPLL) {
214 /* Switch to another always on src */
Patrick Daly9196ed42013-03-13 15:59:03 -0700215 select_clk_source_div(priv, cxo_s);
Patrick Daly985c14b2012-12-03 17:12:37 -0800216
217 /* Re-program acpu pll */
Patrick Daly57d87e62013-04-09 18:51:51 -0700218 clk_disable_unprepare(tgt);
Patrick Dalye85c6bc2013-01-31 14:14:28 -0800219
Patrick Daly985c14b2012-12-03 17:12:37 -0800220 rc = clk_set_rate(tgt, tgt_freq_hz);
221 if (rc)
222 pr_err("Failed to set ACPU PLL to %u\n", tgt_freq_hz);
Patrick Dalye85c6bc2013-01-31 14:14:28 -0800223
Patrick Daly57d87e62013-04-09 18:51:51 -0700224 BUG_ON(clk_prepare_enable(tgt));
Patrick Daly985c14b2012-12-03 17:12:37 -0800225
226 /* Switch back to acpu pll */
Patrick Daly9196ed42013-03-13 15:59:03 -0700227 select_clk_source_div(priv, tgt_s);
Patrick Daly985c14b2012-12-03 17:12:37 -0800228
229 } else if (strt_s->src != ACPUPLL && tgt_s->src == ACPUPLL) {
230 rc = clk_set_rate(tgt, tgt_freq_hz);
231 if (rc) {
232 pr_err("Failed to set ACPU PLL to %u\n", tgt_freq_hz);
233 return rc;
234 }
235
Patrick Daly57d87e62013-04-09 18:51:51 -0700236 rc = clk_prepare_enable(tgt);
Patrick Dalye85c6bc2013-01-31 14:14:28 -0800237
Patrick Daly985c14b2012-12-03 17:12:37 -0800238 if (rc) {
239 pr_err("ACPU PLL enable failed\n");
240 return rc;
241 }
242
Patrick Daly9196ed42013-03-13 15:59:03 -0700243 select_clk_source_div(priv, tgt_s);
Patrick Daly985c14b2012-12-03 17:12:37 -0800244
Patrick Daly57d87e62013-04-09 18:51:51 -0700245 clk_disable_unprepare(strt);
Patrick Dalye85c6bc2013-01-31 14:14:28 -0800246
Patrick Daly985c14b2012-12-03 17:12:37 -0800247 } else {
Patrick Daly57d87e62013-04-09 18:51:51 -0700248 rc = clk_prepare_enable(tgt);
Patrick Dalye85c6bc2013-01-31 14:14:28 -0800249
Patrick Daly985c14b2012-12-03 17:12:37 -0800250 if (rc) {
251 pr_err("%s enable failed\n",
Patrick Daly9196ed42013-03-13 15:59:03 -0700252 priv->src_clocks[tgt_s->src].name);
Patrick Daly985c14b2012-12-03 17:12:37 -0800253 return rc;
254 }
255
Patrick Daly9196ed42013-03-13 15:59:03 -0700256 select_clk_source_div(priv, tgt_s);
Patrick Daly985c14b2012-12-03 17:12:37 -0800257
Patrick Daly57d87e62013-04-09 18:51:51 -0700258 clk_disable_unprepare(strt);
Patrick Dalye85c6bc2013-01-31 14:14:28 -0800259
Patrick Daly985c14b2012-12-03 17:12:37 -0800260 }
261
262 return rc;
263}
264
265static int acpuclk_cortex_set_rate(int cpu, unsigned long rate,
266 enum setrate_reason reason)
267{
268 struct clkctl_acpu_speed *tgt_s, *strt_s;
269 int rc = 0;
270
271 if (reason == SETRATE_CPUFREQ)
Patrick Daly9196ed42013-03-13 15:59:03 -0700272 mutex_lock(&priv->lock);
Patrick Daly985c14b2012-12-03 17:12:37 -0800273
Patrick Daly9196ed42013-03-13 15:59:03 -0700274 strt_s = priv->current_speed;
Patrick Daly985c14b2012-12-03 17:12:37 -0800275
276 /* Return early if rate didn't change */
Patrick Daly8016dca2013-05-28 20:05:17 -0700277 if (rate == strt_s->khz && reason != SETRATE_INIT)
Patrick Daly985c14b2012-12-03 17:12:37 -0800278 goto out;
279
280 /* Find target frequency */
Patrick Daly9196ed42013-03-13 15:59:03 -0700281 for (tgt_s = priv->freq_tbl; tgt_s->khz != 0; tgt_s++)
Patrick Daly985c14b2012-12-03 17:12:37 -0800282 if (tgt_s->khz == rate)
283 break;
284 if (tgt_s->khz == 0) {
285 rc = -EINVAL;
286 goto out;
287 }
288
289 /* Increase VDD levels if needed */
Patrick Daly8016dca2013-05-28 20:05:17 -0700290 if ((reason == SETRATE_CPUFREQ)
Patrick Daly985c14b2012-12-03 17:12:37 -0800291 && (tgt_s->khz > strt_s->khz)) {
292 rc = increase_vdd(tgt_s->vdd_cpu, tgt_s->vdd_mem);
293 if (rc)
294 goto out;
295 }
296
297 pr_debug("Switching from CPU rate %u KHz -> %u KHz\n",
298 strt_s->khz, tgt_s->khz);
299
Patrick Dalye85c6bc2013-01-31 14:14:28 -0800300 /* Switch CPU speed. Flag indicates atomic context */
301 if (reason == SETRATE_CPUFREQ || reason == SETRATE_INIT)
Patrick Daly57d87e62013-04-09 18:51:51 -0700302 rc = set_speed(tgt_s);
Patrick Dalye85c6bc2013-01-31 14:14:28 -0800303 else
Patrick Daly57d87e62013-04-09 18:51:51 -0700304 rc = set_speed_atomic(tgt_s);
Patrick Dalye85c6bc2013-01-31 14:14:28 -0800305
Patrick Daly985c14b2012-12-03 17:12:37 -0800306 if (rc)
307 goto out;
308
Patrick Daly9196ed42013-03-13 15:59:03 -0700309 priv->current_speed = tgt_s;
Patrick Daly985c14b2012-12-03 17:12:37 -0800310 pr_debug("CPU speed change complete\n");
311
312 /* Nothing else to do for SWFI or power-collapse. */
313 if (reason == SETRATE_SWFI || reason == SETRATE_PC)
314 goto out;
315
316 /* Update bus bandwith request */
317 set_bus_bw(tgt_s->bw_level);
318
319 /* Drop VDD levels if we can. */
Patrick Daly8016dca2013-05-28 20:05:17 -0700320 if (tgt_s->khz < strt_s->khz || reason == SETRATE_INIT)
Patrick Daly985c14b2012-12-03 17:12:37 -0800321 decrease_vdd(tgt_s->vdd_cpu, tgt_s->vdd_mem);
322
323out:
324 if (reason == SETRATE_CPUFREQ)
Patrick Daly9196ed42013-03-13 15:59:03 -0700325 mutex_unlock(&priv->lock);
Patrick Daly985c14b2012-12-03 17:12:37 -0800326 return rc;
327}
328
329static unsigned long acpuclk_cortex_get_rate(int cpu)
330{
Patrick Daly9196ed42013-03-13 15:59:03 -0700331 return priv->current_speed->khz;
Patrick Daly985c14b2012-12-03 17:12:37 -0800332}
333
334#ifdef CONFIG_CPU_FREQ_MSM
335static struct cpufreq_frequency_table freq_table[30];
336
337static void __init cpufreq_table_init(void)
338{
339 int i, freq_cnt = 0;
340
Patrick Daly9196ed42013-03-13 15:59:03 -0700341 /* Construct the freq_table tables from priv->freq_tbl. */
342 for (i = 0; priv->freq_tbl[i].khz != 0
Patrick Dalyec985232013-10-15 18:52:43 -0700343 && freq_cnt < ARRAY_SIZE(freq_table) - 1; i++) {
Patrick Daly9196ed42013-03-13 15:59:03 -0700344 if (!priv->freq_tbl[i].use_for_scaling)
Patrick Daly985c14b2012-12-03 17:12:37 -0800345 continue;
346 freq_table[freq_cnt].index = freq_cnt;
Patrick Daly9196ed42013-03-13 15:59:03 -0700347 freq_table[freq_cnt].frequency = priv->freq_tbl[i].khz;
Patrick Daly985c14b2012-12-03 17:12:37 -0800348 freq_cnt++;
349 }
350 /* freq_table not big enough to store all usable freqs. */
Patrick Daly9196ed42013-03-13 15:59:03 -0700351 BUG_ON(priv->freq_tbl[i].khz != 0);
Patrick Daly985c14b2012-12-03 17:12:37 -0800352
353 freq_table[freq_cnt].index = freq_cnt;
354 freq_table[freq_cnt].frequency = CPUFREQ_TABLE_END;
355
356 pr_info("CPU: %d scaling frequencies supported.\n", freq_cnt);
357
358 /* Register table with CPUFreq. */
359 for_each_possible_cpu(i)
360 cpufreq_frequency_table_get_attr(freq_table, i);
361}
362#else
363static void __init cpufreq_table_init(void) {}
364#endif
365
366static struct acpuclk_data acpuclk_cortex_data = {
367 .set_rate = acpuclk_cortex_set_rate,
368 .get_rate = acpuclk_cortex_get_rate,
Patrick Daly985c14b2012-12-03 17:12:37 -0800369};
370
Patrick Daly66e32aa2013-05-30 15:11:52 -0700371void __init get_speed_bin(void __iomem *base, struct bin_info *bin)
372{
373 u32 pte_efuse, redundant_sel;
374
375 pte_efuse = readl_relaxed(base);
376 redundant_sel = (pte_efuse >> 24) & 0x7;
377 bin->speed = pte_efuse & 0x7;
378
379 if (redundant_sel == 1)
380 bin->speed = (pte_efuse >> 27) & 0x7;
381
382 bin->speed_valid = !!(pte_efuse & BIT(3));
383}
384
385static struct clkctl_acpu_speed *__init select_freq_plan(void)
386{
387 struct bin_info bin;
388
389 if (!priv->pte_efuse_base)
390 return priv->freq_tbl;
391
392 get_speed_bin(priv->pte_efuse_base, &bin);
393
394 if (bin.speed_valid) {
395 pr_info("SPEED BIN: %d\n", bin.speed);
396 } else {
397 bin.speed = 0;
398 pr_warn("SPEED BIN: Defaulting to %d\n",
399 bin.speed);
400 }
401
402 return priv->pvs_tables[bin.speed];
403}
404
Patrick Daly985c14b2012-12-03 17:12:37 -0800405int __init acpuclk_cortex_init(struct platform_device *pdev,
406 struct acpuclk_drv_data *data)
407{
Patrick Daly8016dca2013-05-28 20:05:17 -0700408 int rc;
409 int parent;
Patrick Daly985c14b2012-12-03 17:12:37 -0800410
Patrick Daly9196ed42013-03-13 15:59:03 -0700411 priv = data;
412 mutex_init(&priv->lock);
Patrick Daly985c14b2012-12-03 17:12:37 -0800413
Patrick Dalyaf8808e2013-03-20 12:57:00 -0700414 acpuclk_cortex_data.power_collapse_khz = priv->wait_for_irq_khz;
415 acpuclk_cortex_data.wait_for_irq_khz = priv->wait_for_irq_khz;
416
Patrick Daly66e32aa2013-05-30 15:11:52 -0700417 priv->freq_tbl = select_freq_plan();
418 if (!priv->freq_tbl) {
419 pr_err("Invalid freq table selected\n");
420 BUG();
421 }
422
Patrick Daly9196ed42013-03-13 15:59:03 -0700423 bus_perf_client = msm_bus_scale_register_client(priv->bus_scale);
Patrick Daly985c14b2012-12-03 17:12:37 -0800424 if (!bus_perf_client) {
425 pr_err("Unable to register bus client\n");
426 BUG();
427 }
428
Patrick Daly985c14b2012-12-03 17:12:37 -0800429 /* Initialize regulators */
Patrick Daly9196ed42013-03-13 15:59:03 -0700430 rc = increase_vdd(priv->vdd_max_cpu, priv->vdd_max_mem);
Patrick Daly985c14b2012-12-03 17:12:37 -0800431 if (rc)
Patrick Daly8016dca2013-05-28 20:05:17 -0700432 return rc;
Patrick Daly985c14b2012-12-03 17:12:37 -0800433
Patrick Daly18748a72013-04-24 18:59:22 -0700434 if (priv->vdd_mem) {
435 rc = regulator_enable(priv->vdd_mem);
436 if (rc) {
437 dev_err(&pdev->dev, "regulator_enable for mem failed\n");
Patrick Daly8016dca2013-05-28 20:05:17 -0700438 return rc;
Patrick Daly18748a72013-04-24 18:59:22 -0700439 }
Patrick Daly985c14b2012-12-03 17:12:37 -0800440 }
441
Patrick Daly9196ed42013-03-13 15:59:03 -0700442 rc = regulator_enable(priv->vdd_cpu);
Patrick Daly985c14b2012-12-03 17:12:37 -0800443 if (rc) {
444 dev_err(&pdev->dev, "regulator_enable for cpu failed\n");
Patrick Daly8016dca2013-05-28 20:05:17 -0700445 return rc;
Patrick Daly985c14b2012-12-03 17:12:37 -0800446 }
447
Patrick Daly8016dca2013-05-28 20:05:17 -0700448 priv->current_speed = find_cur_cpu_level();
449 parent = priv->current_speed->src;
450 rc = clk_prepare_enable(priv->src_clocks[parent].clk);
451 if (rc) {
452 dev_err(&pdev->dev, "handoff: prepare_enable failed\n");
453 return rc;
454 }
455
456 rc = acpuclk_cortex_set_rate(0, priv->current_speed->khz, SETRATE_INIT);
457 if (rc) {
458 dev_err(&pdev->dev, "handoff: set rate failed\n");
459 return rc;
460 }
Patrick Daly985c14b2012-12-03 17:12:37 -0800461
462 acpuclk_register(&acpuclk_cortex_data);
463 cpufreq_table_init();
464
465 return 0;
Patrick Daly985c14b2012-12-03 17:12:37 -0800466}