blob: edfaf90a82878055c6933211611faffbc0c0ebfc [file] [log] [blame]
Aravind Venkateswaran69605a92013-03-07 14:12:16 -08001/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#include <linux/kernel.h>
14#include <linux/io.h>
15#include <linux/err.h>
16#include <linux/delay.h>
17#include <linux/string.h>
18#include <linux/iopoll.h>
19#include <linux/clk.h>
20
21#include <asm/processor.h>
22#include <mach/msm_iomap.h>
23#include <mach/clk-provider.h>
24
25#include "clock-mdss-8226.h"
26
27#define REG_R(addr) readl_relaxed(addr)
28#define REG_W(data, addr) writel_relaxed(data, addr)
29
30#define GDSC_PHYS 0xFD8C2304
31#define GDSC_SIZE 0x4
32
33#define DSI_PHY_PHYS 0xFD922800
34#define DSI_PHY_SIZE 0x00000800
35
36static unsigned char *mdss_dsi_base;
37static unsigned char *gdsc_base;
38static int pll_byte_clk_rate;
39static int pll_pclk_rate;
40static int pll_initialized;
41static struct clk *mdss_dsi_ahb_clk;
42static unsigned long dsi_pll_rate;
43
44void __init mdss_clk_ctrl_pre_init(struct clk *ahb_clk)
45{
46 BUG_ON(ahb_clk == NULL);
47
48 gdsc_base = ioremap(GDSC_PHYS, GDSC_SIZE);
49 if (!gdsc_base)
50 pr_err("%s: unable to remap gdsc base", __func__);
51
52 mdss_dsi_base = ioremap(DSI_PHY_PHYS, DSI_PHY_SIZE);
53 if (!mdss_dsi_base)
54 pr_err("%s: unable to remap dsi base", __func__);
55
56 mdss_dsi_ahb_clk = ahb_clk;
57}
58
59#define PLL_POLL_MAX_READS 10
60#define PLL_POLL_TIMEOUT_US 50
61
62static int mdss_gdsc_enabled(void)
63{
64 if (!gdsc_base)
65 return 0;
66
67 return !!(readl_relaxed(gdsc_base) & BIT(31));
68}
69
70static int mdss_dsi_check_pll_lock(void)
71{
72 u32 status;
73
Aravind Venkateswaran69605a92013-03-07 14:12:16 -080074 /* poll for PLL ready status */
75 if (readl_poll_timeout_noirq((mdss_dsi_base + 0x02c0),
76 status,
77 ((status & BIT(0)) == 1),
78 PLL_POLL_MAX_READS, PLL_POLL_TIMEOUT_US)) {
79 pr_err("%s: DSI PLL status=%x failed to Lock\n",
80 __func__, status);
81 pll_initialized = 0;
82 } else {
83 pll_initialized = 1;
84 }
Aravind Venkateswaran69605a92013-03-07 14:12:16 -080085
86 return pll_initialized;
87}
88
89static long mdss_dsi_pll_byte_round_rate(struct clk *c, unsigned long rate)
90{
91 if (pll_initialized) {
92 return pll_byte_clk_rate;
93 } else {
94 pr_err("%s: DSI PLL not configured\n", __func__);
95 return -EINVAL;
96 }
97}
98
99static long mdss_dsi_pll_pixel_round_rate(struct clk *c, unsigned long rate)
100{
101 if (pll_initialized) {
102 return pll_pclk_rate;
103 } else {
104 pr_err("%s: Configure Byte clk first\n", __func__);
105 return -EINVAL;
106 }
107}
108
109static int mdss_dsi_pll_pixel_set_rate(struct clk *c, unsigned long rate)
110{
111 if (pll_initialized) {
Chandan Uddaraju6316b502013-03-25 18:42:04 -0700112 pll_pclk_rate = rate;
Aravind Venkateswaran69605a92013-03-07 14:12:16 -0800113 pr_debug("%s: pll_pclk_rate=%d\n", __func__, pll_pclk_rate);
114 return 0;
115 } else {
116 pr_err("%s: Configure Byte clk first\n", __func__);
117 return -EINVAL;
118 }
119}
120
121static int __mdss_dsi_pll_byte_set_rate(struct clk *c, unsigned long rate)
122{
123 pr_debug("%s: rate=%ld\n", __func__, rate);
124
125 if (pll_initialized)
126 return 0;
127
128 REG_W(0x70, mdss_dsi_base + 0x0230); /* LPFC1 CFG */
129 REG_W(0x08, mdss_dsi_base + 0x022c); /* LPFR CFG */
130 REG_W(0x02, mdss_dsi_base + 0x0210); /* VREG CFG */
131 REG_W(0x00, mdss_dsi_base + 0x0204); /* postDiv1 */
132 REG_W(0x01, mdss_dsi_base + 0x0200); /* REFCLK CFG */
133 REG_W(0x03, mdss_dsi_base + 0x0224); /* postDiv2 */
134 REG_W(0x00, mdss_dsi_base + 0x0238); /* SDM CFG0 */
135 REG_W(0x0b, mdss_dsi_base + 0x023c); /* SDM CFG1 */
136 REG_W(0x00, mdss_dsi_base + 0x0240); /* SDM CFG2 */
137 REG_W(0x6c, mdss_dsi_base + 0x0244); /* SDM CFG3 */
138 REG_W(0x02, mdss_dsi_base + 0x0208); /* ChgPump */
139 REG_W(0x31, mdss_dsi_base + 0x020c); /* VCOLPF CFG */
140 REG_W(0x15, mdss_dsi_base + 0x0234); /* LPFC2 CFG */
141
142 REG_W(0x30, mdss_dsi_base + 0x0284); /* CAL CFG6 */
143 REG_W(0x00, mdss_dsi_base + 0x0288); /* CAL CFG7 */
144 REG_W(0x60, mdss_dsi_base + 0x028c); /* CAL CFG8 */
145 REG_W(0x00, mdss_dsi_base + 0x0290); /* CAL CFG9 */
146 REG_W(0xdd, mdss_dsi_base + 0x0294); /* CAL CFG10 */
147 REG_W(0x01, mdss_dsi_base + 0x0298); /* CAL CFG11 */
148
Chandan Uddaraju6316b502013-03-25 18:42:04 -0700149 REG_W(0x05, mdss_dsi_base + 0x0228); /* postDiv3 */
Aravind Venkateswaran69605a92013-03-07 14:12:16 -0800150 REG_W(0x2b, mdss_dsi_base + 0x0278); /* Cal CFG3 */
151 REG_W(0x66, mdss_dsi_base + 0x027c); /* Cal CFG4 */
152 REG_W(0x05, mdss_dsi_base + 0x0264); /* LKDET CFG2 */
153 REG_W(0x00, mdss_dsi_base + 0x0248); /* SDM CFG4 */
154 REG_W(0x00, mdss_dsi_base + 0x0214); /* PWRGEN CFG */
155 REG_W(0x0a, mdss_dsi_base + 0x026c); /* CAL CFG0 */
156 REG_W(0x20, mdss_dsi_base + 0x029c); /* EFUSE CFG */
157
158 dsi_pll_rate = rate;
159 pll_byte_clk_rate = rate;
160
161 pr_debug("%s: PLL initialized. bcl=%d\n", __func__, pll_byte_clk_rate);
162 pll_initialized = 1;
163
164 return 0;
165}
166
167static int mdss_dsi_pll_byte_set_rate(struct clk *c, unsigned long rate)
168{
169 int ret;
170
171 clk_prepare_enable(mdss_dsi_ahb_clk);
172 ret = __mdss_dsi_pll_byte_set_rate(c, rate);
173 clk_disable_unprepare(mdss_dsi_ahb_clk);
174
175 return ret;
176}
177
Aravind Venkateswaran69605a92013-03-07 14:12:16 -0800178static void mdss_dsi_uniphy_pll_sw_reset(void)
179{
Aravind Venkateswaranf0152c62013-04-09 18:19:35 -0700180 /*
181 * Add hardware recommended delays after toggling the
182 * software reset bit off and back on.
183 */
Aravind Venkateswaran69605a92013-03-07 14:12:16 -0800184 REG_W(0x01, mdss_dsi_base + 0x0268); /* PLL TEST CFG */
Aravind Venkateswaranf0152c62013-04-09 18:19:35 -0700185 udelay(300);
Aravind Venkateswaran69605a92013-03-07 14:12:16 -0800186 REG_W(0x00, mdss_dsi_base + 0x0268); /* PLL TEST CFG */
Aravind Venkateswaranf0152c62013-04-09 18:19:35 -0700187 udelay(300);
188}
189
190static void mdss_dsi_pll_enable_casem(void)
191{
192 int i;
193
194 /*
195 * Add hardware recommended delays between register writes for
196 * the updates to take effect. These delays are necessary for the
197 * PLL to successfully lock.
198 */
199 REG_W(0x01, mdss_dsi_base + 0x0220); /* GLB CFG */
200 udelay(200);
201 REG_W(0x05, mdss_dsi_base + 0x0220); /* GLB CFG */
202 udelay(200);
203 REG_W(0x0f, mdss_dsi_base + 0x0220); /* GLB CFG */
204 udelay(1000);
205
206 for (i = 0; (i < 3) && !mdss_dsi_check_pll_lock(); i++) {
207 REG_W(0x07, mdss_dsi_base + 0x0220); /* GLB CFG */
208 udelay(1);
209
210 REG_W(0x0f, mdss_dsi_base + 0x0220); /* GLB CFG */
211 udelay(1000);
212 }
213
214 if (pll_initialized)
215 pr_debug("%s: PLL Locked after %d attempts\n", __func__, i);
216 else
217 pr_debug("%s: PLL failed to lock\n", __func__);
218}
219
220static void mdss_dsi_pll_enable_casef1(void)
221{
222 /*
223 * Add hardware recommended delays between register writes for
224 * the updates to take effect. These delays are necessary for the
225 * PLL to successfully lock.
226 */
227 REG_W(0x01, mdss_dsi_base + 0x0220); /* GLB CFG */
228 udelay(200);
229 REG_W(0x05, mdss_dsi_base + 0x0220); /* GLB CFG */
230 udelay(200);
231 REG_W(0x0f, mdss_dsi_base + 0x0220); /* GLB CFG */
232 udelay(200);
233 REG_W(0x0d, mdss_dsi_base + 0x0220); /* GLB CFG */
234 udelay(200);
235 REG_W(0x0f, mdss_dsi_base + 0x0220); /* GLB CFG */
236 udelay(1000);
237
238 if (mdss_dsi_check_pll_lock())
239 pr_debug("%s: PLL Locked\n", __func__);
240 else
241 pr_debug("%s: PLL failed to lock\n", __func__);
242}
243
244static void mdss_dsi_pll_enable_cased(void)
245{
246 /*
247 * Add hardware recommended delays between register writes for
248 * the updates to take effect. These delays are necessary for the
249 * PLL to successfully lock.
250 */
251 REG_W(0x01, mdss_dsi_base + 0x0220); /* GLB CFG */
Aravind Venkateswaran69605a92013-03-07 14:12:16 -0800252 udelay(1);
Aravind Venkateswaranf0152c62013-04-09 18:19:35 -0700253 REG_W(0x05, mdss_dsi_base + 0x0220); /* GLB CFG */
254 udelay(1);
255 REG_W(0x07, mdss_dsi_base + 0x0220); /* GLB CFG */
256 udelay(1);
257 REG_W(0x05, mdss_dsi_base + 0x0220); /* GLB CFG */
258 udelay(1);
259 REG_W(0x07, mdss_dsi_base + 0x0220); /* GLB CFG */
260 udelay(1);
261 REG_W(0x0f, mdss_dsi_base + 0x0220); /* GLB CFG */
262 udelay(1);
263
264 if (mdss_dsi_check_pll_lock())
265 pr_debug("%s: PLL Locked\n", __func__);
266 else
267 pr_debug("%s: PLL failed to lock\n", __func__);
268}
269
270static void mdss_dsi_pll_enable_casec(void)
271{
272 /*
273 * Add hardware recommended delays between register writes for
274 * the updates to take effect. These delays are necessary for the
275 * PLL to successfully lock.
276 */
277 REG_W(0x01, mdss_dsi_base + 0x0220); /* GLB CFG */
278 udelay(200);
279 REG_W(0x05, mdss_dsi_base + 0x0220); /* GLB CFG */
280 udelay(200);
281 REG_W(0x0f, mdss_dsi_base + 0x0220); /* GLB CFG */
282 udelay(1000);
283
284 if (mdss_dsi_check_pll_lock())
285 pr_debug("%s: PLL Locked\n", __func__);
286 else
287 pr_debug("%s: PLL failed to lock\n", __func__);
288}
289
290static void mdss_dsi_pll_enable_casee(void)
291{
292 /*
293 * Add hardware recommended delays between register writes for
294 * the updates to take effect. These delays are necessary for the
295 * PLL to successfully lock.
296 */
297 REG_W(0x01, mdss_dsi_base + 0x0220); /* GLB CFG */
298 udelay(200);
299 REG_W(0x05, mdss_dsi_base + 0x0220); /* GLB CFG */
300 udelay(200);
301 REG_W(0x0d, mdss_dsi_base + 0x0220); /* GLB CFG */
302 REG_W(0x0f, mdss_dsi_base + 0x0220); /* GLB CFG */
303 udelay(1000);
304
305 if (mdss_dsi_check_pll_lock())
306 pr_debug("%s: PLL Locked\n", __func__);
307 else
308 pr_debug("%s: PLL failed to lock\n", __func__);
Aravind Venkateswaran69605a92013-03-07 14:12:16 -0800309}
310
311static int __mdss_dsi_pll_enable(struct clk *c)
312{
Aravind Venkateswaran69605a92013-03-07 14:12:16 -0800313 if (!pll_initialized) {
314 if (dsi_pll_rate)
315 __mdss_dsi_pll_byte_set_rate(c, dsi_pll_rate);
316 else
317 pr_err("%s: Calling clk_en before set_rate\n",
318 __func__);
319 }
320
Aravind Venkateswaranf0152c62013-04-09 18:19:35 -0700321 /*
322 * Try all PLL power-up sequences one-by-one until
323 * PLL lock is detected
324 */
Aravind Venkateswaran69605a92013-03-07 14:12:16 -0800325 mdss_dsi_uniphy_pll_sw_reset();
Aravind Venkateswaranf0152c62013-04-09 18:19:35 -0700326 mdss_dsi_pll_enable_casem();
327 if (pll_initialized)
328 goto pll_locked;
Aravind Venkateswaran69605a92013-03-07 14:12:16 -0800329
Aravind Venkateswaranf0152c62013-04-09 18:19:35 -0700330 mdss_dsi_uniphy_pll_sw_reset();
331 mdss_dsi_pll_enable_cased();
332 if (pll_initialized)
333 goto pll_locked;
Aravind Venkateswaran69605a92013-03-07 14:12:16 -0800334
Aravind Venkateswaranf0152c62013-04-09 18:19:35 -0700335 mdss_dsi_uniphy_pll_sw_reset();
336 mdss_dsi_pll_enable_cased();
337 if (pll_initialized)
338 goto pll_locked;
Aravind Venkateswaran69605a92013-03-07 14:12:16 -0800339
Aravind Venkateswaranf0152c62013-04-09 18:19:35 -0700340 mdss_dsi_uniphy_pll_sw_reset();
341 mdss_dsi_pll_enable_casef1();
342 if (pll_initialized)
343 goto pll_locked;
Aravind Venkateswaran69605a92013-03-07 14:12:16 -0800344
Aravind Venkateswaranf0152c62013-04-09 18:19:35 -0700345 mdss_dsi_uniphy_pll_sw_reset();
346 mdss_dsi_pll_enable_casec();
347 if (pll_initialized)
348 goto pll_locked;
349
350 mdss_dsi_uniphy_pll_sw_reset();
351 mdss_dsi_pll_enable_casee();
352 if (pll_initialized)
353 goto pll_locked;
354
355 pr_err("%s: DSI PLL failed to Lock\n", __func__);
356 return -EINVAL;
357
358pll_locked:
359 pr_debug("%s: PLL Lock success\n", __func__);
Aravind Venkateswaran69605a92013-03-07 14:12:16 -0800360
361 return 0;
362}
363
364static void __mdss_dsi_pll_disable(void)
365{
366 writel_relaxed(0x00, mdss_dsi_base + 0x0220); /* GLB CFG */
Aravind Venkateswaranf0152c62013-04-09 18:19:35 -0700367 pr_debug("%s: PLL disabled\n", __func__);
Aravind Venkateswaran69605a92013-03-07 14:12:16 -0800368 pll_initialized = 0;
369}
370
371static DEFINE_SPINLOCK(dsipll_lock);
372static int dsipll_refcount;
373
374static void mdss_dsi_pll_disable(struct clk *c)
375{
376 unsigned long flags;
377
378 spin_lock_irqsave(&dsipll_lock, flags);
379 if (WARN(dsipll_refcount == 0, "DSI PLL clock is unbalanced"))
380 goto out;
381 if (dsipll_refcount == 1)
382 __mdss_dsi_pll_disable();
383 dsipll_refcount--;
384out:
385 spin_unlock_irqrestore(&dsipll_lock, flags);
386}
387
388static int mdss_dsi_pll_enable(struct clk *c)
389{
390 unsigned long flags;
391 int ret = 0;
392
393 spin_lock_irqsave(&dsipll_lock, flags);
394 if (dsipll_refcount == 0) {
395 ret = __mdss_dsi_pll_enable(c);
396 if (ret < 0)
397 goto out;
398 }
399 dsipll_refcount++;
400out:
401 spin_unlock_irqrestore(&dsipll_lock, flags);
402 return ret;
403}
404
405/* todo: Adjust these values appropriately */
406static enum handoff mdss_dsi_pll_byte_handoff(struct clk *c)
407{
Aravind Venkateswaranf0152c62013-04-09 18:19:35 -0700408 if (mdss_gdsc_enabled()) {
409 clk_prepare_enable(mdss_dsi_ahb_clk);
410 if (mdss_dsi_check_pll_lock()) {
411 c->rate = 59000000;
412 dsi_pll_rate = 59000000;
413 pll_byte_clk_rate = 59000000;
414 pll_pclk_rate = 117000000;
415 dsipll_refcount++;
416 return HANDOFF_ENABLED_CLK;
417 }
418 clk_disable_unprepare(mdss_dsi_ahb_clk);
Aravind Venkateswaran69605a92013-03-07 14:12:16 -0800419 }
420
421 return HANDOFF_DISABLED_CLK;
422}
423
424/* todo: Adjust these values appropriately */
425static enum handoff mdss_dsi_pll_pixel_handoff(struct clk *c)
426{
Aravind Venkateswaranf0152c62013-04-09 18:19:35 -0700427 if (mdss_gdsc_enabled()) {
428 clk_prepare_enable(mdss_dsi_ahb_clk);
429 if (mdss_dsi_check_pll_lock()) {
430 c->rate = 117000000;
431 dsipll_refcount++;
432 return HANDOFF_ENABLED_CLK;
433 }
434 clk_disable_unprepare(mdss_dsi_ahb_clk);
Aravind Venkateswaran69605a92013-03-07 14:12:16 -0800435 }
436
437 return HANDOFF_DISABLED_CLK;
438}
439
440struct clk_ops clk_ops_dsi_pixel_pll = {
441 .enable = mdss_dsi_pll_enable,
442 .disable = mdss_dsi_pll_disable,
443 .set_rate = mdss_dsi_pll_pixel_set_rate,
444 .round_rate = mdss_dsi_pll_pixel_round_rate,
445 .handoff = mdss_dsi_pll_pixel_handoff,
446};
447
448struct clk_ops clk_ops_dsi_byte_pll = {
449 .enable = mdss_dsi_pll_enable,
450 .disable = mdss_dsi_pll_disable,
451 .set_rate = mdss_dsi_pll_byte_set_rate,
452 .round_rate = mdss_dsi_pll_byte_round_rate,
453 .handoff = mdss_dsi_pll_byte_handoff,
454};