blob: 7777ef1fdf8907611055aef8dd333e777d168345 [file] [log] [blame]
Padmanabhan Komanduru703bd6d2014-03-25 19:57:01 +05301/* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
Arpita Banerjee2522bc62013-05-24 16:03:53 -07002 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are
5 * met:
6 * * Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * * Redistributions in binary form must reproduce the above
9 * copyright notice, this list of conditions and the following
10 * disclaimer in the documentation and/or other materials provided
11 * with the distribution.
12 * * Neither the name of The Linux Foundation nor the names of its
13 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 */
29#include <debug.h>
30#include <reg.h>
31#include <err.h>
32#include <smem.h>
33#include <mipi_dsi.h>
34#include <platform/iomap.h>
35
36#define LPFR_LUT_SIZE 10
37
38#define VCO_REF_CLOCK_RATE 19200000
39
40#define FRAC_DIVIDER 10000
41
42typedef struct lpfr_cfg {
43 uint32_t vco_rate;
44 uint8_t resistance;
45};
46
47static struct lpfr_cfg lpfr_lut[LPFR_LUT_SIZE] = {
48 {479500000, 8},
49 {480000000, 11},
50 {575500000, 8},
51 {576000000, 12},
52 {610500000, 8},
53 {659500000, 9},
54 {671500000, 10},
55 {672000000, 14},
56 {708500000, 10},
57 {750000000, 11},
58 };
59
60uint64_t div_s64(uint64_t dividend, uint32_t divisor, uint32_t *remainder)
61{
62 *remainder = dividend % divisor;
63
64 return dividend / divisor;
65}
66
Padmanabhan Komanduru703bd6d2014-03-25 19:57:01 +053067void mdss_dsi_uniphy_pll_lock_detect_setting(uint32_t pll_base)
68{
69 writel(0x0c, pll_base + 0x0064); /* LKDetect CFG2 */
70 udelay(100);
71 writel(0x0d, pll_base + 0x0064); /* LKDetect CFG2 */
72}
73
74void mdss_dsi_uniphy_pll_sw_reset(uint32_t pll_base)
75{
76 writel(0x01, pll_base + 0x0068); /* PLL TEST CFG */
77 udelay(1);
78 writel(0x00, pll_base + 0x0068); /* PLL TEST CFG */
79 udelay(1);
80}
81
82int32_t mdss_dsi_auto_pll_config(uint32_t pll_base, uint32_t ctl_base,
Casey Piper4bb1b742013-08-26 11:22:25 -070083 struct mdss_dsi_pll_config *pd)
Arpita Banerjee2522bc62013-05-24 16:03:53 -070084{
85 uint32_t rem, divider;
86 uint32_t refclk_cfg = 0, frac_n_mode = 0, ref_doubler_en_b = 0;
87 uint64_t vco_clock, div_fbx;
88 uint32_t ref_clk_to_pll = 0, frac_n_value = 0;
89 uint32_t sdm_cfg0, sdm_cfg1, sdm_cfg2, sdm_cfg3;
90 uint32_t gen_vco_clk, cal_cfg10, cal_cfg11;
91 uint32_t res;
92 uint8_t i, rc = NO_ERROR;
93
94 /* Configure the Loop filter resistance */
95 for (i = 0; i < LPFR_LUT_SIZE; i++)
96 if (pd->vco_clock <= lpfr_lut[i].vco_rate)
97 break;
98 if (i == LPFR_LUT_SIZE) {
99 dprintf(INFO, "unable to get loop filter resistance. vco=%d\n"
100 , lpfr_lut[i].vco_rate);
101 rc = ERROR;
102 return rc;
103 }
104
Casey Piper4bb1b742013-08-26 11:22:25 -0700105 mdss_dsi_phy_sw_reset(ctl_base);
Arpita Banerjee2522bc62013-05-24 16:03:53 -0700106
107 /* Loop filter resistance value */
Padmanabhan Komanduru703bd6d2014-03-25 19:57:01 +0530108 writel(lpfr_lut[i].resistance, pll_base + 0x002c);
Arpita Banerjee2522bc62013-05-24 16:03:53 -0700109 /* Loop filter capacitance values : c1 and c2 */
Padmanabhan Komanduru703bd6d2014-03-25 19:57:01 +0530110 writel(0x70, pll_base + 0x0030);
111 writel(0x15, pll_base + 0x0034);
Arpita Banerjee2522bc62013-05-24 16:03:53 -0700112
Padmanabhan Komanduru703bd6d2014-03-25 19:57:01 +0530113 writel(0x02, pll_base + 0x0008); /* ChgPump */
Arpita Banerjee2522bc62013-05-24 16:03:53 -0700114 /* postDiv1 - calculated in pll config*/
Padmanabhan Komanduru703bd6d2014-03-25 19:57:01 +0530115 writel(pd->posdiv1, pll_base + 0x0004);
Arpita Banerjee2522bc62013-05-24 16:03:53 -0700116 /* postDiv2 - fixed devision 4 */
Padmanabhan Komanduru703bd6d2014-03-25 19:57:01 +0530117 writel(0x03, pll_base + 0x0024);
Arpita Banerjee2522bc62013-05-24 16:03:53 -0700118 /* postDiv3 - calculated in pll config */
Padmanabhan Komanduru703bd6d2014-03-25 19:57:01 +0530119 writel(pd->posdiv3, pll_base + 0x0028); /* postDiv3 */
Arpita Banerjee2522bc62013-05-24 16:03:53 -0700120
Padmanabhan Komanduru703bd6d2014-03-25 19:57:01 +0530121 writel(0x2b, pll_base + 0x0078); /* Cal CFG3 */
122 writel(0x66, pll_base + 0x007c); /* Cal CFG4 */
123 writel(0x05, pll_base + 0x0064); /* LKDetect CFG2 */
Arpita Banerjee2522bc62013-05-24 16:03:53 -0700124
125 rem = pd->vco_clock % VCO_REF_CLOCK_RATE;
126 if (rem) {
127 refclk_cfg = 0x1;
128 frac_n_mode = 1;
129 ref_doubler_en_b = 0;
130 } else {
131 refclk_cfg = 0x0;
132 frac_n_mode = 0;
133 ref_doubler_en_b = 1;
134 }
135
136 ref_clk_to_pll = (VCO_REF_CLOCK_RATE * 2 * refclk_cfg)
137 + (ref_doubler_en_b * VCO_REF_CLOCK_RATE);
138
139 vco_clock = ((uint64_t) pd->vco_clock) * FRAC_DIVIDER;
140
141 div_fbx = vco_clock / ref_clk_to_pll;
142
143 rem = (uint32_t) (div_fbx % FRAC_DIVIDER);
144 rem = rem * (1 << 16);
145 frac_n_value = rem / FRAC_DIVIDER;
146
147 divider = pd->vco_clock / ref_clk_to_pll;
148 div_fbx *= ref_clk_to_pll;
149 gen_vco_clk = div_fbx / FRAC_DIVIDER;
150
151 if (frac_n_mode) {
152 sdm_cfg0 = 0x0;
153 sdm_cfg1 = (divider & 0x3f) - 1;
154 sdm_cfg3 = frac_n_value / 256;
155 sdm_cfg2 = frac_n_value % 256;
156 } else {
157 sdm_cfg0 = (0x1 << 5);
158 sdm_cfg0 |= (divider & 0x3f) - 1;
159 sdm_cfg1 = 0x0;
160 sdm_cfg2 = 0;
161 sdm_cfg3 = 0;
162 }
163
164 cal_cfg11 = gen_vco_clk / 256000000;
165 cal_cfg10 = (gen_vco_clk % 256000000) / 1000000;
166
Padmanabhan Komanduru703bd6d2014-03-25 19:57:01 +0530167 writel(sdm_cfg1 , pll_base + 0x003c); /* SDM CFG1 */
168 writel(sdm_cfg2 , pll_base + 0x0040); /* SDM CFG2 */
169 writel(sdm_cfg3 , pll_base + 0x0044); /* SDM CFG3 */
170 writel(0x00, pll_base + 0x0048); /* SDM CFG4 */
Arpita Banerjee2522bc62013-05-24 16:03:53 -0700171
172 udelay(10);
173
Padmanabhan Komanduru703bd6d2014-03-25 19:57:01 +0530174 writel(refclk_cfg, pll_base + 0x0000); /* REFCLK CFG */
175 writel(0x00, pll_base + 0x0014); /* PWRGEN CFG */
176 writel(0x71, pll_base + 0x000c); /* VCOLPF CFG */
177 writel(pd->directpath, pll_base + 0x0010); /* VREG CFG */
178 writel(sdm_cfg0, pll_base + 0x0038); /* SDM CFG0 */
Arpita Banerjee2522bc62013-05-24 16:03:53 -0700179
Padmanabhan Komanduru703bd6d2014-03-25 19:57:01 +0530180 writel(0x0a, pll_base + 0x006c); /* CAL CFG0 */
181 writel(0x30, pll_base + 0x0084); /* CAL CFG6 */
182 writel(0x00, pll_base + 0x0088); /* CAL CFG7 */
183 writel(0x60, pll_base + 0x008c); /* CAL CFG8 */
184 writel(0x00, pll_base + 0x0090); /* CAL CFG9 */
185 writel(cal_cfg10, pll_base + 0x0094); /* CAL CFG10 */
186 writel(cal_cfg11, pll_base + 0x0098); /* CAL CFG11 */
187 writel(0x20, pll_base + 0x009c); /* EFUSE CFG */
Arpita Banerjee2522bc62013-05-24 16:03:53 -0700188}