Blame view

drivers/cpufreq/imx6q-cpufreq.c 17.2 KB
1dd538f07   Shawn Guo   cpufreq: add imx6...
1
  /*
90ff4d1c3   Bai Ping   MLK-14747 driver:...
2
3
   * Copyright (C) 2013-2016 Freescale Semiconductor, Inc.
   * Copyright 2017 NXP.
1dd538f07   Shawn Guo   cpufreq: add imx6...
4
5
6
7
8
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License version 2 as
   * published by the Free Software Foundation.
   */
80d1382e9   Bai Ping   MLK-9739 cpufreq:...
9
  #include <linux/busfreq-imx.h>
1dd538f07   Shawn Guo   cpufreq: add imx6...
10
  #include <linux/clk.h>
b494b48da   Sudeep KarkadaNagesha   cpufreq: imx6q-cp...
11
  #include <linux/cpu.h>
1dd538f07   Shawn Guo   cpufreq: add imx6...
12
  #include <linux/cpufreq.h>
1dd538f07   Shawn Guo   cpufreq: add imx6...
13
14
  #include <linux/err.h>
  #include <linux/module.h>
90ee80a6f   Leonard Crestez   MLK-14301: Revert...
15
  #include <linux/slab.h>
1dd538f07   Shawn Guo   cpufreq: add imx6...
16
  #include <linux/of.h>
e4db1c743   Nishanth Menon   PM / OPP: rename ...
17
  #include <linux/pm_opp.h>
1dd538f07   Shawn Guo   cpufreq: add imx6...
18
19
  #include <linux/platform_device.h>
  #include <linux/regulator/consumer.h>
62300a004   Bai Ping   MLK-9693 cpufreq:...
20
  #include <linux/suspend.h>
1dd538f07   Shawn Guo   cpufreq: add imx6...
21
22
23
  
  #define PU_SOC_VOLTAGE_NORMAL	1250000
  #define PU_SOC_VOLTAGE_HIGH	1275000
1a4dd3071   Bai Ping   MLK-11252-02 cpuf...
24
25
  #define DC_VOLTAGE_MIN		1300000
  #define DC_VOLTAGE_MAX		1400000
1dd538f07   Shawn Guo   cpufreq: add imx6...
26
  #define FREQ_1P2_GHZ		1200000000
276fa4846   Bai Ping   MLK-10271 cpufreq...
27
  #define FREQ_396_MHZ		396000
90ff4d1c3   Bai Ping   MLK-14747 driver:...
28
  #define FREQ_528_MHZ		528000
40b06ddfa   Bai Ping   MLK-13096-02 cpuf...
29
  #define FREQ_198_MHZ		198000
460db6ced   Bai Ping   MLK-13014 ARM: im...
30
  #define FREQ_24_MHZ		24000
1dd538f07   Shawn Guo   cpufreq: add imx6...
31

a7062855a   Bai Ping   MLK-13616 ARM: im...
32
  struct regulator *arm_reg;
1dd538f07   Shawn Guo   cpufreq: add imx6...
33
  static struct regulator *pu_reg;
a7062855a   Bai Ping   MLK-13616 ARM: im...
34
  struct regulator *soc_reg;
1a4dd3071   Bai Ping   MLK-11252-02 cpuf...
35
  static struct regulator *dc_reg;
1dd538f07   Shawn Guo   cpufreq: add imx6...
36
37
38
39
40
41
  
  static struct clk *arm_clk;
  static struct clk *pll1_sys_clk;
  static struct clk *pll1_sw_clk;
  static struct clk *step_clk;
  static struct clk *pll2_pfd2_396m_clk;
a35fc5a33   Bai Ping   cpufreq: imx: upd...
42
  /* clk used by i.MX6UL */
ced7bc8de   Bai Ping   MLK-11343-02 cpuf...
43
44
45
  static struct clk *pll1_bypass;
  static struct clk *pll1_bypass_src;
  static struct clk *pll1;
a35fc5a33   Bai Ping   cpufreq: imx: upd...
46
47
  static struct clk *pll2_bus_clk;
  static struct clk *secondary_sel_clk;
1dd538f07   Shawn Guo   cpufreq: add imx6...
48
  static struct device *cpu_dev;
cc87b8a8e   Viresh Kumar   imx6q: free OPP t...
49
  static bool free_opp;
1dd538f07   Shawn Guo   cpufreq: add imx6...
50
51
  static struct cpufreq_frequency_table *freq_table;
  static unsigned int transition_latency;
62300a004   Bai Ping   MLK-9693 cpufreq:...
52
  static struct mutex set_cpufreq_lock;
b4573d1d6   Anson Huang   cpufreq: imx6q: c...
53
54
  static u32 *imx6_soc_volt;
  static u32 soc_opp_count;
6babbe05d   Bai Ping   MLK-12623-01 cpuf...
55
  static bool ignore_dc_reg;
1d733f828   Bai Ping   MLK-13133-02 cpuf...
56
  static bool low_power_run_support;
b4573d1d6   Anson Huang   cpufreq: imx6q: c...
57

9c0ebcf78   Viresh Kumar   cpufreq: Implemen...
58
  static int imx6q_set_target(struct cpufreq_policy *policy, unsigned int index)
