blob: f2c8d5840edf118a9c5cdeed4b2d31fbf8a493aa [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
74 clk_prepare_enable(mdss_dsi_ahb_clk);
75 /* poll for PLL ready status */
76 if (readl_poll_timeout_noirq((mdss_dsi_base + 0x02c0),
77 status,
78 ((status & BIT(0)) == 1),
79 PLL_POLL_MAX_READS, PLL_POLL_TIMEOUT_US)) {
80 pr_err("%s: DSI PLL status=%x failed to Lock\n",
81 __func__, status);
82 pll_initialized = 0;
83 } else {
84 pll_initialized = 1;
85 }
86 clk_disable_unprepare(mdss_dsi_ahb_clk);
87
88 return pll_initialized;
89}
90
91static long mdss_dsi_pll_byte_round_rate(struct clk *c, unsigned long rate)
92{
93 if (pll_initialized) {
94 return pll_byte_clk_rate;
95 } else {
96 pr_err("%s: DSI PLL not configured\n", __func__);
97 return -EINVAL;
98 }
99}
100
101static long mdss_dsi_pll_pixel_round_rate(struct clk *c, unsigned long rate)
102{
103 if (pll_initialized) {
104 return pll_pclk_rate;
105 } else {
106 pr_err("%s: Configure Byte clk first\n", __func__);
107 return -EINVAL;
108 }
109}
110
111static int mdss_dsi_pll_pixel_set_rate(struct clk *c, unsigned long rate)
112{
113 if (pll_initialized) {
Chandan Uddaraju6316b502013-03-25 18:42:04 -0700114 pll_pclk_rate = rate;
Aravind Venkateswaran69605a92013-03-07 14:12:16 -0800115 pr_debug("%s: pll_pclk_rate=%d\n", __func__, pll_pclk_rate);
116 return 0;
117 } else {
118 pr_err("%s: Configure Byte clk first\n", __func__);
119 return -EINVAL;
120 }
121}
122
123static int __mdss_dsi_pll_byte_set_rate(struct clk *c, unsigned long rate)
124{
125 pr_debug("%s: rate=%ld\n", __func__, rate);
126
127 if (pll_initialized)
128 return 0;
129
130 REG_W(0x70, mdss_dsi_base + 0x0230); /* LPFC1 CFG */
131 REG_W(0x08, mdss_dsi_base + 0x022c); /* LPFR CFG */
132 REG_W(0x02, mdss_dsi_base + 0x0210); /* VREG CFG */
133 REG_W(0x00, mdss_dsi_base + 0x0204); /* postDiv1 */
134 REG_W(0x01, mdss_dsi_base + 0x0200); /* REFCLK CFG */
135 REG_W(0x03, mdss_dsi_base + 0x0224); /* postDiv2 */
136 REG_W(0x00, mdss_dsi_base + 0x0238); /* SDM CFG0 */
137 REG_W(0x0b, mdss_dsi_base + 0x023c); /* SDM CFG1 */
138 REG_W(0x00, mdss_dsi_base + 0x0240); /* SDM CFG2 */
139 REG_W(0x6c, mdss_dsi_base + 0x0244); /* SDM CFG3 */
140 REG_W(0x02, mdss_dsi_base + 0x0208); /* ChgPump */
141 REG_W(0x31, mdss_dsi_base + 0x020c); /* VCOLPF CFG */
142 REG_W(0x15, mdss_dsi_base + 0x0234); /* LPFC2 CFG */
143
144 REG_W(0x30, mdss_dsi_base + 0x0284); /* CAL CFG6 */
145 REG_W(0x00, mdss_dsi_base + 0x0288); /* CAL CFG7 */
146 REG_W(0x60, mdss_dsi_base + 0x028c); /* CAL CFG8 */
147 REG_W(0x00, mdss_dsi_base + 0x0290); /* CAL CFG9 */
148 REG_W(0xdd, mdss_dsi_base + 0x0294); /* CAL CFG10 */
149 REG_W(0x01, mdss_dsi_base + 0x0298); /* CAL CFG11 */
150
Chandan Uddaraju6316b502013-03-25 18:42:04 -0700151 REG_W(0x05, mdss_dsi_base + 0x0228); /* postDiv3 */
Aravind Venkateswaran69605a92013-03-07 14:12:16 -0800152 REG_W(0x2b, mdss_dsi_base + 0x0278); /* Cal CFG3 */
153 REG_W(0x66, mdss_dsi_base + 0x027c); /* Cal CFG4 */
154 REG_W(0x05, mdss_dsi_base + 0x0264); /* LKDET CFG2 */
155 REG_W(0x00, mdss_dsi_base + 0x0248); /* SDM CFG4 */
156 REG_W(0x00, mdss_dsi_base + 0x0214); /* PWRGEN CFG */
157 REG_W(0x0a, mdss_dsi_base + 0x026c); /* CAL CFG0 */
158 REG_W(0x20, mdss_dsi_base + 0x029c); /* EFUSE CFG */
159
160 dsi_pll_rate = rate;
161 pll_byte_clk_rate = rate;
162
163 pr_debug("%s: PLL initialized. bcl=%d\n", __func__, pll_byte_clk_rate);
164 pll_initialized = 1;
165
166 return 0;
167}
168
169static int mdss_dsi_pll_byte_set_rate(struct clk *c, unsigned long rate)
170{
171 int ret;
172
173 clk_prepare_enable(mdss_dsi_ahb_clk);
174 ret = __mdss_dsi_pll_byte_set_rate(c, rate);
175 clk_disable_unprepare(mdss_dsi_ahb_clk);
176
177 return ret;
178}
179
180static void mdss_dsi_uniphy_pll_lock_detect_setting(void)
181{
182 REG_W(0x04, mdss_dsi_base + 0x0264); /* LKDetect CFG2 */
183 udelay(100);
184 REG_W(0x05, mdss_dsi_base + 0x0264); /* LKDetect CFG2 */
185 udelay(500);
186}
187
188static void mdss_dsi_uniphy_pll_sw_reset(void)
189{
190 REG_W(0x01, mdss_dsi_base + 0x0268); /* PLL TEST CFG */
191 udelay(1);
192 REG_W(0x00, mdss_dsi_base + 0x0268); /* PLL TEST CFG */
193 udelay(1);
194}
195
196static int __mdss_dsi_pll_enable(struct clk *c)
197{
198 u32 status;
199 u32 max_reads, timeout_us;
200 int i;
201
202 if (!pll_initialized) {
203 if (dsi_pll_rate)
204 __mdss_dsi_pll_byte_set_rate(c, dsi_pll_rate);
205 else
206 pr_err("%s: Calling clk_en before set_rate\n",
207 __func__);
208 }
209
210 mdss_dsi_uniphy_pll_sw_reset();
211 /* PLL power up */
212 /* Add HW recommended delay between
213 register writes for the update to propagate */
214 REG_W(0x01, mdss_dsi_base + 0x0220); /* GLB CFG */
215 udelay(20);
216 REG_W(0x05, mdss_dsi_base + 0x0220); /* GLB CFG */
217 udelay(100);
218 REG_W(0x0d, mdss_dsi_base + 0x0220); /* GLB CFG */
219 udelay(20);
220 REG_W(0x0f, mdss_dsi_base + 0x0220); /* GLB CFG */
221 udelay(200);
222
223 for (i = 0; i < 3; i++) {
224 mdss_dsi_uniphy_pll_lock_detect_setting();
225 /* poll for PLL ready status */
226 max_reads = 5;
227 timeout_us = 100;
228 if (readl_poll_timeout_noirq((mdss_dsi_base + 0x02c0),
229 status,
230 ((status & 0x01) == 1),
231 max_reads, timeout_us)) {
232 pr_debug("%s: DSI PLL status=%x failed to Lock\n",
233 __func__, status);
234 pr_debug("%s:Trying to power UP PLL again\n",
235 __func__);
236 } else
237 break;
238
239 mdss_dsi_uniphy_pll_sw_reset();
240 udelay(1000);
241 /* Add HW recommended delay between
242 register writes for the update to propagate */
243 REG_W(0x01, mdss_dsi_base + 0x0220); /* GLB CFG */
244 udelay(20);
245 REG_W(0x05, mdss_dsi_base + 0x0220); /* GLB CFG */
246 udelay(100);
247 REG_W(0x0d, mdss_dsi_base + 0x0220); /* GLB CFG */
248 udelay(20);
249 REG_W(0x0f, mdss_dsi_base + 0x0220); /* GLB CFG */
250 udelay(200);
251 }
252
253 if ((status & 0x01) != 1) {
254 pr_err("%s: DSI PLL status=%x failed to Lock\n",
255 __func__, status);
256 return -EINVAL;
257 }
258
259 pr_debug("%s: **** PLL Lock success\n", __func__);
260
261 return 0;
262}
263
264static void __mdss_dsi_pll_disable(void)
265{
266 writel_relaxed(0x00, mdss_dsi_base + 0x0220); /* GLB CFG */
267 pr_debug("%s: **** disable pll Initialize\n", __func__);
268 pll_initialized = 0;
269}
270
271static DEFINE_SPINLOCK(dsipll_lock);
272static int dsipll_refcount;
273
274static void mdss_dsi_pll_disable(struct clk *c)
275{
276 unsigned long flags;
277
278 spin_lock_irqsave(&dsipll_lock, flags);
279 if (WARN(dsipll_refcount == 0, "DSI PLL clock is unbalanced"))
280 goto out;
281 if (dsipll_refcount == 1)
282 __mdss_dsi_pll_disable();
283 dsipll_refcount--;
284out:
285 spin_unlock_irqrestore(&dsipll_lock, flags);
286}
287
288static int mdss_dsi_pll_enable(struct clk *c)
289{
290 unsigned long flags;
291 int ret = 0;
292
293 spin_lock_irqsave(&dsipll_lock, flags);
294 if (dsipll_refcount == 0) {
295 ret = __mdss_dsi_pll_enable(c);
296 if (ret < 0)
297 goto out;
298 }
299 dsipll_refcount++;
300out:
301 spin_unlock_irqrestore(&dsipll_lock, flags);
302 return ret;
303}
304
305/* todo: Adjust these values appropriately */
306static enum handoff mdss_dsi_pll_byte_handoff(struct clk *c)
307{
308 if (mdss_gdsc_enabled() && mdss_dsi_check_pll_lock()) {
309 c->rate = 59000000;
310 dsi_pll_rate = 59000000;
311 pll_byte_clk_rate = 59000000;
312 pll_pclk_rate = 117000000;
313 dsipll_refcount++;
314 return HANDOFF_ENABLED_CLK;
315 }
316
317 return HANDOFF_DISABLED_CLK;
318}
319
320/* todo: Adjust these values appropriately */
321static enum handoff mdss_dsi_pll_pixel_handoff(struct clk *c)
322{
323 if (mdss_gdsc_enabled() && mdss_dsi_check_pll_lock()) {
324 c->rate = 117000000;
325 dsipll_refcount++;
326 return HANDOFF_ENABLED_CLK;
327 }
328
329 return HANDOFF_DISABLED_CLK;
330}
331
332struct clk_ops clk_ops_dsi_pixel_pll = {
333 .enable = mdss_dsi_pll_enable,
334 .disable = mdss_dsi_pll_disable,
335 .set_rate = mdss_dsi_pll_pixel_set_rate,
336 .round_rate = mdss_dsi_pll_pixel_round_rate,
337 .handoff = mdss_dsi_pll_pixel_handoff,
338};
339
340struct clk_ops clk_ops_dsi_byte_pll = {
341 .enable = mdss_dsi_pll_enable,
342 .disable = mdss_dsi_pll_disable,
343 .set_rate = mdss_dsi_pll_byte_set_rate,
344 .round_rate = mdss_dsi_pll_byte_round_rate,
345 .handoff = mdss_dsi_pll_byte_handoff,
346};