blob: 3f9fcd98815c20c4b16ed2d776a36f2800533fbe [file] [log] [blame]
Aravind Venkateswaran5773d732016-03-08 16:55:01 -08001/*
2 * Copyright (c) 2016-2017, 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/err.h>
18#include <linux/iopoll.h>
19#include <linux/delay.h>
Aravind Venkateswaran5773d732016-03-08 16:55:01 -080020#include "mdss-dsi-pll.h"
21#include "mdss-pll.h"
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -080022#include <dt-bindings/clock/mdss-10nm-pll-clk.h>
Aravind Venkateswaran5773d732016-03-08 16:55:01 -080023
24#define VCO_DELAY_USEC 1
25
Shashank Babu Chinta Venkataa1db3ff2017-04-20 17:00:48 -070026#define MHZ_250 250000000UL
27#define MHZ_500 500000000UL
28#define MHZ_1000 1000000000UL
29#define MHZ_1100 1100000000UL
Aravind Venkateswaran5773d732016-03-08 16:55:01 -080030#define MHZ_1900 1900000000UL
31#define MHZ_3000 3000000000UL
32
33/* Register Offsets from PLL base address */
34#define PLL_ANALOG_CONTROLS_ONE 0x000
35#define PLL_ANALOG_CONTROLS_TWO 0x004
Abhinav Kumar17a84fafb2017-12-01 17:45:34 -080036#define PLL_INT_LOOP_SETTINGS 0x008
37#define PLL_INT_LOOP_SETTINGS_TWO 0x00c
Aravind Venkateswaran5773d732016-03-08 16:55:01 -080038#define PLL_ANALOG_CONTROLS_THREE 0x010
Abhinav Kumar17a84fafb2017-12-01 17:45:34 -080039#define PLL_ANALOG_CONTROLS_FOUR 0x014
40#define PLL_INT_LOOP_CONTROLS 0x018
Aravind Venkateswaran5773d732016-03-08 16:55:01 -080041#define PLL_DSM_DIVIDER 0x01c
42#define PLL_FEEDBACK_DIVIDER 0x020
43#define PLL_SYSTEM_MUXES 0x024
Abhinav Kumar17a84fafb2017-12-01 17:45:34 -080044#define PLL_FREQ_UPDATE_CONTROL_OVERRIDES 0x028
Aravind Venkateswaran5773d732016-03-08 16:55:01 -080045#define PLL_CMODE 0x02c
46#define PLL_CALIBRATION_SETTINGS 0x030
Abhinav Kumar17a84fafb2017-12-01 17:45:34 -080047#define PLL_BAND_SEL_CAL_TIMER_LOW 0x034
48#define PLL_BAND_SEL_CAL_TIMER_HIGH 0x038
49#define PLL_BAND_SEL_CAL_SETTINGS 0x03c
50#define PLL_BAND_SEL_MIN 0x040
51#define PLL_BAND_SEL_MAX 0x044
52#define PLL_BAND_SEL_PFILT 0x048
53#define PLL_BAND_SEL_IFILT 0x04c
54#define PLL_BAND_SEL_CAL_SETTINGS_TWO 0x050
Aravind Venkateswaran5773d732016-03-08 16:55:01 -080055#define PLL_BAND_SEL_CAL_SETTINGS_THREE 0x054
Abhinav Kumar17a84fafb2017-12-01 17:45:34 -080056#define PLL_BAND_SEL_CAL_SETTINGS_FOUR 0x058
57#define PLL_BAND_SEL_ICODE_HIGH 0x05c
58#define PLL_BAND_SEL_ICODE_LOW 0x060
Aravind Venkateswaran5773d732016-03-08 16:55:01 -080059#define PLL_FREQ_DETECT_SETTINGS_ONE 0x064
Shashank Babu Chinta Venkata4302e8f2017-04-17 13:46:36 -070060#define PLL_PFILT 0x07c
61#define PLL_IFILT 0x080
Abhinav Kumar17a84fafb2017-12-01 17:45:34 -080062#define PLL_GAIN 0x084
63#define PLL_ICODE_LOW 0x088
64#define PLL_ICODE_HIGH 0x08c
65#define PLL_LOCKDET 0x090
Aravind Venkateswaran5773d732016-03-08 16:55:01 -080066#define PLL_OUTDIV 0x094
Abhinav Kumar17a84fafb2017-12-01 17:45:34 -080067#define PLL_FASTLOCK_CONTROL 0x098
68#define PLL_PASS_OUT_OVERRIDE_ONE 0x09c
69#define PLL_PASS_OUT_OVERRIDE_TWO 0x0a0
Aravind Venkateswaran5773d732016-03-08 16:55:01 -080070#define PLL_CORE_OVERRIDE 0x0a4
71#define PLL_CORE_INPUT_OVERRIDE 0x0a8
Abhinav Kumar17a84fafb2017-12-01 17:45:34 -080072#define PLL_RATE_CHANGE 0x0ac
73#define PLL_PLL_DIGITAL_TIMERS 0x0b0
Aravind Venkateswaran5773d732016-03-08 16:55:01 -080074#define PLL_PLL_DIGITAL_TIMERS_TWO 0x0b4
Abhinav Kumar17a84fafb2017-12-01 17:45:34 -080075#define PLL_DEC_FRAC_MUXES 0x0c8
Aravind Venkateswaran5773d732016-03-08 16:55:01 -080076#define PLL_DECIMAL_DIV_START_1 0x0cc
77#define PLL_FRAC_DIV_START_LOW_1 0x0d0
78#define PLL_FRAC_DIV_START_MID_1 0x0d4
79#define PLL_FRAC_DIV_START_HIGH_1 0x0d8
Abhinav Kumar17a84fafb2017-12-01 17:45:34 -080080#define PLL_MASH_CONTROL 0x0ec
81#define PLL_SSC_MUX_CONTROL 0x108
Benjamin Chan50580372016-05-30 14:58:12 -040082#define PLL_SSC_STEPSIZE_LOW_1 0x10c
83#define PLL_SSC_STEPSIZE_HIGH_1 0x110
84#define PLL_SSC_DIV_PER_LOW_1 0x114
85#define PLL_SSC_DIV_PER_HIGH_1 0x118
86#define PLL_SSC_DIV_ADJPER_LOW_1 0x11c
87#define PLL_SSC_DIV_ADJPER_HIGH_1 0x120
88#define PLL_SSC_CONTROL 0x13c
Aravind Venkateswaran5773d732016-03-08 16:55:01 -080089#define PLL_PLL_OUTDIV_RATE 0x140
90#define PLL_PLL_LOCKDET_RATE_1 0x144
91#define PLL_PLL_PROP_GAIN_RATE_1 0x14c
92#define PLL_PLL_BAND_SET_RATE_1 0x154
93#define PLL_PLL_INT_GAIN_IFILT_BAND_1 0x15c
94#define PLL_PLL_FL_INT_GAIN_PFILT_BAND_1 0x164
Abhinav Kumar17a84fafb2017-12-01 17:45:34 -080095#define PLL_FASTLOCK_EN_BAND 0x16c
96#define PLL_FREQ_TUNE_ACCUM_INIT_MUX 0x17c
Aravind Venkateswaran5773d732016-03-08 16:55:01 -080097#define PLL_PLL_LOCK_OVERRIDE 0x180
98#define PLL_PLL_LOCK_DELAY 0x184
Abhinav Kumar17a84fafb2017-12-01 17:45:34 -080099#define PLL_PLL_LOCK_MIN_DELAY 0x188
Shashank Babu Chinta Venkata4302e8f2017-04-17 13:46:36 -0700100#define PLL_CLOCK_INVERTERS 0x18c
Abhinav Kumar17a84fafb2017-12-01 17:45:34 -0800101#define PLL_SPARE_AND_JPC_OVERRIDES 0x190
102#define PLL_BIAS_CONTROL_1 0x194
103#define PLL_BIAS_CONTROL_2 0x198
104#define PLL_ALOG_OBSV_BUS_CTRL_1 0x19c
Aravind Venkateswaran5773d732016-03-08 16:55:01 -0800105#define PLL_COMMON_STATUS_ONE 0x1a0
106
107/* Register Offsets from PHY base address */
108#define PHY_CMN_CLK_CFG0 0x010
109#define PHY_CMN_CLK_CFG1 0x014
110#define PHY_CMN_RBUF_CTRL 0x01c
111#define PHY_CMN_PLL_CNTRL 0x038
112#define PHY_CMN_CTRL_0 0x024
113
Benjamin Chan50580372016-05-30 14:58:12 -0400114/* Bit definition of SSC control registers */
115#define SSC_CENTER BIT(0)
116#define SSC_EN BIT(1)
117#define SSC_FREQ_UPDATE BIT(2)
118#define SSC_FREQ_UPDATE_MUX BIT(3)
119#define SSC_UPDATE_SSC BIT(4)
120#define SSC_UPDATE_SSC_MUX BIT(5)
121#define SSC_START BIT(6)
122#define SSC_START_MUX BIT(7)
123
Aravind Venkateswaran5773d732016-03-08 16:55:01 -0800124enum {
125 DSI_PLL_0,
126 DSI_PLL_1,
127 DSI_PLL_MAX
128};
129
130struct dsi_pll_regs {
131 u32 pll_prop_gain_rate;
Aravind Venkateswaran5773d732016-03-08 16:55:01 -0800132 u32 pll_lockdet_rate;
133 u32 decimal_div_start;
134 u32 frac_div_start_low;
135 u32 frac_div_start_mid;
136 u32 frac_div_start_high;
Shashank Babu Chinta Venkataa1db3ff2017-04-20 17:00:48 -0700137 u32 pll_clock_inverters;
Benjamin Chan50580372016-05-30 14:58:12 -0400138 u32 ssc_stepsize_low;
139 u32 ssc_stepsize_high;
140 u32 ssc_div_per_low;
141 u32 ssc_div_per_high;
142 u32 ssc_adjper_low;
143 u32 ssc_adjper_high;
144 u32 ssc_control;
Aravind Venkateswaran5773d732016-03-08 16:55:01 -0800145};
146
147struct dsi_pll_config {
148 u32 ref_freq;
149 bool div_override;
150 u32 output_div;
151 bool ignore_frac;
152 bool disable_prescaler;
Benjamin Chan50580372016-05-30 14:58:12 -0400153 bool enable_ssc;
154 bool ssc_center;
Aravind Venkateswaran5773d732016-03-08 16:55:01 -0800155 u32 dec_bits;
156 u32 frac_bits;
157 u32 lock_timer;
158 u32 ssc_freq;
159 u32 ssc_offset;
160 u32 ssc_adj_per;
161 u32 thresh_cycles;
162 u32 refclk_cycles;
163};
164
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -0800165struct dsi_pll_10nm {
Aravind Venkateswaran5773d732016-03-08 16:55:01 -0800166 struct mdss_pll_resources *rsc;
167 struct dsi_pll_config pll_configuration;
168 struct dsi_pll_regs reg_setup;
Aravind Venkateswaran5773d732016-03-08 16:55:01 -0800169};
170
Rajkumar Subbiahb6adb3a2017-06-16 17:08:48 -0400171static inline int pll_reg_read(void *context, unsigned int reg,
172 unsigned int *val)
173{
174 int rc = 0;
175 struct mdss_pll_resources *rsc = context;
176
177 rc = mdss_pll_resource_enable(rsc, true);
178 if (rc) {
179 pr_err("Failed to enable dsi pll resources, rc=%d\n", rc);
180 return rc;
181 }
182
183 *val = MDSS_PLL_REG_R(rsc->pll_base, reg);
184 (void)mdss_pll_resource_enable(rsc, false);
185
186 return rc;
187}
188
189static inline int pll_reg_write(void *context, unsigned int reg,
190 unsigned int val)
191{
192 int rc = 0;
193 struct mdss_pll_resources *rsc = context;
194
195 rc = mdss_pll_resource_enable(rsc, true);
196 if (rc) {
197 pr_err("Failed to enable dsi pll resources, rc=%d\n", rc);
198 return rc;
199 }
200
201 MDSS_PLL_REG_W(rsc->pll_base, reg, val);
202 (void)mdss_pll_resource_enable(rsc, false);
203
204 return rc;
205}
206
207static inline int phy_reg_read(void *context, unsigned int reg,
208 unsigned int *val)
209{
210 int rc = 0;
211 struct mdss_pll_resources *rsc = context;
212
213 rc = mdss_pll_resource_enable(rsc, true);
214 if (rc) {
215 pr_err("Failed to enable dsi pll resources, rc=%d\n", rc);
216 return rc;
217 }
218
219 *val = MDSS_PLL_REG_R(rsc->phy_base, reg);
220 (void)mdss_pll_resource_enable(rsc, false);
221
222 return rc;
223}
224
225static inline int phy_reg_write(void *context, unsigned int reg,
226 unsigned int val)
227{
228 int rc = 0;
229 struct mdss_pll_resources *rsc = context;
230
231 rc = mdss_pll_resource_enable(rsc, true);
232 if (rc) {
233 pr_err("Failed to enable dsi pll resources, rc=%d\n", rc);
234 return rc;
235 }
236
237 MDSS_PLL_REG_W(rsc->phy_base, reg, val);
238 (void)mdss_pll_resource_enable(rsc, false);
239
240 return rc;
241}
242
243static inline int phy_reg_update_bits_sub(struct mdss_pll_resources *rsc,
244 unsigned int reg, unsigned int mask, unsigned int val)
245{
246 u32 reg_val;
247 int rc = 0;
248
249 reg_val = MDSS_PLL_REG_R(rsc->phy_base, reg);
250 reg_val &= ~mask;
251 reg_val |= (val & mask);
252 MDSS_PLL_REG_W(rsc->phy_base, reg, reg_val);
253
254 return rc;
255}
256
257static inline int phy_reg_update_bits(void *context, unsigned int reg,
258 unsigned int mask, unsigned int val)
259{
260 int rc = 0;
261 struct mdss_pll_resources *rsc = context;
262
263 rc = mdss_pll_resource_enable(rsc, true);
264 if (rc) {
265 pr_err("Failed to enable dsi pll resources, rc=%d\n", rc);
266 return rc;
267 }
268
269 rc = phy_reg_update_bits_sub(rsc, reg, mask, val);
270 if (!rc && rsc->slave)
271 rc = phy_reg_update_bits_sub(rsc->slave, reg, mask, val);
272 (void)mdss_pll_resource_enable(rsc, false);
273
274 return rc;
275}
276
277static inline int pclk_mux_read_sel(void *context, unsigned int reg,
278 unsigned int *val)
279{
280 int rc = 0;
281 struct mdss_pll_resources *rsc = context;
282
283 rc = mdss_pll_resource_enable(rsc, true);
284 if (rc)
285 pr_err("Failed to enable dsi pll resources, rc=%d\n", rc);
286 else
Shashank Babu Chinta Venkatae0ce0122017-11-27 17:23:23 -0800287 *val = (MDSS_PLL_REG_R(rsc->phy_base, reg) & 0x3);
Rajkumar Subbiahb6adb3a2017-06-16 17:08:48 -0400288
289 (void)mdss_pll_resource_enable(rsc, false);
290 return rc;
291}
292
293
294static inline int pclk_mux_write_sel_sub(struct mdss_pll_resources *rsc,
295 unsigned int reg, unsigned int val)
296{
297 u32 reg_val;
298 int rc = 0;
299
300 reg_val = MDSS_PLL_REG_R(rsc->phy_base, reg);
301 reg_val &= ~0x03;
302 reg_val |= val;
303
304 MDSS_PLL_REG_W(rsc->phy_base, reg, reg_val);
305
306 return rc;
307}
308
309static inline int pclk_mux_write_sel(void *context, unsigned int reg,
310 unsigned int val)
311{
312 int rc = 0;
313 struct mdss_pll_resources *rsc = context;
314
315 rc = mdss_pll_resource_enable(rsc, true);
316 if (rc) {
317 pr_err("Failed to enable dsi pll resources, rc=%d\n", rc);
318 return rc;
319 }
320
321 rc = pclk_mux_write_sel_sub(rsc, reg, val);
322 if (!rc && rsc->slave)
323 rc = pclk_mux_write_sel_sub(rsc->slave, reg, val);
324
325 (void)mdss_pll_resource_enable(rsc, false);
326
Sandeep Panda9a674ec2017-09-20 18:08:06 +0530327 /*
328 * cache the current parent index for cases where parent
329 * is not changing but rate is changing. In that case
330 * clock framework won't call parent_set and hence dsiclk_sel
331 * bit won't be programmed. e.g. dfps update use case.
332 */
333 rsc->cached_cfg1 = val;
334
Rajkumar Subbiahb6adb3a2017-06-16 17:08:48 -0400335 return rc;
336}
337
Aravind Venkateswaran5773d732016-03-08 16:55:01 -0800338static struct mdss_pll_resources *pll_rsc_db[DSI_PLL_MAX];
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -0800339static struct dsi_pll_10nm plls[DSI_PLL_MAX];
Aravind Venkateswaran5773d732016-03-08 16:55:01 -0800340
341static void dsi_pll_config_slave(struct mdss_pll_resources *rsc)
342{
343 u32 reg;
344 struct mdss_pll_resources *orsc = pll_rsc_db[DSI_PLL_1];
345
346 if (!rsc)
347 return;
348
349 /* Only DSI PLL0 can act as a master */
350 if (rsc->index != DSI_PLL_0)
351 return;
352
353 /* default configuration: source is either internal or ref clock */
354 rsc->slave = NULL;
355
356 if (!orsc) {
357 pr_warn("slave PLL unavilable, assuming standalone config\n");
358 return;
359 }
360
361 /* check to see if the source of DSI1 PLL bitclk is set to external */
362 reg = MDSS_PLL_REG_R(orsc->phy_base, PHY_CMN_CLK_CFG1);
363 reg &= (BIT(2) | BIT(3));
364 if (reg == 0x04)
365 rsc->slave = pll_rsc_db[DSI_PLL_1]; /* external source */
366
367 pr_debug("Slave PLL %s\n", rsc->slave ? "configured" : "absent");
368}
369
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -0800370static void dsi_pll_setup_config(struct dsi_pll_10nm *pll,
Aravind Venkateswaran5773d732016-03-08 16:55:01 -0800371 struct mdss_pll_resources *rsc)
372{
373 struct dsi_pll_config *config = &pll->pll_configuration;
374
375 config->ref_freq = 19200000;
376 config->output_div = 1;
377 config->dec_bits = 8;
378 config->frac_bits = 18;
379 config->lock_timer = 64;
380 config->ssc_freq = 31500;
Benjamin Chan50580372016-05-30 14:58:12 -0400381 config->ssc_offset = 5000;
Aravind Venkateswaran5773d732016-03-08 16:55:01 -0800382 config->ssc_adj_per = 2;
383 config->thresh_cycles = 32;
384 config->refclk_cycles = 256;
385
386 config->div_override = false;
387 config->ignore_frac = false;
388 config->disable_prescaler = false;
Benjamin Chan50580372016-05-30 14:58:12 -0400389 config->enable_ssc = rsc->ssc_en;
390 config->ssc_center = rsc->ssc_center;
391
392 if (config->enable_ssc) {
393 if (rsc->ssc_freq)
394 config->ssc_freq = rsc->ssc_freq;
395 if (rsc->ssc_ppm)
396 config->ssc_offset = rsc->ssc_ppm;
397 }
Aravind Venkateswaran5773d732016-03-08 16:55:01 -0800398
399 dsi_pll_config_slave(rsc);
400}
401
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -0800402static void dsi_pll_calc_dec_frac(struct dsi_pll_10nm *pll,
Aravind Venkateswaran5773d732016-03-08 16:55:01 -0800403 struct mdss_pll_resources *rsc)
404{
405 struct dsi_pll_config *config = &pll->pll_configuration;
406 struct dsi_pll_regs *regs = &pll->reg_setup;
Aravind Venkateswaran5773d732016-03-08 16:55:01 -0800407 u64 fref = rsc->vco_ref_clk_rate;
Aravind Venkateswaran5773d732016-03-08 16:55:01 -0800408 u64 pll_freq;
409 u64 divider;
410 u64 dec, dec_multiple;
411 u32 frac;
412 u64 multiplier;
413
Rajkumar Subbiahb6adb3a2017-06-16 17:08:48 -0400414 pll_freq = rsc->vco_current_rate;
Aravind Venkateswaran5773d732016-03-08 16:55:01 -0800415
416 if (config->disable_prescaler)
417 divider = fref;
418 else
419 divider = fref * 2;
420
421 multiplier = 1 << config->frac_bits;
422 dec_multiple = div_u64(pll_freq * multiplier, divider);
423 div_u64_rem(dec_multiple, multiplier, &frac);
424
425 dec = div_u64(dec_multiple, multiplier);
426
427 if (pll_freq <= MHZ_1900)
428 regs->pll_prop_gain_rate = 8;
429 else if (pll_freq <= MHZ_3000)
430 regs->pll_prop_gain_rate = 10;
431 else
432 regs->pll_prop_gain_rate = 12;
Shashank Babu Chinta Venkataa1db3ff2017-04-20 17:00:48 -0700433 if (pll_freq < MHZ_1100)
434 regs->pll_clock_inverters = 8;
435 else
436 regs->pll_clock_inverters = 0;
Aravind Venkateswaran5773d732016-03-08 16:55:01 -0800437
Aravind Venkateswaran5773d732016-03-08 16:55:01 -0800438 regs->pll_lockdet_rate = config->lock_timer;
439 regs->decimal_div_start = dec;
440 regs->frac_div_start_low = (frac & 0xff);
441 regs->frac_div_start_mid = (frac & 0xff00) >> 8;
442 regs->frac_div_start_high = (frac & 0x30000) >> 16;
443}
444
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -0800445static void dsi_pll_calc_ssc(struct dsi_pll_10nm *pll,
Benjamin Chan50580372016-05-30 14:58:12 -0400446 struct mdss_pll_resources *rsc)
447{
448 struct dsi_pll_config *config = &pll->pll_configuration;
449 struct dsi_pll_regs *regs = &pll->reg_setup;
450 u32 ssc_per;
451 u32 ssc_mod;
452 u64 ssc_step_size;
453 u64 frac;
454
455 if (!config->enable_ssc) {
456 pr_debug("SSC not enabled\n");
457 return;
458 }
459
460 ssc_per = DIV_ROUND_CLOSEST(config->ref_freq, config->ssc_freq) / 2 - 1;
461 ssc_mod = (ssc_per + 1) % (config->ssc_adj_per + 1);
462 ssc_per -= ssc_mod;
463
464 frac = regs->frac_div_start_low |
465 (regs->frac_div_start_mid << 8) |
466 (regs->frac_div_start_high << 16);
467 ssc_step_size = regs->decimal_div_start;
468 ssc_step_size *= (1 << config->frac_bits);
469 ssc_step_size += frac;
470 ssc_step_size *= config->ssc_offset;
471 ssc_step_size *= (config->ssc_adj_per + 1);
472 ssc_step_size = div_u64(ssc_step_size, (ssc_per + 1));
473 ssc_step_size = DIV_ROUND_CLOSEST_ULL(ssc_step_size, 1000000);
474
475 regs->ssc_div_per_low = ssc_per & 0xFF;
476 regs->ssc_div_per_high = (ssc_per & 0xFF00) >> 8;
477 regs->ssc_stepsize_low = (u32)(ssc_step_size & 0xFF);
478 regs->ssc_stepsize_high = (u32)((ssc_step_size & 0xFF00) >> 8);
479 regs->ssc_adjper_low = config->ssc_adj_per & 0xFF;
480 regs->ssc_adjper_high = (config->ssc_adj_per & 0xFF00) >> 8;
481
482 regs->ssc_control = config->ssc_center ? SSC_CENTER : 0;
483
484 pr_debug("SCC: Dec:%d, frac:%llu, frac_bits:%d\n",
485 regs->decimal_div_start, frac, config->frac_bits);
486 pr_debug("SSC: div_per:0x%X, stepsize:0x%X, adjper:0x%X\n",
487 ssc_per, (u32)ssc_step_size, config->ssc_adj_per);
488}
489
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -0800490static void dsi_pll_ssc_commit(struct dsi_pll_10nm *pll,
Benjamin Chan50580372016-05-30 14:58:12 -0400491 struct mdss_pll_resources *rsc)
492{
493 void __iomem *pll_base = rsc->pll_base;
494 struct dsi_pll_regs *regs = &pll->reg_setup;
495
496 if (pll->pll_configuration.enable_ssc) {
497 pr_debug("SSC is enabled\n");
498
499 MDSS_PLL_REG_W(pll_base, PLL_SSC_STEPSIZE_LOW_1,
500 regs->ssc_stepsize_low);
501 MDSS_PLL_REG_W(pll_base, PLL_SSC_STEPSIZE_HIGH_1,
502 regs->ssc_stepsize_high);
503 MDSS_PLL_REG_W(pll_base, PLL_SSC_DIV_PER_LOW_1,
504 regs->ssc_div_per_low);
505 MDSS_PLL_REG_W(pll_base, PLL_SSC_DIV_PER_HIGH_1,
506 regs->ssc_div_per_high);
507 MDSS_PLL_REG_W(pll_base, PLL_SSC_DIV_ADJPER_LOW_1,
508 regs->ssc_adjper_low);
509 MDSS_PLL_REG_W(pll_base, PLL_SSC_DIV_ADJPER_HIGH_1,
510 regs->ssc_adjper_high);
511 MDSS_PLL_REG_W(pll_base, PLL_SSC_CONTROL,
512 SSC_EN | regs->ssc_control);
513 }
514}
515
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -0800516static void dsi_pll_config_hzindep_reg(struct dsi_pll_10nm *pll,
Aravind Venkateswaran5773d732016-03-08 16:55:01 -0800517 struct mdss_pll_resources *rsc)
518{
519 void __iomem *pll_base = rsc->pll_base;
520
521 MDSS_PLL_REG_W(pll_base, PLL_ANALOG_CONTROLS_ONE, 0x80);
522 MDSS_PLL_REG_W(pll_base, PLL_ANALOG_CONTROLS_TWO, 0x03);
523 MDSS_PLL_REG_W(pll_base, PLL_ANALOG_CONTROLS_THREE, 0x00);
524 MDSS_PLL_REG_W(pll_base, PLL_DSM_DIVIDER, 0x00);
525 MDSS_PLL_REG_W(pll_base, PLL_FEEDBACK_DIVIDER, 0x4e);
Aravind Venkateswaran5773d732016-03-08 16:55:01 -0800526 MDSS_PLL_REG_W(pll_base, PLL_CALIBRATION_SETTINGS, 0x40);
527 MDSS_PLL_REG_W(pll_base, PLL_BAND_SEL_CAL_SETTINGS_THREE, 0xba);
528 MDSS_PLL_REG_W(pll_base, PLL_FREQ_DETECT_SETTINGS_ONE, 0x0c);
529 MDSS_PLL_REG_W(pll_base, PLL_OUTDIV, 0x00);
530 MDSS_PLL_REG_W(pll_base, PLL_CORE_OVERRIDE, 0x00);
531 MDSS_PLL_REG_W(pll_base, PLL_PLL_DIGITAL_TIMERS_TWO, 0x08);
532 MDSS_PLL_REG_W(pll_base, PLL_PLL_PROP_GAIN_RATE_1, 0x08);
533 MDSS_PLL_REG_W(pll_base, PLL_PLL_BAND_SET_RATE_1, 0xc0);
Shashank Babu Chinta Venkata4302e8f2017-04-17 13:46:36 -0700534 MDSS_PLL_REG_W(pll_base, PLL_PLL_INT_GAIN_IFILT_BAND_1, 0xfa);
Aravind Venkateswaran5773d732016-03-08 16:55:01 -0800535 MDSS_PLL_REG_W(pll_base, PLL_PLL_FL_INT_GAIN_PFILT_BAND_1, 0x4c);
536 MDSS_PLL_REG_W(pll_base, PLL_PLL_LOCK_OVERRIDE, 0x80);
Shashank Babu Chinta Venkata4302e8f2017-04-17 13:46:36 -0700537 MDSS_PLL_REG_W(pll_base, PLL_PFILT, 0x29);
538 MDSS_PLL_REG_W(pll_base, PLL_IFILT, 0x3f);
Aravind Venkateswaran5773d732016-03-08 16:55:01 -0800539}
540
Abhinav Kumar17a84fafb2017-12-01 17:45:34 -0800541static void dsi_pll_init_val(struct mdss_pll_resources *rsc)
542{
543 void __iomem *pll_base = rsc->pll_base;
544
545 MDSS_PLL_REG_W(pll_base, PLL_CORE_INPUT_OVERRIDE, 0x10);
546 MDSS_PLL_REG_W(pll_base, PLL_INT_LOOP_SETTINGS, 0x3f);
547 MDSS_PLL_REG_W(pll_base, PLL_INT_LOOP_SETTINGS_TWO, 0x0);
548 MDSS_PLL_REG_W(pll_base, PLL_ANALOG_CONTROLS_FOUR, 0x0);
549 MDSS_PLL_REG_W(pll_base, PLL_INT_LOOP_CONTROLS, 0x80);
550 MDSS_PLL_REG_W(pll_base, PLL_FREQ_UPDATE_CONTROL_OVERRIDES, 0x0);
551 MDSS_PLL_REG_W(pll_base, PLL_BAND_SEL_CAL_TIMER_LOW, 0x0);
552 MDSS_PLL_REG_W(pll_base, PLL_BAND_SEL_CAL_TIMER_HIGH, 0x02);
553 MDSS_PLL_REG_W(pll_base, PLL_BAND_SEL_CAL_SETTINGS, 0x82);
554 MDSS_PLL_REG_W(pll_base, PLL_BAND_SEL_MIN, 0x00);
555 MDSS_PLL_REG_W(pll_base, PLL_BAND_SEL_MAX, 0xff);
556 MDSS_PLL_REG_W(pll_base, PLL_BAND_SEL_PFILT, 0x00);
557 MDSS_PLL_REG_W(pll_base, PLL_BAND_SEL_IFILT, 0x00);
558 MDSS_PLL_REG_W(pll_base, PLL_BAND_SEL_CAL_SETTINGS_TWO, 0x25);
559 MDSS_PLL_REG_W(pll_base, PLL_BAND_SEL_CAL_SETTINGS_FOUR, 0x4f);
560 MDSS_PLL_REG_W(pll_base, PLL_BAND_SEL_ICODE_HIGH, 0x0a);
561 MDSS_PLL_REG_W(pll_base, PLL_BAND_SEL_ICODE_LOW, 0x0);
562 MDSS_PLL_REG_W(pll_base, PLL_GAIN, 0x42);
563 MDSS_PLL_REG_W(pll_base, PLL_ICODE_LOW, 0x00);
564 MDSS_PLL_REG_W(pll_base, PLL_ICODE_HIGH, 0x00);
565 MDSS_PLL_REG_W(pll_base, PLL_LOCKDET, 0x30);
566 MDSS_PLL_REG_W(pll_base, PLL_FASTLOCK_CONTROL, 0x04);
567 MDSS_PLL_REG_W(pll_base, PLL_PASS_OUT_OVERRIDE_ONE, 0x00);
568 MDSS_PLL_REG_W(pll_base, PLL_PASS_OUT_OVERRIDE_TWO, 0x00);
569 MDSS_PLL_REG_W(pll_base, PLL_RATE_CHANGE, 0x01);
570 MDSS_PLL_REG_W(pll_base, PLL_PLL_DIGITAL_TIMERS, 0x08);
571 MDSS_PLL_REG_W(pll_base, PLL_DEC_FRAC_MUXES, 0x00);
572 MDSS_PLL_REG_W(pll_base, PLL_MASH_CONTROL, 0x03);
573 MDSS_PLL_REG_W(pll_base, PLL_SSC_MUX_CONTROL, 0x0);
574 MDSS_PLL_REG_W(pll_base, PLL_SSC_CONTROL, 0x0);
575 MDSS_PLL_REG_W(pll_base, PLL_FASTLOCK_EN_BAND, 0x03);
576 MDSS_PLL_REG_W(pll_base, PLL_FREQ_TUNE_ACCUM_INIT_MUX, 0x0);
577 MDSS_PLL_REG_W(pll_base, PLL_PLL_LOCK_MIN_DELAY, 0x19);
578 MDSS_PLL_REG_W(pll_base, PLL_SPARE_AND_JPC_OVERRIDES, 0x0);
579 MDSS_PLL_REG_W(pll_base, PLL_BIAS_CONTROL_1, 0x40);
580 MDSS_PLL_REG_W(pll_base, PLL_BIAS_CONTROL_2, 0x20);
581 MDSS_PLL_REG_W(pll_base, PLL_ALOG_OBSV_BUS_CTRL_1, 0x0);
582}
583
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -0800584static void dsi_pll_commit(struct dsi_pll_10nm *pll,
Aravind Venkateswaran5773d732016-03-08 16:55:01 -0800585 struct mdss_pll_resources *rsc)
586{
587 void __iomem *pll_base = rsc->pll_base;
588 struct dsi_pll_regs *reg = &pll->reg_setup;
589
590 MDSS_PLL_REG_W(pll_base, PLL_CORE_INPUT_OVERRIDE, 0x12);
591 MDSS_PLL_REG_W(pll_base, PLL_DECIMAL_DIV_START_1,
592 reg->decimal_div_start);
593 MDSS_PLL_REG_W(pll_base, PLL_FRAC_DIV_START_LOW_1,
594 reg->frac_div_start_low);
595 MDSS_PLL_REG_W(pll_base, PLL_FRAC_DIV_START_MID_1,
596 reg->frac_div_start_mid);
597 MDSS_PLL_REG_W(pll_base, PLL_FRAC_DIV_START_HIGH_1,
598 reg->frac_div_start_high);
Shashank Babu Chinta Venkata4302e8f2017-04-17 13:46:36 -0700599 MDSS_PLL_REG_W(pll_base, PLL_PLL_LOCKDET_RATE_1, 0x40);
Shashank Babu Chinta Venkata4302e8f2017-04-17 13:46:36 -0700600 MDSS_PLL_REG_W(pll_base, PLL_PLL_LOCK_DELAY, 0x06);
601 MDSS_PLL_REG_W(pll_base, PLL_CMODE, 0x10);
Shashank Babu Chinta Venkataa1db3ff2017-04-20 17:00:48 -0700602 MDSS_PLL_REG_W(pll_base, PLL_CLOCK_INVERTERS, reg->pll_clock_inverters);
Aravind Venkateswaran5773d732016-03-08 16:55:01 -0800603
Aravind Venkateswaran5773d732016-03-08 16:55:01 -0800604}
605
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -0800606static int vco_10nm_set_rate(struct clk_hw *hw, unsigned long rate,
607 unsigned long parent_rate)
Aravind Venkateswaran5773d732016-03-08 16:55:01 -0800608{
609 int rc;
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -0800610 struct dsi_pll_vco_clk *vco = to_vco_clk_hw(hw);
Aravind Venkateswaran071ecc82016-05-18 15:18:34 -0700611 struct mdss_pll_resources *rsc = vco->priv;
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -0800612 struct dsi_pll_10nm *pll;
Aravind Venkateswaran5773d732016-03-08 16:55:01 -0800613
614 if (!rsc) {
615 pr_err("pll resource not found\n");
616 return -EINVAL;
617 }
618
Aravind Venkateswaran5773d732016-03-08 16:55:01 -0800619 if (rsc->pll_on)
620 return 0;
621
622 pll = rsc->priv;
623 if (!pll) {
624 pr_err("pll configuration not found\n");
625 return -EINVAL;
626 }
627
Aravind Venkateswaran071ecc82016-05-18 15:18:34 -0700628 pr_debug("ndx=%d, rate=%lu\n", rsc->index, rate);
629
630 rsc->vco_current_rate = rate;
631 rsc->vco_ref_clk_rate = vco->ref_clk_rate;
632
Aravind Venkateswaran5773d732016-03-08 16:55:01 -0800633 rc = mdss_pll_resource_enable(rsc, true);
634 if (rc) {
635 pr_err("failed to enable mdss dsi pll(%d), rc=%d\n",
636 rsc->index, rc);
637 return rc;
638 }
639
Abhinav Kumar17a84fafb2017-12-01 17:45:34 -0800640 dsi_pll_init_val(rsc);
641
Aravind Venkateswaran5773d732016-03-08 16:55:01 -0800642 dsi_pll_setup_config(pll, rsc);
643
644 dsi_pll_calc_dec_frac(pll, rsc);
645
Benjamin Chan50580372016-05-30 14:58:12 -0400646 dsi_pll_calc_ssc(pll, rsc);
Aravind Venkateswaran5773d732016-03-08 16:55:01 -0800647
648 dsi_pll_commit(pll, rsc);
649
Benjamin Chan50580372016-05-30 14:58:12 -0400650 dsi_pll_config_hzindep_reg(pll, rsc);
651
652 dsi_pll_ssc_commit(pll, rsc);
653
654 /* flush, ensure all register writes are done*/
655 wmb();
656
Aravind Venkateswaran5773d732016-03-08 16:55:01 -0800657 mdss_pll_resource_enable(rsc, false);
658
Aravind Venkateswaran071ecc82016-05-18 15:18:34 -0700659 return 0;
Aravind Venkateswaran5773d732016-03-08 16:55:01 -0800660}
661
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -0800662static int dsi_pll_10nm_lock_status(struct mdss_pll_resources *pll)
Aravind Venkateswaran5773d732016-03-08 16:55:01 -0800663{
664 int rc;
665 u32 status;
666 u32 const delay_us = 100;
667 u32 const timeout_us = 5000;
668
669 rc = readl_poll_timeout_atomic(pll->pll_base + PLL_COMMON_STATUS_ONE,
670 status,
671 ((status & BIT(0)) > 0),
672 delay_us,
673 timeout_us);
674 if (rc)
675 pr_err("DSI PLL(%d) lock failed, status=0x%08x\n",
676 pll->index, status);
677
678 return rc;
679}
680
681static void dsi_pll_disable_pll_bias(struct mdss_pll_resources *rsc)
682{
683 u32 data = MDSS_PLL_REG_R(rsc->phy_base, PHY_CMN_CTRL_0);
684
Aravind Venkateswaran5773d732016-03-08 16:55:01 -0800685 MDSS_PLL_REG_W(rsc->pll_base, PLL_SYSTEM_MUXES, 0);
Shashank Babu Chinta Venkata4302e8f2017-04-17 13:46:36 -0700686 MDSS_PLL_REG_W(rsc->phy_base, PHY_CMN_CTRL_0, data & ~BIT(5));
Aravind Venkateswaran5773d732016-03-08 16:55:01 -0800687 ndelay(250);
688}
689
690static void dsi_pll_enable_pll_bias(struct mdss_pll_resources *rsc)
691{
692 u32 data = MDSS_PLL_REG_R(rsc->phy_base, PHY_CMN_CTRL_0);
693
694 MDSS_PLL_REG_W(rsc->phy_base, PHY_CMN_CTRL_0, data | BIT(5));
695 MDSS_PLL_REG_W(rsc->pll_base, PLL_SYSTEM_MUXES, 0xc0);
696 ndelay(250);
697}
698
Shashank Babu Chinta Venkata4302e8f2017-04-17 13:46:36 -0700699static void dsi_pll_disable_global_clk(struct mdss_pll_resources *rsc)
700{
701 u32 data;
702
703 data = MDSS_PLL_REG_R(rsc->phy_base, PHY_CMN_CLK_CFG1);
704 MDSS_PLL_REG_W(rsc->phy_base, PHY_CMN_CLK_CFG1, (data & ~BIT(5)));
705}
706
707static void dsi_pll_enable_global_clk(struct mdss_pll_resources *rsc)
708{
709 u32 data;
710
711 data = MDSS_PLL_REG_R(rsc->phy_base, PHY_CMN_CLK_CFG1);
712 MDSS_PLL_REG_W(rsc->phy_base, PHY_CMN_CLK_CFG1, (data | BIT(5)));
713}
714
Aravind Venkateswaran5773d732016-03-08 16:55:01 -0800715static int dsi_pll_enable(struct dsi_pll_vco_clk *vco)
716{
717 int rc;
718 struct mdss_pll_resources *rsc = vco->priv;
719
720 dsi_pll_enable_pll_bias(rsc);
721 if (rsc->slave)
722 dsi_pll_enable_pll_bias(rsc->slave);
723
Sandeep Panda9a674ec2017-09-20 18:08:06 +0530724 phy_reg_update_bits_sub(rsc, PHY_CMN_CLK_CFG1, 0x03, rsc->cached_cfg1);
725 if (rsc->slave)
726 phy_reg_update_bits_sub(rsc->slave, PHY_CMN_CLK_CFG1,
727 0x03, rsc->cached_cfg1);
728 wmb(); /* ensure dsiclk_sel is always programmed before pll start */
729
Aravind Venkateswaran5773d732016-03-08 16:55:01 -0800730 /* Start PLL */
731 MDSS_PLL_REG_W(rsc->phy_base, PHY_CMN_PLL_CNTRL, 0x01);
732
733 /*
734 * ensure all PLL configurations are written prior to checking
735 * for PLL lock.
736 */
737 wmb();
738
739 /* Check for PLL lock */
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -0800740 rc = dsi_pll_10nm_lock_status(rsc);
Aravind Venkateswaran5773d732016-03-08 16:55:01 -0800741 if (rc) {
742 pr_err("PLL(%d) lock failed\n", rsc->index);
743 goto error;
744 }
745
746 rsc->pll_on = true;
Shashank Babu Chinta Venkata4302e8f2017-04-17 13:46:36 -0700747
748 dsi_pll_enable_global_clk(rsc);
749 if (rsc->slave)
750 dsi_pll_enable_global_clk(rsc->slave);
751
Aravind Venkateswaran5773d732016-03-08 16:55:01 -0800752 MDSS_PLL_REG_W(rsc->phy_base, PHY_CMN_RBUF_CTRL, 0x01);
753 if (rsc->slave)
754 MDSS_PLL_REG_W(rsc->slave->phy_base, PHY_CMN_RBUF_CTRL, 0x01);
755
756error:
757 return rc;
758}
759
760static void dsi_pll_disable_sub(struct mdss_pll_resources *rsc)
761{
Aravind Venkateswaran5773d732016-03-08 16:55:01 -0800762 MDSS_PLL_REG_W(rsc->phy_base, PHY_CMN_RBUF_CTRL, 0);
Shashank Babu Chinta Venkata4302e8f2017-04-17 13:46:36 -0700763 dsi_pll_disable_pll_bias(rsc);
Aravind Venkateswaran5773d732016-03-08 16:55:01 -0800764}
765
766static void dsi_pll_disable(struct dsi_pll_vco_clk *vco)
767{
768 struct mdss_pll_resources *rsc = vco->priv;
769
770 if (!rsc->pll_on &&
771 mdss_pll_resource_enable(rsc, true)) {
772 pr_err("failed to enable pll (%d) resources\n", rsc->index);
773 return;
774 }
775
776 rsc->handoff_resources = false;
777
778 pr_debug("stop PLL (%d)\n", rsc->index);
779
Vara Reddyc8d09532017-09-04 23:42:44 -0700780 /*
781 * To avoid any stray glitches while
782 * abruptly powering down the PLL
783 * make sure to gate the clock using
784 * the clock enable bit before powering
785 * down the PLL
786 */
787 dsi_pll_disable_global_clk(rsc);
Aravind Venkateswaran5773d732016-03-08 16:55:01 -0800788 MDSS_PLL_REG_W(rsc->phy_base, PHY_CMN_PLL_CNTRL, 0);
789 dsi_pll_disable_sub(rsc);
Vara Reddyc8d09532017-09-04 23:42:44 -0700790 if (rsc->slave) {
791 dsi_pll_disable_global_clk(rsc->slave);
Aravind Venkateswaran5773d732016-03-08 16:55:01 -0800792 dsi_pll_disable_sub(rsc->slave);
Vara Reddyc8d09532017-09-04 23:42:44 -0700793 }
Aravind Venkateswaran5773d732016-03-08 16:55:01 -0800794 /* flush, ensure all register writes are done*/
795 wmb();
796 rsc->pll_on = false;
797}
798
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -0800799long vco_10nm_round_rate(struct clk_hw *hw, unsigned long rate,
800 unsigned long *parent_rate)
Aravind Venkateswaran5773d732016-03-08 16:55:01 -0800801{
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -0800802 unsigned long rrate = rate;
803 struct dsi_pll_vco_clk *vco = to_vco_clk_hw(hw);
804
805 if (rate < vco->min_rate)
806 rrate = vco->min_rate;
807 if (rate > vco->max_rate)
808 rrate = vco->max_rate;
809
810 *parent_rate = rrate;
811
812 return rrate;
813}
814
815static void vco_10nm_unprepare(struct clk_hw *hw)
816{
817 struct dsi_pll_vco_clk *vco = to_vco_clk_hw(hw);
Aravind Venkateswaran5773d732016-03-08 16:55:01 -0800818 struct mdss_pll_resources *pll = vco->priv;
819
820 if (!pll) {
821 pr_err("dsi pll resources not available\n");
822 return;
823 }
824
Shashank Babu Chinta Venkatae0ce0122017-11-27 17:23:23 -0800825 /*
826 * During unprepare in continuous splash use case we want driver
827 * to pick all dividers instead of retaining bootloader configurations.
828 */
829 if (!pll->handoff_resources) {
830 pll->cached_cfg0 = MDSS_PLL_REG_R(pll->phy_base,
831 PHY_CMN_CLK_CFG0);
832 pll->cached_outdiv = MDSS_PLL_REG_R(pll->pll_base,
833 PLL_PLL_OUTDIV_RATE);
834 pr_debug("cfg0=%d,cfg1=%d, outdiv=%d\n", pll->cached_cfg0,
835 pll->cached_cfg1, pll->cached_outdiv);
836
837 pll->vco_cached_rate = clk_hw_get_rate(hw);
838 }
839
840 /*
841 * When continuous splash screen feature is enabled, we need to cache
842 * the mux configuration for the pixel_clk_src mux clock. The clock
843 * framework does not call back to re-configure the mux value if it is
844 * does not change.For such usecases, we need to ensure that the cached
845 * value is programmed prior to PLL being locked
846 */
847 if (pll->handoff_resources)
848 pll->cached_cfg1 = MDSS_PLL_REG_R(pll->phy_base,
849 PHY_CMN_CLK_CFG1);
Aravind Venkateswaran5773d732016-03-08 16:55:01 -0800850 dsi_pll_disable(vco);
851 mdss_pll_resource_enable(pll, false);
852}
853
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -0800854static int vco_10nm_prepare(struct clk_hw *hw)
Aravind Venkateswaran5773d732016-03-08 16:55:01 -0800855{
856 int rc = 0;
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -0800857 struct dsi_pll_vco_clk *vco = to_vco_clk_hw(hw);
Aravind Venkateswaran5773d732016-03-08 16:55:01 -0800858 struct mdss_pll_resources *pll = vco->priv;
859
860 if (!pll) {
861 pr_err("dsi pll resources are not available\n");
862 return -EINVAL;
863 }
864
Shashank Babu Chinta Venkatacad9fe32017-05-19 14:35:17 -0700865 /* Skip vco recalculation for continuous splash use case */
866 if (pll->handoff_resources == true)
867 return 0;
868
Aravind Venkateswaran5773d732016-03-08 16:55:01 -0800869 rc = mdss_pll_resource_enable(pll, true);
870 if (rc) {
871 pr_err("failed to enable pll (%d) resource, rc=%d\n",
872 pll->index, rc);
873 return rc;
874 }
875
876 if ((pll->vco_cached_rate != 0) &&
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -0800877 (pll->vco_cached_rate == clk_hw_get_rate(hw))) {
878 rc = hw->init->ops->set_rate(hw, pll->vco_cached_rate,
879 pll->vco_cached_rate);
Aravind Venkateswaran5773d732016-03-08 16:55:01 -0800880 if (rc) {
881 pr_err("pll(%d) set_rate failed, rc=%d\n",
882 pll->index, rc);
883 mdss_pll_resource_enable(pll, false);
884 return rc;
885 }
Shashank Babu Chinta Venkata2182d622017-05-08 14:39:40 -0700886 pr_debug("cfg0=%d, cfg1=%d\n", pll->cached_cfg0,
887 pll->cached_cfg1);
888 MDSS_PLL_REG_W(pll->phy_base, PHY_CMN_CLK_CFG0,
889 pll->cached_cfg0);
Rajkumar Subbiahb6adb3a2017-06-16 17:08:48 -0400890 MDSS_PLL_REG_W(pll->pll_base, PLL_PLL_OUTDIV_RATE,
891 pll->cached_outdiv);
Aravind Venkateswaran5773d732016-03-08 16:55:01 -0800892 }
893
894 rc = dsi_pll_enable(vco);
895 if (rc) {
896 mdss_pll_resource_enable(pll, false);
897 pr_err("pll(%d) enable failed, rc=%d\n", pll->index, rc);
898 return rc;
899 }
900
901 return rc;
902}
903
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -0800904static unsigned long vco_10nm_recalc_rate(struct clk_hw *hw,
905 unsigned long parent_rate)
Aravind Venkateswaran5773d732016-03-08 16:55:01 -0800906{
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -0800907 struct dsi_pll_vco_clk *vco = to_vco_clk_hw(hw);
Aravind Venkateswaran5773d732016-03-08 16:55:01 -0800908 struct mdss_pll_resources *pll = vco->priv;
909 int rc;
910 u64 ref_clk = vco->ref_clk_rate;
911 u64 vco_rate;
912 u64 multiplier;
913 u32 frac;
914 u32 dec;
915 u32 outdiv;
916 u64 pll_freq, tmp64;
917
Shashank Babu Chinta Venkata4302e8f2017-04-17 13:46:36 -0700918 if (!vco->priv)
919 pr_err("vco priv is null\n");
920
Aravind Venkateswarandc65c972017-10-10 16:43:29 -0700921 /*
922 * Calculate the vco rate from HW registers only for handoff cases.
923 * For other cases where a vco_10nm_set_rate() has already been
924 * called, just return the rate that was set earlier. This is due
925 * to the fact that recalculating VCO rate requires us to read the
926 * correct value of the pll_out_div divider clock, which is only set
927 * afterwards.
928 */
929 if (pll->vco_current_rate != 0) {
930 pr_debug("returning vco rate = %lld\n", pll->vco_current_rate);
931 return pll->vco_current_rate;
932 }
933
Aravind Venkateswaran5773d732016-03-08 16:55:01 -0800934 rc = mdss_pll_resource_enable(pll, true);
935 if (rc) {
936 pr_err("failed to enable pll(%d) resource, rc=%d\n",
937 pll->index, rc);
938 return 0;
939 }
940
Shashank Babu Chinta Venkatacad9fe32017-05-19 14:35:17 -0700941 if (!dsi_pll_10nm_lock_status(pll))
942 pll->handoff_resources = true;
943
Aravind Venkateswaran5773d732016-03-08 16:55:01 -0800944 dec = MDSS_PLL_REG_R(pll->pll_base, PLL_DECIMAL_DIV_START_1);
945 dec &= 0xFF;
946
947 frac = MDSS_PLL_REG_R(pll->pll_base, PLL_FRAC_DIV_START_LOW_1);
948 frac |= ((MDSS_PLL_REG_R(pll->pll_base, PLL_FRAC_DIV_START_MID_1) &
949 0xFF) <<
950 8);
951 frac |= ((MDSS_PLL_REG_R(pll->pll_base, PLL_FRAC_DIV_START_HIGH_1) &
952 0x3) <<
953 16);
954
955 /* OUTDIV_1:0 field is (log(outdiv, 2)) */
Aravind Venkateswaran55d0e222016-06-28 12:00:11 -0700956 outdiv = MDSS_PLL_REG_R(pll->pll_base, PLL_PLL_OUTDIV_RATE);
Aravind Venkateswaran5773d732016-03-08 16:55:01 -0800957 outdiv &= 0x3;
958 outdiv = 1 << outdiv;
959
960 /*
961 * TODO:
962 * 1. Assumes prescaler is disabled
963 * 2. Multiplier is 2^18. it should be 2^(num_of_frac_bits)
964 **/
965 multiplier = 1 << 18;
966 pll_freq = dec * (ref_clk * 2);
967 tmp64 = (ref_clk * 2 * frac);
Aravind Venkateswaran55d0e222016-06-28 12:00:11 -0700968 pll_freq += div_u64(tmp64, multiplier);
Aravind Venkateswaran5773d732016-03-08 16:55:01 -0800969
Aravind Venkateswaran55d0e222016-06-28 12:00:11 -0700970 vco_rate = div_u64(pll_freq, outdiv);
Aravind Venkateswaran5773d732016-03-08 16:55:01 -0800971
Aravind Venkateswaran55d0e222016-06-28 12:00:11 -0700972 pr_debug("dec=0x%x, frac=0x%x, outdiv=%d, vco=%llu\n",
973 dec, frac, outdiv, vco_rate);
Aravind Venkateswaran5773d732016-03-08 16:55:01 -0800974
975 (void)mdss_pll_resource_enable(pll, false);
976
977 return (unsigned long)vco_rate;
978}
979
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -0800980static int pixel_clk_get_div(void *context, unsigned int reg, unsigned int *div)
Aravind Venkateswaran5773d732016-03-08 16:55:01 -0800981{
982 int rc;
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -0800983 struct mdss_pll_resources *pll = context;
Aravind Venkateswaran5773d732016-03-08 16:55:01 -0800984 u32 reg_val;
Aravind Venkateswaran5773d732016-03-08 16:55:01 -0800985
986 rc = mdss_pll_resource_enable(pll, true);
987 if (rc) {
988 pr_err("Failed to enable dsi pll resources, rc=%d\n", rc);
989 return rc;
990 }
991
992 reg_val = MDSS_PLL_REG_R(pll->phy_base, PHY_CMN_CLK_CFG0);
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -0800993 *div = (reg_val & 0xF0) >> 4;
994
Shashank Babu Chinta Venkata4302e8f2017-04-17 13:46:36 -0700995 /**
996 * Common clock framework the divider value is interpreted as one less
997 * hence we return one less for all dividers except when zero
998 */
999 if (*div != 0)
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -08001000 *div -= 1;
Aravind Venkateswaran5773d732016-03-08 16:55:01 -08001001
1002 (void)mdss_pll_resource_enable(pll, false);
1003
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -08001004 return rc;
Aravind Venkateswaran5773d732016-03-08 16:55:01 -08001005}
1006
1007static void pixel_clk_set_div_sub(struct mdss_pll_resources *pll, int div)
1008{
1009 u32 reg_val;
1010
1011 reg_val = MDSS_PLL_REG_R(pll->phy_base, PHY_CMN_CLK_CFG0);
1012 reg_val &= ~0xF0;
1013 reg_val |= (div << 4);
1014 MDSS_PLL_REG_W(pll->phy_base, PHY_CMN_CLK_CFG0, reg_val);
1015}
1016
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -08001017static int pixel_clk_set_div(void *context, unsigned int reg, unsigned int div)
Aravind Venkateswaran5773d732016-03-08 16:55:01 -08001018{
1019 int rc;
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -08001020 struct mdss_pll_resources *pll = context;
Aravind Venkateswaran5773d732016-03-08 16:55:01 -08001021
1022 rc = mdss_pll_resource_enable(pll, true);
1023 if (rc) {
1024 pr_err("Failed to enable dsi pll resources, rc=%d\n", rc);
1025 return rc;
1026 }
Shashank Babu Chinta Venkata4302e8f2017-04-17 13:46:36 -07001027 /**
1028 * In common clock framework the divider value provided is one less and
1029 * and hence adjusting the divider value by one prior to writing it to
1030 * hardware
1031 */
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -08001032 div++;
Aravind Venkateswaran5773d732016-03-08 16:55:01 -08001033 pixel_clk_set_div_sub(pll, div);
1034 if (pll->slave)
1035 pixel_clk_set_div_sub(pll->slave, div);
Aravind Venkateswaran5773d732016-03-08 16:55:01 -08001036 (void)mdss_pll_resource_enable(pll, false);
1037
1038 return 0;
1039}
1040
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -08001041static int bit_clk_get_div(void *context, unsigned int reg, unsigned int *div)
Aravind Venkateswaran5773d732016-03-08 16:55:01 -08001042{
1043 int rc;
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -08001044 struct mdss_pll_resources *pll = context;
Aravind Venkateswaran5773d732016-03-08 16:55:01 -08001045 u32 reg_val;
Aravind Venkateswaran5773d732016-03-08 16:55:01 -08001046
1047 rc = mdss_pll_resource_enable(pll, true);
1048 if (rc) {
1049 pr_err("Failed to enable dsi pll resources, rc=%d\n", rc);
1050 return rc;
1051 }
1052
1053 reg_val = MDSS_PLL_REG_R(pll->phy_base, PHY_CMN_CLK_CFG0);
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -08001054 *div = (reg_val & 0x0F);
1055
Shashank Babu Chinta Venkata4302e8f2017-04-17 13:46:36 -07001056 /**
1057 *Common clock framework the divider value is interpreted as one less
1058 * hence we return one less for all dividers except when zero
1059 */
1060 if (*div != 0)
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -08001061 *div -= 1;
Aravind Venkateswaran5773d732016-03-08 16:55:01 -08001062 (void)mdss_pll_resource_enable(pll, false);
1063
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -08001064 return rc;
Aravind Venkateswaran5773d732016-03-08 16:55:01 -08001065}
1066
1067static void bit_clk_set_div_sub(struct mdss_pll_resources *rsc, int div)
1068{
1069 u32 reg_val;
1070
1071 reg_val = MDSS_PLL_REG_R(rsc->phy_base, PHY_CMN_CLK_CFG0);
1072 reg_val &= ~0x0F;
Aravind Venkateswaran071ecc82016-05-18 15:18:34 -07001073 reg_val |= div;
Aravind Venkateswaran5773d732016-03-08 16:55:01 -08001074 MDSS_PLL_REG_W(rsc->phy_base, PHY_CMN_CLK_CFG0, reg_val);
1075}
1076
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -08001077static int bit_clk_set_div(void *context, unsigned int reg, unsigned int div)
Aravind Venkateswaran5773d732016-03-08 16:55:01 -08001078{
1079 int rc;
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -08001080 struct mdss_pll_resources *rsc = context;
Aravind Venkateswaran5773d732016-03-08 16:55:01 -08001081 struct dsi_pll_8998 *pll;
1082
1083 if (!rsc) {
1084 pr_err("pll resource not found\n");
1085 return -EINVAL;
1086 }
1087
1088 pll = rsc->priv;
1089 if (!pll) {
1090 pr_err("pll configuration not found\n");
1091 return -EINVAL;
1092 }
1093
1094 rc = mdss_pll_resource_enable(rsc, true);
1095 if (rc) {
1096 pr_err("Failed to enable dsi pll resources, rc=%d\n", rc);
1097 return rc;
1098 }
Shashank Babu Chinta Venkata4302e8f2017-04-17 13:46:36 -07001099
1100 /**
1101 * In common clock framework the divider value provided is one less and
1102 * and hence adjusting the divider value by one prior to writing it to
1103 * hardware
1104 */
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -08001105 div++;
Aravind Venkateswaran5773d732016-03-08 16:55:01 -08001106
Aravind Venkateswaran5773d732016-03-08 16:55:01 -08001107 bit_clk_set_div_sub(rsc, div);
Aravind Venkateswaran071ecc82016-05-18 15:18:34 -07001108 /* For slave PLL, this divider always should be set to 1 */
Aravind Venkateswaran5773d732016-03-08 16:55:01 -08001109 if (rsc->slave)
Aravind Venkateswaran071ecc82016-05-18 15:18:34 -07001110 bit_clk_set_div_sub(rsc->slave, 1);
Aravind Venkateswaran5773d732016-03-08 16:55:01 -08001111
1112 (void)mdss_pll_resource_enable(rsc, false);
1113
Aravind Venkateswaran5773d732016-03-08 16:55:01 -08001114 return rc;
1115}
1116
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -08001117static struct regmap_config dsi_pll_10nm_config = {
1118 .reg_bits = 32,
1119 .reg_stride = 4,
1120 .val_bits = 32,
1121 .max_register = 0x7c0,
Aravind Venkateswaran5773d732016-03-08 16:55:01 -08001122};
1123
Rajkumar Subbiahb6adb3a2017-06-16 17:08:48 -04001124static struct regmap_bus pll_regmap_bus = {
1125 .reg_write = pll_reg_write,
1126 .reg_read = pll_reg_read,
Aravind Venkateswaran5773d732016-03-08 16:55:01 -08001127};
1128
Shashank Babu Chinta Venkatae0ce0122017-11-27 17:23:23 -08001129static struct regmap_bus pclk_src_mux_regmap_bus = {
1130 .reg_read = pclk_mux_read_sel,
Rajkumar Subbiahb6adb3a2017-06-16 17:08:48 -04001131 .reg_write = pclk_mux_write_sel,
Aravind Venkateswaran5773d732016-03-08 16:55:01 -08001132};
1133
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -08001134static struct regmap_bus pclk_src_regmap_bus = {
1135 .reg_write = pixel_clk_set_div,
1136 .reg_read = pixel_clk_get_div,
Aravind Venkateswaran5773d732016-03-08 16:55:01 -08001137};
1138
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -08001139static struct regmap_bus bitclk_src_regmap_bus = {
1140 .reg_write = bit_clk_set_div,
1141 .reg_read = bit_clk_get_div,
Aravind Venkateswaran5773d732016-03-08 16:55:01 -08001142};
1143
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -08001144static const struct clk_ops clk_ops_vco_10nm = {
1145 .recalc_rate = vco_10nm_recalc_rate,
1146 .set_rate = vco_10nm_set_rate,
1147 .round_rate = vco_10nm_round_rate,
1148 .prepare = vco_10nm_prepare,
1149 .unprepare = vco_10nm_unprepare,
1150};
1151
1152static struct regmap_bus mdss_mux_regmap_bus = {
1153 .reg_write = mdss_set_mux_sel,
1154 .reg_read = mdss_get_mux_sel,
Aravind Venkateswaran5773d732016-03-08 16:55:01 -08001155};
1156
1157/*
1158 * Clock tree for generating DSI byte and pixel clocks.
1159 *
1160 *
1161 * +---------------+
1162 * | vco_clk |
1163 * +-------+-------+
1164 * |
Rajkumar Subbiahb6adb3a2017-06-16 17:08:48 -04001165 * |
1166 * +---------------+
1167 * | pll_out_div |
1168 * | DIV(1,2,4,8) |
1169 * +-------+-------+
1170 * |
1171 * +-----------------------------+--------+
1172 * | | |
1173 * +-------v-------+ | |
1174 * | bitclk_src | | |
1175 * | DIV(1..15) | | |
1176 * +-------+-------+ | |
1177 * | | |
1178 * +----------+---------+ | |
1179 * Shadow Path | | | | |
1180 * + +-------v-------+ | +------v------+ | +------v-------+
1181 * | | byteclk_src | | |post_bit_div | | |post_vco_div |
1182 * | | DIV(8) | | |DIV (2) | | |DIV(4) |
1183 * | +-------+-------+ | +------+------+ | +------+-------+
1184 * | | | | | | |
1185 * | | | +------+ | |
1186 * | | +-------------+ | | +----+
1187 * | +--------+ | | | |
1188 * | | +-v--v-v---v------+
Aravind Venkateswaran5773d732016-03-08 16:55:01 -08001189 * +-v---------v----+ \ pclk_src_mux /
1190 * \ byteclk_mux / \ /
1191 * \ / +-----+-----+
1192 * +----+-----+ | Shadow Path
1193 * | | +
1194 * v +-----v------+ |
1195 * dsi_byte_clk | pclk_src | |
1196 * | DIV(1..15) | |
1197 * +-----+------+ |
1198 * | |
1199 * | |
1200 * +--------+ |
1201 * | |
1202 * +---v----v----+
1203 * \ pclk_mux /
1204 * \ /
1205 * +---+---+
1206 * |
1207 * |
1208 * v
1209 * dsi_pclk
1210 *
1211 */
1212
1213static struct dsi_pll_vco_clk dsi0pll_vco_clk = {
1214 .ref_clk_rate = 19200000UL,
Shashank Babu Chinta Venkataa1db3ff2017-04-20 17:00:48 -07001215 .min_rate = 1000000000UL,
Aravind Venkateswaran5773d732016-03-08 16:55:01 -08001216 .max_rate = 3500000000UL,
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -08001217 .hw.init = &(struct clk_init_data){
1218 .name = "dsi0pll_vco_clk",
Shashank Babu Chinta Venkata2182d622017-05-08 14:39:40 -07001219 .parent_names = (const char *[]){"bi_tcxo"},
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -08001220 .num_parents = 1,
1221 .ops = &clk_ops_vco_10nm,
1222 .flags = CLK_GET_RATE_NOCACHE,
Aravind Venkateswaran5773d732016-03-08 16:55:01 -08001223 },
1224};
1225
Aravind Venkateswaran5773d732016-03-08 16:55:01 -08001226static struct dsi_pll_vco_clk dsi1pll_vco_clk = {
1227 .ref_clk_rate = 19200000UL,
Shashank Babu Chinta Venkataa1db3ff2017-04-20 17:00:48 -07001228 .min_rate = 1000000000UL,
Aravind Venkateswaran5773d732016-03-08 16:55:01 -08001229 .max_rate = 3500000000UL,
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -08001230 .hw.init = &(struct clk_init_data){
1231 .name = "dsi1pll_vco_clk",
Shashank Babu Chinta Venkata2182d622017-05-08 14:39:40 -07001232 .parent_names = (const char *[]){"bi_tcxo"},
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -08001233 .num_parents = 1,
1234 .ops = &clk_ops_vco_10nm,
1235 .flags = CLK_GET_RATE_NOCACHE,
Aravind Venkateswaran5773d732016-03-08 16:55:01 -08001236 },
1237};
1238
Rajkumar Subbiahb6adb3a2017-06-16 17:08:48 -04001239static struct clk_regmap_div dsi0pll_pll_out_div = {
1240 .reg = PLL_PLL_OUTDIV_RATE,
1241 .shift = 0,
1242 .width = 2,
1243 .flags = CLK_DIVIDER_POWER_OF_TWO,
1244 .clkr = {
1245 .hw.init = &(struct clk_init_data){
1246 .name = "dsi0pll_pll_out_div",
1247 .parent_names = (const char *[]){"dsi0pll_vco_clk"},
1248 .num_parents = 1,
1249 .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT),
1250 .ops = &clk_regmap_div_ops,
1251 },
1252 },
1253};
1254
1255static struct clk_regmap_div dsi1pll_pll_out_div = {
1256 .reg = PLL_PLL_OUTDIV_RATE,
1257 .shift = 0,
1258 .width = 2,
1259 .flags = CLK_DIVIDER_POWER_OF_TWO,
1260 .clkr = {
1261 .hw.init = &(struct clk_init_data){
1262 .name = "dsi1pll_pll_out_div",
1263 .parent_names = (const char *[]){"dsi1pll_vco_clk"},
1264 .num_parents = 1,
1265 .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT),
1266 .ops = &clk_regmap_div_ops,
1267 },
1268 },
1269};
1270
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -08001271static struct clk_regmap_div dsi0pll_bitclk_src = {
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -08001272 .shift = 0,
1273 .width = 4,
1274 .clkr = {
1275 .hw.init = &(struct clk_init_data){
1276 .name = "dsi0pll_bitclk_src",
Rajkumar Subbiahb6adb3a2017-06-16 17:08:48 -04001277 .parent_names = (const char *[]){"dsi0pll_pll_out_div"},
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -08001278 .num_parents = 1,
1279 .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT),
1280 .ops = &clk_regmap_div_ops,
1281 },
Aravind Venkateswaran5773d732016-03-08 16:55:01 -08001282 },
1283};
1284
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -08001285static struct clk_regmap_div dsi1pll_bitclk_src = {
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -08001286 .shift = 0,
1287 .width = 4,
1288 .clkr = {
1289 .hw.init = &(struct clk_init_data){
1290 .name = "dsi1pll_bitclk_src",
Rajkumar Subbiahb6adb3a2017-06-16 17:08:48 -04001291 .parent_names = (const char *[]){"dsi1pll_pll_out_div"},
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -08001292 .num_parents = 1,
1293 .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT),
1294 .ops = &clk_regmap_div_ops,
1295 },
Aravind Venkateswaran5773d732016-03-08 16:55:01 -08001296 },
1297};
1298
Rajkumar Subbiahb6adb3a2017-06-16 17:08:48 -04001299static struct clk_fixed_factor dsi0pll_post_vco_div = {
1300 .div = 4,
1301 .mult = 1,
1302 .hw.init = &(struct clk_init_data){
1303 .name = "dsi0pll_post_vco_div",
1304 .parent_names = (const char *[]){"dsi0pll_pll_out_div"},
1305 .num_parents = 1,
1306 .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT),
1307 .ops = &clk_fixed_factor_ops,
Aravind Venkateswaran5773d732016-03-08 16:55:01 -08001308 },
Aravind Venkateswaran5773d732016-03-08 16:55:01 -08001309};
1310
Rajkumar Subbiahb6adb3a2017-06-16 17:08:48 -04001311static struct clk_fixed_factor dsi1pll_post_vco_div = {
1312 .div = 4,
1313 .mult = 1,
1314 .hw.init = &(struct clk_init_data){
1315 .name = "dsi1pll_post_vco_div",
1316 .parent_names = (const char *[]){"dsi1pll_pll_out_div"},
1317 .num_parents = 1,
1318 .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT),
1319 .ops = &clk_fixed_factor_ops,
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -08001320 },
Aravind Venkateswaran5773d732016-03-08 16:55:01 -08001321};
1322
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -08001323static struct clk_fixed_factor dsi0pll_byteclk_src = {
1324 .div = 8,
1325 .mult = 1,
1326 .hw.init = &(struct clk_init_data){
1327 .name = "dsi0pll_byteclk_src",
1328 .parent_names = (const char *[]){"dsi0pll_bitclk_src"},
1329 .num_parents = 1,
1330 .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT),
1331 .ops = &clk_fixed_factor_ops,
1332 },
1333};
1334
1335static struct clk_fixed_factor dsi1pll_byteclk_src = {
1336 .div = 8,
1337 .mult = 1,
1338 .hw.init = &(struct clk_init_data){
1339 .name = "dsi1pll_byteclk_src",
1340 .parent_names = (const char *[]){"dsi1pll_bitclk_src"},
1341 .num_parents = 1,
1342 .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT),
1343 .ops = &clk_fixed_factor_ops,
1344 },
1345};
1346
Rajkumar Subbiahb6adb3a2017-06-16 17:08:48 -04001347static struct clk_fixed_factor dsi0pll_post_bit_div = {
1348 .div = 2,
1349 .mult = 1,
1350 .hw.init = &(struct clk_init_data){
1351 .name = "dsi0pll_post_bit_div",
1352 .parent_names = (const char *[]){"dsi0pll_bitclk_src"},
1353 .num_parents = 1,
1354 .flags = CLK_GET_RATE_NOCACHE,
1355 .ops = &clk_fixed_factor_ops,
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -08001356 },
1357};
1358
Rajkumar Subbiahb6adb3a2017-06-16 17:08:48 -04001359static struct clk_fixed_factor dsi1pll_post_bit_div = {
1360 .div = 2,
1361 .mult = 1,
1362 .hw.init = &(struct clk_init_data){
1363 .name = "dsi1pll_post_bit_div",
1364 .parent_names = (const char *[]){"dsi1pll_bitclk_src"},
1365 .num_parents = 1,
1366 .flags = CLK_GET_RATE_NOCACHE,
1367 .ops = &clk_fixed_factor_ops,
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -08001368 },
1369};
1370
1371static struct clk_regmap_mux dsi0pll_byteclk_mux = {
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -08001372 .shift = 0,
Shashank Babu Chinta Venkata45aef0b2017-05-01 13:12:16 -07001373 .width = 1,
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -08001374 .clkr = {
1375 .hw.init = &(struct clk_init_data){
Shashank Babu Chinta Venkata4302e8f2017-04-17 13:46:36 -07001376 .name = "dsi0_phy_pll_out_byteclk",
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -08001377 .parent_names = (const char *[]){"dsi0pll_byteclk_src"},
1378 .num_parents = 1,
1379 .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT),
1380 .ops = &clk_regmap_mux_closest_ops,
1381 },
1382 },
1383};
1384
1385static struct clk_regmap_mux dsi1pll_byteclk_mux = {
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -08001386 .shift = 0,
Shashank Babu Chinta Venkata45aef0b2017-05-01 13:12:16 -07001387 .width = 1,
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -08001388 .clkr = {
1389 .hw.init = &(struct clk_init_data){
Shashank Babu Chinta Venkata4302e8f2017-04-17 13:46:36 -07001390 .name = "dsi1_phy_pll_out_byteclk",
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -08001391 .parent_names = (const char *[]){"dsi1pll_byteclk_src"},
1392 .num_parents = 1,
1393 .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT),
1394 .ops = &clk_regmap_mux_closest_ops,
1395 },
1396 },
1397};
1398
1399static struct clk_regmap_mux dsi0pll_pclk_src_mux = {
Rajkumar Subbiahb6adb3a2017-06-16 17:08:48 -04001400 .reg = PHY_CMN_CLK_CFG1,
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -08001401 .shift = 0,
Rajkumar Subbiahb6adb3a2017-06-16 17:08:48 -04001402 .width = 2,
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -08001403 .clkr = {
1404 .hw.init = &(struct clk_init_data){
1405 .name = "dsi0pll_pclk_src_mux",
Rajkumar Subbiahb6adb3a2017-06-16 17:08:48 -04001406 .parent_names = (const char *[]){"dsi0pll_bitclk_src",
1407 "dsi0pll_post_bit_div",
1408 "dsi0pll_pll_out_div",
1409 "dsi0pll_post_vco_div"},
1410 .num_parents = 4,
1411 .flags = CLK_GET_RATE_NOCACHE,
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -08001412 .ops = &clk_regmap_mux_closest_ops,
1413 },
1414 },
1415};
1416
1417static struct clk_regmap_mux dsi1pll_pclk_src_mux = {
Rajkumar Subbiahb6adb3a2017-06-16 17:08:48 -04001418 .reg = PHY_CMN_CLK_CFG1,
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -08001419 .shift = 0,
Rajkumar Subbiahb6adb3a2017-06-16 17:08:48 -04001420 .width = 2,
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -08001421 .clkr = {
1422 .hw.init = &(struct clk_init_data){
1423 .name = "dsi1pll_pclk_src_mux",
Rajkumar Subbiahb6adb3a2017-06-16 17:08:48 -04001424 .parent_names = (const char *[]){"dsi1pll_bitclk_src",
1425 "dsi1pll_post_bit_div",
1426 "dsi1pll_pll_out_div",
1427 "dsi1pll_post_vco_div"},
1428 .num_parents = 4,
1429 .flags = CLK_GET_RATE_NOCACHE,
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -08001430 .ops = &clk_regmap_mux_closest_ops,
1431 },
1432 },
1433};
1434
1435static struct clk_regmap_div dsi0pll_pclk_src = {
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -08001436 .shift = 0,
1437 .width = 4,
1438 .clkr = {
1439 .hw.init = &(struct clk_init_data){
1440 .name = "dsi0pll_pclk_src",
1441 .parent_names = (const char *[]){
1442 "dsi0pll_pclk_src_mux"},
1443 .num_parents = 1,
1444 .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT),
1445 .ops = &clk_regmap_div_ops,
1446 },
1447 },
1448};
1449
1450static struct clk_regmap_div dsi1pll_pclk_src = {
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -08001451 .shift = 0,
1452 .width = 4,
1453 .clkr = {
1454 .hw.init = &(struct clk_init_data){
1455 .name = "dsi1pll_pclk_src",
1456 .parent_names = (const char *[]){
1457 "dsi1pll_pclk_src_mux"},
1458 .num_parents = 1,
1459 .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT),
1460 .ops = &clk_regmap_div_ops,
1461 },
1462 },
1463};
1464
1465static struct clk_regmap_mux dsi0pll_pclk_mux = {
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -08001466 .shift = 0,
Shashank Babu Chinta Venkata45aef0b2017-05-01 13:12:16 -07001467 .width = 1,
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -08001468 .clkr = {
1469 .hw.init = &(struct clk_init_data){
Shashank Babu Chinta Venkata4302e8f2017-04-17 13:46:36 -07001470 .name = "dsi0_phy_pll_out_dsiclk",
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -08001471 .parent_names = (const char *[]){"dsi0pll_pclk_src"},
1472 .num_parents = 1,
1473 .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT),
1474 .ops = &clk_regmap_mux_closest_ops,
1475 },
1476 },
1477};
1478
1479static struct clk_regmap_mux dsi1pll_pclk_mux = {
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -08001480 .shift = 0,
Shashank Babu Chinta Venkata45aef0b2017-05-01 13:12:16 -07001481 .width = 1,
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -08001482 .clkr = {
1483 .hw.init = &(struct clk_init_data){
Shashank Babu Chinta Venkata4302e8f2017-04-17 13:46:36 -07001484 .name = "dsi1_phy_pll_out_dsiclk",
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -08001485 .parent_names = (const char *[]){"dsi1pll_pclk_src"},
1486 .num_parents = 1,
1487 .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT),
1488 .ops = &clk_regmap_mux_closest_ops,
1489 },
1490 },
1491};
1492
1493static struct clk_hw *mdss_dsi_pllcc_10nm[] = {
1494 [VCO_CLK_0] = &dsi0pll_vco_clk.hw,
Rajkumar Subbiahb6adb3a2017-06-16 17:08:48 -04001495 [PLL_OUT_DIV_0_CLK] = &dsi0pll_pll_out_div.clkr.hw,
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -08001496 [BITCLK_SRC_0_CLK] = &dsi0pll_bitclk_src.clkr.hw,
1497 [BYTECLK_SRC_0_CLK] = &dsi0pll_byteclk_src.hw,
Rajkumar Subbiahb6adb3a2017-06-16 17:08:48 -04001498 [POST_BIT_DIV_0_CLK] = &dsi0pll_post_bit_div.hw,
1499 [POST_VCO_DIV_0_CLK] = &dsi0pll_post_vco_div.hw,
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -08001500 [BYTECLK_MUX_0_CLK] = &dsi0pll_byteclk_mux.clkr.hw,
1501 [PCLK_SRC_MUX_0_CLK] = &dsi0pll_pclk_src_mux.clkr.hw,
1502 [PCLK_SRC_0_CLK] = &dsi0pll_pclk_src.clkr.hw,
1503 [PCLK_MUX_0_CLK] = &dsi0pll_pclk_mux.clkr.hw,
1504 [VCO_CLK_1] = &dsi1pll_vco_clk.hw,
Rajkumar Subbiahb6adb3a2017-06-16 17:08:48 -04001505 [PLL_OUT_DIV_1_CLK] = &dsi1pll_pll_out_div.clkr.hw,
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -08001506 [BITCLK_SRC_1_CLK] = &dsi1pll_bitclk_src.clkr.hw,
1507 [BYTECLK_SRC_1_CLK] = &dsi1pll_byteclk_src.hw,
Rajkumar Subbiahb6adb3a2017-06-16 17:08:48 -04001508 [POST_BIT_DIV_1_CLK] = &dsi1pll_post_bit_div.hw,
1509 [POST_VCO_DIV_1_CLK] = &dsi1pll_post_vco_div.hw,
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -08001510 [BYTECLK_MUX_1_CLK] = &dsi1pll_byteclk_mux.clkr.hw,
1511 [PCLK_SRC_MUX_1_CLK] = &dsi1pll_pclk_src_mux.clkr.hw,
1512 [PCLK_SRC_1_CLK] = &dsi1pll_pclk_src.clkr.hw,
1513 [PCLK_MUX_1_CLK] = &dsi1pll_pclk_mux.clkr.hw,
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -08001514};
1515
1516int dsi_pll_clock_register_10nm(struct platform_device *pdev,
Aravind Venkateswaran5773d732016-03-08 16:55:01 -08001517 struct mdss_pll_resources *pll_res)
1518{
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -08001519 int rc = 0, ndx, i;
1520 struct clk *clk;
1521 struct clk_onecell_data *clk_data;
1522 int num_clks = ARRAY_SIZE(mdss_dsi_pllcc_10nm);
1523 struct regmap *rmap;
Aravind Venkateswaran5773d732016-03-08 16:55:01 -08001524
1525 if (!pdev || !pdev->dev.of_node ||
1526 !pll_res || !pll_res->pll_base || !pll_res->phy_base) {
1527 pr_err("Invalid params\n");
1528 return -EINVAL;
1529 }
1530
1531 ndx = pll_res->index;
1532
1533 if (ndx >= DSI_PLL_MAX) {
1534 pr_err("pll index(%d) NOT supported\n", ndx);
1535 return -EINVAL;
1536 }
1537
1538 pll_rsc_db[ndx] = pll_res;
Aravind Venkateswaran5773d732016-03-08 16:55:01 -08001539 plls[ndx].rsc = pll_res;
Shashank Babu Chinta Venkata4302e8f2017-04-17 13:46:36 -07001540 pll_res->priv = &plls[ndx];
Aravind Venkateswaran5773d732016-03-08 16:55:01 -08001541 pll_res->vco_delay = VCO_DELAY_USEC;
Aravind Venkateswaran5773d732016-03-08 16:55:01 -08001542
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -08001543 clk_data = devm_kzalloc(&pdev->dev, sizeof(struct clk_onecell_data),
1544 GFP_KERNEL);
1545 if (!clk_data)
1546 return -ENOMEM;
Aravind Venkateswaran5773d732016-03-08 16:55:01 -08001547
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -08001548 clk_data->clks = devm_kzalloc(&pdev->dev, (num_clks *
1549 sizeof(struct clk *)), GFP_KERNEL);
1550 if (!clk_data->clks) {
1551 devm_kfree(&pdev->dev, clk_data);
1552 return -ENOMEM;
Aravind Venkateswaran5773d732016-03-08 16:55:01 -08001553 }
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -08001554 clk_data->clk_num = num_clks;
Aravind Venkateswaran5773d732016-03-08 16:55:01 -08001555
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -08001556 /* Establish client data */
1557 if (ndx == 0) {
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -08001558
Rajkumar Subbiahb6adb3a2017-06-16 17:08:48 -04001559 rmap = devm_regmap_init(&pdev->dev, &pll_regmap_bus,
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -08001560 pll_res, &dsi_pll_10nm_config);
Rajkumar Subbiahb6adb3a2017-06-16 17:08:48 -04001561 dsi0pll_pll_out_div.clkr.regmap = rmap;
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -08001562
1563 rmap = devm_regmap_init(&pdev->dev, &bitclk_src_regmap_bus,
1564 pll_res, &dsi_pll_10nm_config);
1565 dsi0pll_bitclk_src.clkr.regmap = rmap;
1566
1567 rmap = devm_regmap_init(&pdev->dev, &pclk_src_regmap_bus,
1568 pll_res, &dsi_pll_10nm_config);
1569 dsi0pll_pclk_src.clkr.regmap = rmap;
1570
1571 rmap = devm_regmap_init(&pdev->dev, &mdss_mux_regmap_bus,
1572 pll_res, &dsi_pll_10nm_config);
1573 dsi0pll_pclk_mux.clkr.regmap = rmap;
1574
Shashank Babu Chinta Venkatae0ce0122017-11-27 17:23:23 -08001575 rmap = devm_regmap_init(&pdev->dev, &pclk_src_mux_regmap_bus,
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -08001576 pll_res, &dsi_pll_10nm_config);
1577 dsi0pll_pclk_src_mux.clkr.regmap = rmap;
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -08001578 rmap = devm_regmap_init(&pdev->dev, &mdss_mux_regmap_bus,
1579 pll_res, &dsi_pll_10nm_config);
1580 dsi0pll_byteclk_mux.clkr.regmap = rmap;
1581
Shashank Babu Chinta Venkata4302e8f2017-04-17 13:46:36 -07001582 dsi0pll_vco_clk.priv = pll_res;
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -08001583 for (i = VCO_CLK_0; i <= PCLK_MUX_0_CLK; i++) {
1584 clk = devm_clk_register(&pdev->dev,
1585 mdss_dsi_pllcc_10nm[i]);
1586 if (IS_ERR(clk)) {
1587 pr_err("clk registration failed for DSI clock:%d\n",
1588 pll_res->index);
1589 rc = -EINVAL;
1590 goto clk_register_fail;
1591 }
1592 clk_data->clks[i] = clk;
1593
1594 }
1595
1596 rc = of_clk_add_provider(pdev->dev.of_node,
1597 of_clk_src_onecell_get, clk_data);
1598
1599
1600 } else {
Rajkumar Subbiahb6adb3a2017-06-16 17:08:48 -04001601 rmap = devm_regmap_init(&pdev->dev, &pll_regmap_bus,
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -08001602 pll_res, &dsi_pll_10nm_config);
Rajkumar Subbiahb6adb3a2017-06-16 17:08:48 -04001603 dsi1pll_pll_out_div.clkr.regmap = rmap;
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -08001604
1605 rmap = devm_regmap_init(&pdev->dev, &bitclk_src_regmap_bus,
1606 pll_res, &dsi_pll_10nm_config);
1607 dsi1pll_bitclk_src.clkr.regmap = rmap;
1608
1609 rmap = devm_regmap_init(&pdev->dev, &pclk_src_regmap_bus,
1610 pll_res, &dsi_pll_10nm_config);
1611 dsi1pll_pclk_src.clkr.regmap = rmap;
1612
Shashank Babu Chinta Venkatae0ce0122017-11-27 17:23:23 -08001613 rmap = devm_regmap_init(&pdev->dev, &mdss_mux_regmap_bus,
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -08001614 pll_res, &dsi_pll_10nm_config);
1615 dsi1pll_pclk_mux.clkr.regmap = rmap;
1616
Shashank Babu Chinta Venkatae0ce0122017-11-27 17:23:23 -08001617 rmap = devm_regmap_init(&pdev->dev, &pclk_src_mux_regmap_bus,
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -08001618 pll_res, &dsi_pll_10nm_config);
1619 dsi1pll_pclk_src_mux.clkr.regmap = rmap;
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -08001620 rmap = devm_regmap_init(&pdev->dev, &mdss_mux_regmap_bus,
1621 pll_res, &dsi_pll_10nm_config);
1622 dsi1pll_byteclk_mux.clkr.regmap = rmap;
Shashank Babu Chinta Venkata4302e8f2017-04-17 13:46:36 -07001623 dsi1pll_vco_clk.priv = pll_res;
Shashank Babu Chinta Venkata704b93b2017-02-06 15:23:11 -08001624
1625 for (i = VCO_CLK_1; i <= PCLK_MUX_1_CLK; i++) {
1626 clk = devm_clk_register(&pdev->dev,
1627 mdss_dsi_pllcc_10nm[i]);
1628 if (IS_ERR(clk)) {
1629 pr_err("clk registration failed for DSI clock:%d\n",
1630 pll_res->index);
1631 rc = -EINVAL;
1632 goto clk_register_fail;
1633 }
1634 clk_data->clks[i] = clk;
1635
1636 }
1637
1638 rc = of_clk_add_provider(pdev->dev.of_node,
1639 of_clk_src_onecell_get, clk_data);
1640 }
1641 if (!rc) {
1642 pr_info("Registered DSI PLL ndx=%d, clocks successfully", ndx);
1643
1644 return rc;
1645 }
1646clk_register_fail:
1647 devm_kfree(&pdev->dev, clk_data->clks);
1648 devm_kfree(&pdev->dev, clk_data);
Aravind Venkateswaran5773d732016-03-08 16:55:01 -08001649 return rc;
1650}