1dd538f07   Shawn Guo   cpufreq: add imx6...
59
  {
47d43ba73   Nishanth Menon   PM / OPP: rename ...
60
  	struct dev_pm_opp *opp;
1dd538f07   Shawn Guo   cpufreq: add imx6...
61
  	unsigned long freq_hz, volt, volt_old;
d4019f0a9   Viresh Kumar   cpufreq: move fre...
62
  	unsigned int old_freq, new_freq;
1dd538f07   Shawn Guo   cpufreq: add imx6...
63
  	int ret;
62300a004   Bai Ping   MLK-9693 cpufreq:...
64
  	mutex_lock(&set_cpufreq_lock);
d4019f0a9   Viresh Kumar   cpufreq: move fre...
65
66
  	new_freq = freq_table[index].frequency;
  	freq_hz = new_freq * 1000;
f1e77d6f0   Bai Ping   MLK-12868-01 cpuf...
67
  	old_freq = policy->cur;
1dd538f07   Shawn Guo   cpufreq: add imx6...
68

460db6ced   Bai Ping   MLK-13014 ARM: im...
69
70
71
  	/*
  	 * ON i.MX6ULL, the 24MHz setpoint is not seen by cpufreq
  	 * so we neet to prevent the cpufreq change frequency
40b06ddfa   Bai Ping   MLK-13096-02 cpuf...
72
  	 * from 24MHz to 198Mhz directly. busfreq will handle this
460db6ced   Bai Ping   MLK-13014 ARM: im...
73
74
  	 * when exit from low bus mode.
  	 */
40b06ddfa   Bai Ping   MLK-13096-02 cpuf...
75
  	if (old_freq == FREQ_24_MHZ && new_freq == FREQ_198_MHZ) {
460db6ced   Bai Ping   MLK-13014 ARM: im...
76
77
78
  		mutex_unlock(&set_cpufreq_lock);
  		return 0;
  	};
1dd538f07   Shawn Guo   cpufreq: add imx6...
79
  	rcu_read_lock();
5d4879cda   Nishanth Menon   PM / OPP: rename ...
80
  	opp = dev_pm_opp_find_freq_ceil(cpu_dev, &freq_hz);
1dd538f07   Shawn Guo   cpufreq: add imx6...
81
82
83
84
  	if (IS_ERR(opp)) {
  		rcu_read_unlock();
  		dev_err(cpu_dev, "failed to find OPP for %ld
  ", freq_hz);
62300a004   Bai Ping   MLK-9693 cpufreq:...
85
  		mutex_unlock(&set_cpufreq_lock);
1dd538f07   Shawn Guo   cpufreq: add imx6...
86
87
  		return PTR_ERR(opp);
  	}
5d4879cda   Nishanth Menon   PM / OPP: rename ...
88
  	volt = dev_pm_opp_get_voltage(opp);
1dd538f07   Shawn Guo   cpufreq: add imx6...
89
90
91
92
93
  	rcu_read_unlock();
  	volt_old = regulator_get_voltage(arm_reg);
  
  	dev_dbg(cpu_dev, "%u MHz, %ld mV --> %u MHz, %ld mV
  ",
d4019f0a9   Viresh Kumar   cpufreq: move fre...
94
95
  		old_freq / 1000, volt_old / 1000,
  		new_freq / 1000, volt / 1000);
80d1382e9   Bai Ping   MLK-9739 cpufreq:...
96
97
98
99
  	/*
  	 * CPU freq is increasing, so need to ensure
  	 * that bus frequency is increased too.
  	 */
1d733f828   Bai Ping   MLK-13133-02 cpuf...
100
101
102
103
  	if (low_power_run_support) {
  		if (old_freq == freq_table[0].frequency)
  			request_bus_freq(BUS_FREQ_HIGH);
  	} else if (old_freq <= FREQ_396_MHZ && new_freq > FREQ_396_MHZ) {
80d1382e9   Bai Ping   MLK-9739 cpufreq:...
104
  		request_bus_freq(BUS_FREQ_HIGH);
1d733f828   Bai Ping   MLK-13133-02 cpuf...
105
  	}
5a571c352   Viresh Kumar   cpufreq: imx6q: c...
106

1dd538f07   Shawn Guo   cpufreq: add imx6...
107
  	/* scaling up?  scale voltage before frequency */
d4019f0a9   Viresh Kumar   cpufreq: move fre...
108
  	if (new_freq > old_freq) {
22d0628a2   Anson Huang   cpufreq: imx6: re...
109
110
111
112
113
  		if (!IS_ERR(pu_reg)) {
  			ret = regulator_set_voltage_tol(pu_reg, imx6_soc_volt[index], 0);
  			if (ret) {
  				dev_err(cpu_dev, "failed to scale vddpu up: %d
  ", ret);
62300a004   Bai Ping   MLK-9693 cpufreq:...
114
  				mutex_unlock(&set_cpufreq_lock);
22d0628a2   Anson Huang   cpufreq: imx6: re...
115
116
  				return ret;
  			}
b4573d1d6   Anson Huang   cpufreq: imx6q: c...
117
118
119
120
121
  		}
  		ret = regulator_set_voltage_tol(soc_reg, imx6_soc_volt[index], 0);
  		if (ret) {
  			dev_err(cpu_dev, "failed to scale vddsoc up: %d
  ", ret);
62300a004   Bai Ping   MLK-9693 cpufreq:...
122
  			mutex_unlock(&set_cpufreq_lock);
b4573d1d6   Anson Huang   cpufreq: imx6q: c...
123
124
  			return ret;
  		}
1dd538f07   Shawn Guo   cpufreq: add imx6...
125
126
127
128
129
  		ret = regulator_set_voltage_tol(arm_reg, volt, 0);
  		if (ret) {
  			dev_err(cpu_dev,
  				"failed to scale vddarm up: %d
  ", ret);
62300a004   Bai Ping   MLK-9693 cpufreq:...
130
  			mutex_unlock(&set_cpufreq_lock);
d4019f0a9   Viresh Kumar   cpufreq: move fre...
131
  			return ret;
1dd538f07   Shawn Guo   cpufreq: add imx6...
132
  		}
1dd538f07   Shawn Guo   cpufreq: add imx6...
133
134
135
136
137
138
  	}
  
  	/*
  	 * The setpoints are selected per PLL/PDF frequencies, so we need to
  	 * reprogram PLL for frequency scaling.  The procedure of reprogramming
  	 * PLL1 is as below.
a35fc5a33   Bai Ping   cpufreq: imx: upd...
139
140
141
  	 * For i.MX6UL, it has a secondary clk mux, the cpu frequency change
  	 * flow is slightly different from other i.MX6 OSC.
  	 * The cpu frequeny change flow for i.MX6(except i.MX6UL) is as below:
1dd538f07   Shawn Guo   cpufreq: add imx6...
142
143
144
145
  	 *  - Enable pll2_pfd2_396m_clk and reparent pll1_sw_clk to it
  	 *  - Reprogram pll1_sys_clk and reparent pll1_sw_clk back to it
  	 *  - Disable pll2_pfd2_396m_clk
  	 */
c97fa8900   Octavian Purdila   MLK-14624 cpufreq...
146
147
  	if (of_machine_is_compatible("fsl,imx6ul") ||
  	    of_machine_is_compatible("fsl,imx6ull")) {
a35fc5a33   Bai Ping   cpufreq: imx: upd...
148
149
150
151
152
153
154
155
  		/*
  		 * When changing pll1_sw_clk's parent to pll1_sys_clk,
  		 * CPU may run at higher than 528MHz, this will lead to
  		 * the system unstable if the voltage is lower than the
  		 * voltage of 528MHz, so lower the CPU frequency to one
  		 * half before changing CPU frequency.
  		 */
  		clk_set_rate(arm_clk, (old_freq >> 1) * 1000);
1dd538f07   Shawn Guo   cpufreq: add imx6...
156
  		clk_set_parent(pll1_sw_clk, pll1_sys_clk);
a35fc5a33   Bai Ping   cpufreq: imx: upd...
157
158
159
160
161
162
  		if (freq_hz > clk_get_rate(pll2_pfd2_396m_clk))
  			clk_set_parent(secondary_sel_clk, pll2_bus_clk);
  		else
  			clk_set_parent(secondary_sel_clk, pll2_pfd2_396m_clk);
  		clk_set_parent(step_clk, secondary_sel_clk);
  		clk_set_parent(pll1_sw_clk, step_clk);
6babbe05d   Bai Ping   MLK-12623-01 cpuf...
163
164
165
166
  		if (freq_hz > clk_get_rate(pll2_bus_clk)) {
  			clk_set_rate(pll1, new_freq * 1000);
  			clk_set_parent(pll1_sw_clk, pll1_sys_clk);
  		}
a35fc5a33   Bai Ping   cpufreq: imx: upd...
167
168
169
170
  	} else {
  		clk_set_parent(step_clk, pll2_pfd2_396m_clk);
  		clk_set_parent(pll1_sw_clk, step_clk);
  		if (freq_hz > clk_get_rate(pll2_pfd2_396m_clk)) {
560cb1bc0   Octavian Purdila   MLK-14653 cpufreq...
171
172
173
174
175
  			/* Ensure that pll1_bypass is set back to
  			 * pll1. We have to do this first so that the
  			 * change rate done to pll1_sys_clk done below
  			 * can propagate up to pll1.
  			 */
6019bf6b9   Leonard Crestez   MLK-13843: Ensure...
176
  			clk_set_parent(pll1_bypass, pll1);
560cb1bc0   Octavian Purdila   MLK-14653 cpufreq...
177
  			clk_set_rate(pll1_sys_clk, new_freq * 1000);
a35fc5a33   Bai Ping   cpufreq: imx: upd...
178
  			clk_set_parent(pll1_sw_clk, pll1_sys_clk);
6019bf6b9   Leonard Crestez   MLK-13843: Ensure...
179
180
181
182
183
184
  		} else {
  			/*
  			 * Need to ensure that PLL1 is bypassed and enabled
  			 * before ARM-PODF is set.
  			 */
  			clk_set_parent(pll1_bypass, pll1_bypass_src);
a35fc5a33   Bai Ping   cpufreq: imx: upd...
185
  		}
1dd538f07   Shawn Guo   cpufreq: add imx6...
186
187
188
  	}
  
  	/* Ensure the arm clock divider is what we expect */
d4019f0a9   Viresh Kumar   cpufreq: move fre...
189
  	ret = clk_set_rate(arm_clk, new_freq * 1000);
1dd538f07   Shawn Guo   cpufreq: add imx6...
190
191
192
193
  	if (ret) {
  		dev_err(cpu_dev, "failed to set clock rate: %d
  ", ret);
  		regulator_set_voltage_tol(arm_reg, volt_old, 0);
62300a004   Bai Ping   MLK-9693 cpufreq:...
194
  		mutex_unlock(&set_cpufreq_lock);
d4019f0a9   Viresh Kumar   cpufreq: move fre...
195
  		return ret;
1dd538f07   Shawn Guo   cpufreq: add imx6...
196
197
198
  	}
  
  	/* scaling down?  scale voltage after frequency */
d4019f0a9   Viresh Kumar   cpufreq: move fre...
199
  	if (new_freq < old_freq) {
1dd538f07   Shawn Guo   cpufreq: add imx6...
200
  		ret = regulator_set_voltage_tol(arm_reg, volt, 0);
5a571c352   Viresh Kumar   cpufreq: imx6q: c...
201
  		if (ret) {
1dd538f07   Shawn Guo   cpufreq: add imx6...
202
203
204
  			dev_warn(cpu_dev,
  				 "failed to scale vddarm down: %d
  ", ret);
5a571c352   Viresh Kumar   cpufreq: imx6q: c...
205
206
  			ret = 0;
  		}
b4573d1d6   Anson Huang   cpufreq: imx6q: c...
207
208
209
210
211
212
  		ret = regulator_set_voltage_tol(soc_reg, imx6_soc_volt[index], 0);
  		if (ret) {
  			dev_warn(cpu_dev, "failed to scale vddsoc down: %d
  ", ret);
  			ret = 0;
  		}
22d0628a2   Anson Huang   cpufreq: imx6: re...
213
214
215
216
217
218
219
  		if (!IS_ERR(pu_reg)) {
  			ret = regulator_set_voltage_tol(pu_reg, imx6_soc_volt[index], 0);
  			if (ret) {
  				dev_warn(cpu_dev, "failed to scale vddpu down: %d
  ", ret);
  				ret = 0;
  			}
1dd538f07   Shawn Guo   cpufreq: add imx6...
220
221
  		}
  	}
80d1382e9   Bai Ping   MLK-9739 cpufreq:...
222
223
224
225
  	/*
  	 * If CPU is dropped to the lowest level, release the need
  	 * for a high bus frequency.
  	 */
1d733f828   Bai Ping   MLK-13133-02 cpuf...
226
227
228
229
  	if (low_power_run_support) {
  		if (new_freq == freq_table[0].frequency)
  			release_bus_freq(BUS_FREQ_HIGH);
  	} else if (old_freq > FREQ_396_MHZ && new_freq <= FREQ_396_MHZ) {
80d1382e9   Bai Ping   MLK-9739 cpufreq:...
230
  		release_bus_freq(BUS_FREQ_HIGH);
1d733f828   Bai Ping   MLK-13133-02 cpuf...
231
  	}
1dd538f07   Shawn Guo   cpufreq: add imx6...
232

62300a004   Bai Ping   MLK-9693 cpufreq:...
233
  	mutex_unlock(&set_cpufreq_lock);
d4019f0a9   Viresh Kumar   cpufreq: move fre...
234
  	return 0;
1dd538f07   Shawn Guo   cpufreq: add imx6...
235
236
237
238
  }
  
  static int imx6q_cpufreq_init(struct cpufreq_policy *policy)
  {
ef9f0601c   Bai Ping   MLK-9777 cpufreq:...
239
  	int ret;
652ed95d5   Viresh Kumar   cpufreq: introduc...
240
  	policy->clk = arm_clk;
ef9f0601c   Bai Ping   MLK-9777 cpufreq:...
241
242
243
244
245
246
247
248
  	policy->cur = clk_get_rate(arm_clk) / 1000;
  
  	ret = cpufreq_generic_init(policy, freq_table, transition_latency);
  	if (ret) {
  		dev_err(cpu_dev, "imx6 cpufreq init failed!
  ");
  		return ret;
  	}
1d733f828   Bai Ping   MLK-13133-02 cpuf...
249
  	if (low_power_run_support && policy->cur > freq_table[0].frequency) {
ef9f0601c   Bai Ping   MLK-9777 cpufreq:...
250
  		request_bus_freq(BUS_FREQ_HIGH);
1d733f828   Bai Ping   MLK-13133-02 cpuf...
251
252
253
  	} else if (policy->cur > FREQ_396_MHZ) {
  		request_bus_freq(BUS_FREQ_HIGH);
  	}
ef9f0601c   Bai Ping   MLK-9777 cpufreq:...
254
  	return 0;
1dd538f07   Shawn Guo   cpufreq: add imx6...
255
  }
1dd538f07   Shawn Guo   cpufreq: add imx6...
256
  static struct cpufreq_driver imx6q_cpufreq_driver = {
ae6b42713   Viresh Kumar   cpufreq: Mark ARM...
257
  	.flags = CPUFREQ_NEED_INITIAL_FREQ_CHECK,
4f6ba385e   Viresh Kumar   cpufreq: imx6q: U...
258
  	.verify = cpufreq_generic_frequency_table_verify,
9c0ebcf78   Viresh Kumar   cpufreq: Implemen...
259
  	.target_index = imx6q_set_target,
652ed95d5   Viresh Kumar   cpufreq: introduc...
260
  	.get = cpufreq_generic_get,
1dd538f07   Shawn Guo   cpufreq: add imx6...
261
  	.init = imx6q_cpufreq_init,
1dd538f07   Shawn Guo   cpufreq: add imx6...
262
  	.name = "imx6q-cpufreq",
4f6ba385e   Viresh Kumar   cpufreq: imx6q: U...
263
  	.attr = cpufreq_generic_attr,
1dd538f07   Shawn Guo   cpufreq: add imx6...
264
  };
62300a004   Bai Ping   MLK-9693 cpufreq:...
265
266
267
268
269
270
271
272
273
274
275
276
277
  static int imx6_cpufreq_pm_notify(struct notifier_block *nb,
  	unsigned long event, void *dummy)
  {
  	struct cpufreq_policy *data = cpufreq_cpu_get(0);
  	static u32 cpufreq_policy_min_pre_suspend;
  
  	/*
  	 * During suspend/resume, When cpufreq driver try to increase
  	 * voltage/freq, it needs to control I2C/SPI to communicate
  	 * with external PMIC to adjust voltage, but these I2C/SPI
  	 * devices may be already suspended, to avoid such scenario,
  	 * we just increase cpufreq to highest setpoint before suspend.
  	 */
39bf6af34   Bai Ping   MLK-11912 cpufreq...
278
279
  	if (!data)
  		return NOTIFY_BAD;
62300a004   Bai Ping   MLK-9693 cpufreq:...
280
281
282
283
  	switch (event) {
  	case PM_SUSPEND_PREPARE:
  		cpufreq_policy_min_pre_suspend = data->user_policy.min;
  		data->user_policy.min = data->user_policy.max;
1a4dd3071   Bai Ping   MLK-11252-02 cpuf...
284

6babbe05d   Bai Ping   MLK-12623-01 cpuf...
285
  		if (!IS_ERR(dc_reg) && !ignore_dc_reg)
1a4dd3071   Bai Ping   MLK-11252-02 cpuf...
286
  			regulator_set_voltage_tol(dc_reg, DC_VOLTAGE_MAX, 0);
62300a004   Bai Ping   MLK-9693 cpufreq:...
287
288
289
  		break;
  	case PM_POST_SUSPEND:
  		data->user_policy.min = cpufreq_policy_min_pre_suspend;
1a4dd3071   Bai Ping   MLK-11252-02 cpuf...
290

6babbe05d   Bai Ping   MLK-12623-01 cpuf...
291
  		if (!IS_ERR(dc_reg) && !ignore_dc_reg)
1a4dd3071   Bai Ping   MLK-11252-02 cpuf...
292
  			regulator_set_voltage_tol(dc_reg, DC_VOLTAGE_MIN, 0);
62300a004   Bai Ping   MLK-9693 cpufreq:...
293
294
295
296
297
298
  		break;
  	default:
  		break;
  	}
  
  	cpufreq_update_policy(0);
afcf68ffd   Bai Ping   MLK-12328 cpufreq...
299
  	cpufreq_cpu_put(data);
62300a004   Bai Ping   MLK-9693 cpufreq:...
300
301
302
303
304
305
306
  
  	return NOTIFY_OK;
  }
  
  static struct notifier_block imx6_cpufreq_pm_notifier = {
  	.notifier_call = imx6_cpufreq_pm_notify,
  };
1dd538f07   Shawn Guo   cpufreq: add imx6...
307
308
309
  static int imx6q_cpufreq_probe(struct platform_device *pdev)
  {
  	struct device_node *np;
47d43ba73   Nishanth Menon   PM / OPP: rename ...
310
  	struct dev_pm_opp *opp;
602a44634   Anson Huang   MLK-13119-3 cpufr...
311
  	struct clk *vpu_axi_podf;
1dd538f07   Shawn Guo   cpufreq: add imx6...
312
313
  	unsigned long min_volt, max_volt;
  	int num, ret;
b4573d1d6   Anson Huang   cpufreq: imx6q: c...
314
315
  	const struct property *prop;
  	const __be32 *val;
a3e09694d   Robin Gong   MLK-10123: cpufre...
316
  	u32 nr, j, i = 0;
602a44634   Anson Huang   MLK-13119-3 cpufr...
317
  	u32 vpu_axi_rate = 0;
1dd538f07   Shawn Guo   cpufreq: add imx6...
318

b494b48da   Sudeep KarkadaNagesha   cpufreq: imx6q-cp...
319
320
321
322
323
324
  	cpu_dev = get_cpu_device(0);
  	if (!cpu_dev) {
  		pr_err("failed to get cpu0 device
  ");
  		return -ENODEV;
  	}
1dd538f07   Shawn Guo   cpufreq: add imx6...
325

cdc58d602   Sudeep KarkadaNagesha   cpufreq: imx6q-cp...
326
  	np = of_node_get(cpu_dev->of_node);
1dd538f07   Shawn Guo   cpufreq: add imx6...
327
328
329
330
331
  	if (!np) {
  		dev_err(cpu_dev, "failed to find cpu0 node
  ");
  		return -ENOENT;
  	}
90ee80a6f   Leonard Crestez   MLK-14301: Revert...
332
333
334
335
336
337
338
339
  	arm_clk = clk_get(cpu_dev, "arm");
  	pll1_sys_clk = clk_get(cpu_dev, "pll1_sys");
  	pll1_sw_clk = clk_get(cpu_dev, "pll1_sw");
  	step_clk = clk_get(cpu_dev, "step");
  	pll2_pfd2_396m_clk = clk_get(cpu_dev, "pll2_pfd2_396m");
  	pll1 = clk_get(cpu_dev, "pll1");
  	pll1_bypass = clk_get(cpu_dev, "pll1_bypass");
  	pll1_bypass_src = clk_get(cpu_dev, "pll1_bypass_src");
1dd538f07   Shawn Guo   cpufreq: add imx6...
340
  	if (IS_ERR(arm_clk) || IS_ERR(pll1_sys_clk) || IS_ERR(pll1_sw_clk) ||
ced7bc8de   Bai Ping   MLK-11343-02 cpuf...
341
342
  	    IS_ERR(step_clk) || IS_ERR(pll2_pfd2_396m_clk) || IS_ERR(pll1) ||
  	    IS_ERR(pll1_bypass) || IS_ERR(pll1_bypass_src)) {
1dd538f07   Shawn Guo   cpufreq: add imx6...
343
344
345
  		dev_err(cpu_dev, "failed to get clocks
  ");
  		ret = -ENOENT;
90ee80a6f   Leonard Crestez   MLK-14301: Revert...
346
  		goto put_clk;
1dd538f07   Shawn Guo   cpufreq: add imx6...
347
  	}
c97fa8900   Octavian Purdila   MLK-14624 cpufreq...
348
349
  	if (of_machine_is_compatible("fsl,imx6ul") ||
  	    of_machine_is_compatible("fsl,imx6ull")) {
a35fc5a33   Bai Ping   cpufreq: imx: upd...
350
351
352
353
354
355
  		pll2_bus_clk = clk_get(cpu_dev, "pll2_bus");
  		secondary_sel_clk = clk_get(cpu_dev, "secondary_sel");
  		if (IS_ERR(pll2_bus_clk) || IS_ERR(secondary_sel_clk)) {
  			dev_err(cpu_dev, "failed to get clocks specific to imx6ul
  ");
  			ret = -ENOENT;
90ee80a6f   Leonard Crestez   MLK-14301: Revert...
356
  			goto put_clk;
a35fc5a33   Bai Ping   cpufreq: imx: upd...
357
358
  		}
  	}
90ee80a6f   Leonard Crestez   MLK-14301: Revert...
359
360
  	vpu_axi_podf = clk_get(cpu_dev, "vpu_axi_podf");
  	if (!IS_ERR(vpu_axi_podf)) {
602a44634   Anson Huang   MLK-13119-3 cpufr...
361
  		vpu_axi_rate = clk_get_rate(vpu_axi_podf);
90ee80a6f   Leonard Crestez   MLK-14301: Revert...
362
363
  		clk_put(vpu_axi_podf);
  	}
602a44634   Anson Huang   MLK-13119-3 cpufr...
364

90ee80a6f   Leonard Crestez   MLK-14301: Revert...
365
366
367
  	arm_reg = regulator_get(cpu_dev, "arm");
  	pu_reg = regulator_get_optional(cpu_dev, "pu");
  	soc_reg = regulator_get(cpu_dev, "soc");
22d0628a2   Anson Huang   cpufreq: imx6: re...
368
  	if (IS_ERR(arm_reg) || IS_ERR(soc_reg)) {
a544de724   Irina Tirdea   MLK-13793-1 cpufr...
369
370
371
372
373
374
375
  		ret = IS_ERR(arm_reg)?PTR_ERR(arm_reg):PTR_ERR(soc_reg);
  		if (ret == -EPROBE_DEFER)
  			dev_warn(cpu_dev, "regulators not ready, retry
  ");
  		else
  			dev_err(cpu_dev, "failed to get regulators: %d
  ", ret);
90ee80a6f   Leonard Crestez   MLK-14301: Revert...
376
  		goto put_reg;
1dd538f07   Shawn Guo   cpufreq: add imx6...
377
  	}
90ee80a6f   Leonard Crestez   MLK-14301: Revert...
378
  	dc_reg = regulator_get_optional(cpu_dev, "dc");
1a4dd3071   Bai Ping   MLK-11252-02 cpuf...
379

20b7cbe29   John Tobias   cpufreq: imx6q: a...
380
  	/*
fe3aca041   Robin Gong   MLK-10073-3 cpufr...
381
382
383
384
385
386
387
388
389
  	 * soc_reg sync  with arm_reg if arm shares the same regulator
  	 * with soc. Otherwise, regulator common framework will refuse to update
  	 * this consumer's voltage right now while another consumer voltage
  	 * still keep in old one. For example, imx6sx-sdb with pfuze200 in
  	 * ldo-bypass mode.
  	 */
  	of_property_read_u32(np, "fsl,arm-soc-shared", &i);
  	if (i == 1)
  		soc_reg = arm_reg;
1d733f828   Bai Ping   MLK-13133-02 cpuf...
390
391
392
  
  	/* On i.MX6ULL, check the 24MHz low power run mode support */
  	low_power_run_support = of_property_read_bool(np, "fsl,low-power-run");
fe3aca041   Robin Gong   MLK-10073-3 cpufr...
393
  	/*
20b7cbe29   John Tobias   cpufreq: imx6q: a...
394
395
396
397
  	 * We expect an OPP table supplied by platform.
  	 * Just, incase the platform did not supply the OPP
  	 * table, it will try to get it.
  	 */
5d4879cda   Nishanth Menon   PM / OPP: rename ...
398
  	num = dev_pm_opp_get_opp_count(cpu_dev);
1dd538f07   Shawn Guo   cpufreq: add imx6...
399
  	if (num < 0) {
8f8d37b25   Viresh Kumar   PM / OPP: Prefix ...
400
  		ret = dev_pm_opp_of_add_table(cpu_dev);
20b7cbe29   John Tobias   cpufreq: imx6q: a...
401
402
403
  		if (ret < 0) {
  			dev_err(cpu_dev, "failed to init OPP table: %d
  ", ret);
90ee80a6f   Leonard Crestez   MLK-14301: Revert...
404
  			goto put_reg;
20b7cbe29   John Tobias   cpufreq: imx6q: a...
405
  		}
cc87b8a8e   Viresh Kumar   imx6q: free OPP t...
406
407
  		/* Because we have added the OPPs here, we must free them */
  		free_opp = true;
20b7cbe29   John Tobias   cpufreq: imx6q: a...
408
409
410
411
412
  		num = dev_pm_opp_get_opp_count(cpu_dev);
  		if (num < 0) {
  			ret = num;
  			dev_err(cpu_dev, "no OPP table is found: %d
  ", ret);
cc87b8a8e   Viresh Kumar   imx6q: free OPP t...
413
  			goto out_free_opp;
20b7cbe29   John Tobias   cpufreq: imx6q: a...
414
  		}
1dd538f07   Shawn Guo   cpufreq: add imx6...
415
  	}
5d4879cda   Nishanth Menon   PM / OPP: rename ...
416
  	ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table);
1dd538f07   Shawn Guo   cpufreq: add imx6...
417
418
419
  	if (ret) {
  		dev_err(cpu_dev, "failed to init cpufreq table: %d
  ", ret);
90ee80a6f   Leonard Crestez   MLK-14301: Revert...
420
  		goto put_reg;
1dd538f07   Shawn Guo   cpufreq: add imx6...
421
  	}
6babbe05d   Bai Ping   MLK-12623-01 cpuf...
422
  	/*
90ff4d1c3   Bai Ping   MLK-14747 driver:...
423
  	 * On i.MX6UL/ULL EVK board, if the SOC is run in overide frequency,
6babbe05d   Bai Ping   MLK-12623-01 cpuf...
424
425
  	 * the dc_regulator voltage should not be touched.
  	 */
90ff4d1c3   Bai Ping   MLK-14747 driver:...
426
  	if (freq_table[num - 1].frequency > FREQ_528_MHZ)
6babbe05d   Bai Ping   MLK-12623-01 cpuf...
427
428
429
  		ignore_dc_reg = true;
  	if (!IS_ERR(dc_reg) && !ignore_dc_reg)
  		regulator_set_voltage_tol(dc_reg, DC_VOLTAGE_MIN, 0);
b4573d1d6   Anson Huang   cpufreq: imx6q: c...
430
  	/* Make imx6_soc_volt array's size same as arm opp number */
90ee80a6f   Leonard Crestez   MLK-14301: Revert...
431
  	imx6_soc_volt = kzalloc(sizeof(*imx6_soc_volt) * num, GFP_KERNEL);
b4573d1d6   Anson Huang   cpufreq: imx6q: c...
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
  	if (imx6_soc_volt == NULL) {
  		ret = -ENOMEM;
  		goto free_freq_table;
  	}
  
  	prop = of_find_property(np, "fsl,soc-operating-points", NULL);
  	if (!prop || !prop->value)
  		goto soc_opp_out;
  
  	/*
  	 * Each OPP is a set of tuples consisting of frequency and
  	 * voltage like <freq-kHz vol-uV>.
  	 */
  	nr = prop->length / sizeof(u32);
  	if (nr % 2 || (nr / 2) < num)
  		goto soc_opp_out;
  
  	for (j = 0; j < num; j++) {
  		val = prop->value;
  		for (i = 0; i < nr / 2; i++) {
  			unsigned long freq = be32_to_cpup(val++);
  			unsigned long volt = be32_to_cpup(val++);
  			if (freq_table[j].frequency == freq) {
  				imx6_soc_volt[soc_opp_count++] = volt;
40fb857f8   Anson Huang   MLK-10103-2 cpufr...
456
457
458
459
460
461
462
  #ifdef CONFIG_MX6_VPU_352M
  				if (freq == 792000) {
  					pr_info("increase SOC/PU voltage for VPU352MHz
  ");
  					imx6_soc_volt[soc_opp_count - 1] = 1250000;
  				}
  #endif
602a44634   Anson Huang   MLK-13119-3 cpufr...
463
464
465
466
467
468
469
470
  				if (vpu_axi_rate == 396000000) {
  					if (freq <= 996000) {
  						pr_info("increase SOC/PU voltage for VPU396MHz at %ld MHz
  ",
  							freq / 1000);
  						imx6_soc_volt[soc_opp_count - 1] = 1275000;
  					}
  				}
b4573d1d6   Anson Huang   cpufreq: imx6q: c...
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
  				break;
  			}
  		}
  	}
  
  soc_opp_out:
  	/* use fixed soc opp volt if no valid soc opp info found in dtb */
  	if (soc_opp_count != num) {
  		dev_warn(cpu_dev, "can NOT find valid fsl,soc-operating-points property in dtb, use default value!
  ");
  		for (j = 0; j < num; j++)
  			imx6_soc_volt[j] = PU_SOC_VOLTAGE_NORMAL;
  		if (freq_table[num - 1].frequency * 1000 == FREQ_1P2_GHZ)
  			imx6_soc_volt[num - 1] = PU_SOC_VOLTAGE_HIGH;
  	}
1dd538f07   Shawn Guo   cpufreq: add imx6...
486
487
488
489
  	if (of_property_read_u32(np, "clock-latency", &transition_latency))
  		transition_latency = CPUFREQ_ETERNAL;
  
  	/*
b4573d1d6   Anson Huang   cpufreq: imx6q: c...
490
491
492
493
494
495
  	 * Calculate the ramp time for max voltage change in the
  	 * VDDSOC and VDDPU regulators.
  	 */
  	ret = regulator_set_voltage_time(soc_reg, imx6_soc_volt[0], imx6_soc_volt[num - 1]);
  	if (ret > 0)
  		transition_latency += ret * 1000;
22d0628a2   Anson Huang   cpufreq: imx6: re...
496
497
498
499
500
  	if (!IS_ERR(pu_reg)) {
  		ret = regulator_set_voltage_time(pu_reg, imx6_soc_volt[0], imx6_soc_volt[num - 1]);
  		if (ret > 0)
  			transition_latency += ret * 1000;
  	}
b4573d1d6   Anson Huang   cpufreq: imx6q: c...
501
502
  
  	/*
1dd538f07   Shawn Guo   cpufreq: add imx6...
503
504
505
506
507
  	 * OPP is maintained in order of increasing frequency, and
  	 * freq_table initialised from OPP is therefore sorted in the
  	 * same order.
  	 */
  	rcu_read_lock();
5d4879cda   Nishanth Menon   PM / OPP: rename ...
508
  	opp = dev_pm_opp_find_freq_exact(cpu_dev,
1dd538f07   Shawn Guo   cpufreq: add imx6...
509
  				  freq_table[0].frequency * 1000, true);
5d4879cda   Nishanth Menon   PM / OPP: rename ...
510
511
  	min_volt = dev_pm_opp_get_voltage(opp);
  	opp = dev_pm_opp_find_freq_exact(cpu_dev,
1dd538f07   Shawn Guo   cpufreq: add imx6...
512
  				  freq_table[--num].frequency * 1000, true);
5d4879cda   Nishanth Menon   PM / OPP: rename ...
513
  	max_volt = dev_pm_opp_get_voltage(opp);
1dd538f07   Shawn Guo   cpufreq: add imx6...
514
515
516
517
  	rcu_read_unlock();
  	ret = regulator_set_voltage_time(arm_reg, min_volt, max_volt);
  	if (ret > 0)
  		transition_latency += ret * 1000;
62300a004   Bai Ping   MLK-9693 cpufreq:...
518
  	mutex_init(&set_cpufreq_lock);
1dd538f07   Shawn Guo   cpufreq: add imx6...
519
520
521
522
523
524
  	ret = cpufreq_register_driver(&imx6q_cpufreq_driver);
  	if (ret) {
  		dev_err(cpu_dev, "failed register driver: %d
  ", ret);
  		goto free_freq_table;
  	}
62300a004   Bai Ping   MLK-9693 cpufreq:...
525
  	register_pm_notifier(&imx6_cpufreq_pm_notifier);
1dd538f07   Shawn Guo   cpufreq: add imx6...
526
  	of_node_put(np);
a544de724   Irina Tirdea   MLK-13793-1 cpufr...
527
528
  	dev_info(cpu_dev, "Registered imx6q-cpufreq
  ");
1dd538f07   Shawn Guo   cpufreq: add imx6...
529
530
531
  	return 0;
  
  free_freq_table:
90ee80a6f   Leonard Crestez   MLK-14301: Revert...
532
  	kfree(imx6_soc_volt);
5d4879cda   Nishanth Menon   PM / OPP: rename ...
533
  	dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table);
cc87b8a8e   Viresh Kumar   imx6q: free OPP t...
534
535
  out_free_opp:
  	if (free_opp)
8f8d37b25   Viresh Kumar   PM / OPP: Prefix ...
536
  		dev_pm_opp_of_remove_table(cpu_dev);
90ee80a6f   Leonard Crestez   MLK-14301: Revert...
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
  put_reg:
  	if (!IS_ERR(arm_reg))
  		regulator_put(arm_reg);
  	if (!IS_ERR(pu_reg))
  		regulator_put(pu_reg);
  	if (!IS_ERR(soc_reg))
  		regulator_put(soc_reg);
  	if (!IS_ERR(dc_reg))
  		regulator_put(dc_reg);
  put_clk:
  	if (!IS_ERR(arm_clk))
  		clk_put(arm_clk);
  	if (!IS_ERR(pll1_sys_clk))
  		clk_put(pll1_sys_clk);
  	if (!IS_ERR(pll1_sw_clk))
  		clk_put(pll1_sw_clk);
  	if (!IS_ERR(step_clk))
  		clk_put(step_clk);
  	if (!IS_ERR(pll2_pfd2_396m_clk))
  		clk_put(pll2_pfd2_396m_clk);
  	if (!IS_ERR(pll1))
  		clk_put(pll1);
  	if (!IS_ERR(pll1_bypass))
  		clk_put(pll1_bypass);
  	if (!IS_ERR(pll1_bypass_src))
  		clk_put(pll1_bypass_src);
  	if (!IS_ERR(pll2_bus_clk))
  		clk_put(pll2_bus_clk);
  	if (!IS_ERR(secondary_sel_clk))
  		clk_put(secondary_sel_clk);
1dd538f07   Shawn Guo   cpufreq: add imx6...
567
568
569
570
571
572
573
  	of_node_put(np);
  	return ret;
  }
  
  static int imx6q_cpufreq_remove(struct platform_device *pdev)
  {
  	cpufreq_unregister_driver(&imx6q_cpufreq_driver);
90ee80a6f   Leonard Crestez   MLK-14301: Revert...
574
  	kfree(imx6_soc_volt);
5d4879cda   Nishanth Menon   PM / OPP: rename ...
575
  	dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table);
cc87b8a8e   Viresh Kumar   imx6q: free OPP t...
576
  	if (free_opp)
8f8d37b25   Viresh Kumar   PM / OPP: Prefix ...
577
  		dev_pm_opp_of_remove_table(cpu_dev);
90ee80a6f   Leonard Crestez   MLK-14301: Revert...
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
  	regulator_put(arm_reg);
  	if (!IS_ERR(pu_reg))
  		regulator_put(pu_reg);
  	regulator_put(soc_reg);
  	if (!IS_ERR(dc_reg))
  		regulator_put(dc_reg);
  	clk_put(arm_clk);
  	clk_put(pll1_sys_clk);
  	clk_put(pll1_sw_clk);
  	clk_put(step_clk);
  	clk_put(pll1);
  	clk_put(pll1_bypass);
  	clk_put(pll1_bypass_src);
  	clk_put(pll2_pfd2_396m_clk);
  	clk_put(pll2_bus_clk);
  	clk_put(secondary_sel_clk);
1dd538f07   Shawn Guo   cpufreq: add imx6...
594
595
596
597
598
599
600
  
  	return 0;
  }
  
  static struct platform_driver imx6q_cpufreq_platdrv = {
  	.driver = {
  		.name	= "imx6q-cpufreq",
1dd538f07   Shawn Guo   cpufreq: add imx6...
601
602
603
604
605
606
607
608
609
  	},
  	.probe		= imx6q_cpufreq_probe,
  	.remove		= imx6q_cpufreq_remove,
  };
  module_platform_driver(imx6q_cpufreq_platdrv);
  
  MODULE_AUTHOR("Shawn Guo <shawn.guo@linaro.org>");
  MODULE_DESCRIPTION("Freescale i.MX6Q cpufreq driver");
  MODULE_LICENSE("GPL");