brintos

brintos / linux-shallow public Read only

0
0
Text · 30.1 KiB · 1723f0e Raw
1100 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (c) 2016, The Linux Foundation. All rights reserved.4 */5 6#include <linux/clk.h>7#include <linux/clk-provider.h>8#include <linux/delay.h>9 10#include "dsi_phy.h"11#include "dsi.xml.h"12#include "dsi_phy_14nm.xml.h"13 14#define PHY_14NM_CKLN_IDX	415 16/*17 * DSI PLL 14nm - clock diagram (eg: DSI0):18 *19 *         dsi0n1_postdiv_clk20 *                         |21 *                         |22 *                 +----+  |  +----+23 *  dsi0vco_clk ---| n1 |--o--| /8 |-- dsi0pllbyte24 *                 +----+  |  +----+25 *                         |           dsi0n1_postdivby2_clk26 *                         |   +----+  |27 *                         o---| /2 |--o--|\28 *                         |   +----+     | \   +----+29 *                         |              |  |--| n2 |-- dsi0pll30 *                         o--------------| /   +----+31 *                                        |/32 */33 34#define POLL_MAX_READS			1535#define POLL_TIMEOUT_US			100036 37#define VCO_REF_CLK_RATE		1920000038#define VCO_MIN_RATE			1300000000UL39#define VCO_MAX_RATE			2600000000UL40 41struct dsi_pll_config {42	u64 vco_current_rate;43 44	u32 ssc_en;	/* SSC enable/disable */45 46	/* fixed params */47	u32 plllock_cnt;48	u32 ssc_center;49	u32 ssc_adj_period;50	u32 ssc_spread;51	u32 ssc_freq;52 53	/* calculated */54	u32 dec_start;55	u32 div_frac_start;56	u32 ssc_period;57	u32 ssc_step_size;58	u32 plllock_cmp;59	u32 pll_vco_div_ref;60	u32 pll_vco_count;61	u32 pll_kvco_div_ref;62	u32 pll_kvco_count;63};64 65struct pll_14nm_cached_state {66	unsigned long vco_rate;67	u8 n2postdiv;68	u8 n1postdiv;69};70 71struct dsi_pll_14nm {72	struct clk_hw clk_hw;73 74	struct msm_dsi_phy *phy;75 76	/* protects REG_DSI_14nm_PHY_CMN_CLK_CFG0 register */77	spinlock_t postdiv_lock;78 79	struct pll_14nm_cached_state cached_state;80 81	struct dsi_pll_14nm *slave;82};83 84#define to_pll_14nm(x)	container_of(x, struct dsi_pll_14nm, clk_hw)85 86/*87 * Private struct for N1/N2 post-divider clocks. These clocks are similar to88 * the generic clk_divider class of clocks. The only difference is that it89 * also sets the slave DSI PLL's post-dividers if in bonded DSI mode90 */91struct dsi_pll_14nm_postdiv {92	struct clk_hw hw;93 94	/* divider params */95	u8 shift;96	u8 width;97	u8 flags; /* same flags as used by clk_divider struct */98 99	struct dsi_pll_14nm *pll;100};101 102#define to_pll_14nm_postdiv(_hw) container_of(_hw, struct dsi_pll_14nm_postdiv, hw)103 104/*105 * Global list of private DSI PLL struct pointers. We need this for bonded DSI106 * mode, where the master PLL's clk_ops needs access the slave's private data107 */108static struct dsi_pll_14nm *pll_14nm_list[DSI_MAX];109 110static bool pll_14nm_poll_for_ready(struct dsi_pll_14nm *pll_14nm,111				    u32 nb_tries, u32 timeout_us)112{113	bool pll_locked = false, pll_ready = false;114	void __iomem *base = pll_14nm->phy->pll_base;115	u32 tries, val;116 117	tries = nb_tries;118	while (tries--) {119		val = readl(base + REG_DSI_14nm_PHY_PLL_RESET_SM_READY_STATUS);120		pll_locked = !!(val & BIT(5));121 122		if (pll_locked)123			break;124 125		udelay(timeout_us);126	}127 128	if (!pll_locked)129		goto out;130 131	tries = nb_tries;132	while (tries--) {133		val = readl(base + REG_DSI_14nm_PHY_PLL_RESET_SM_READY_STATUS);134		pll_ready = !!(val & BIT(0));135 136		if (pll_ready)137			break;138 139		udelay(timeout_us);140	}141 142out:143	DBG("DSI PLL is %slocked, %sready", pll_locked ? "" : "*not* ", pll_ready ? "" : "*not* ");144 145	return pll_locked && pll_ready;146}147 148static void dsi_pll_14nm_config_init(struct dsi_pll_config *pconf)149{150	/* fixed input */151	pconf->plllock_cnt = 1;152 153	/*154	 * SSC is enabled by default. We might need DT props for configuring155	 * some SSC params like PPM and center/down spread etc.156	 */157	pconf->ssc_en = 1;158	pconf->ssc_center = 0;		/* down spread by default */159	pconf->ssc_spread = 5;		/* PPM / 1000 */160	pconf->ssc_freq = 31500;	/* default recommended */161	pconf->ssc_adj_period = 37;162}163 164#define CEIL(x, y)		(((x) + ((y) - 1)) / (y))165 166static void pll_14nm_ssc_calc(struct dsi_pll_14nm *pll, struct dsi_pll_config *pconf)167{168	u32 period, ssc_period;169	u32 ref, rem;170	u64 step_size;171 172	DBG("vco=%lld ref=%d", pconf->vco_current_rate, VCO_REF_CLK_RATE);173 174	ssc_period = pconf->ssc_freq / 500;175	period = (u32)VCO_REF_CLK_RATE / 1000;176	ssc_period  = CEIL(period, ssc_period);177	ssc_period -= 1;178	pconf->ssc_period = ssc_period;179 180	DBG("ssc freq=%d spread=%d period=%d", pconf->ssc_freq,181	    pconf->ssc_spread, pconf->ssc_period);182 183	step_size = (u32)pconf->vco_current_rate;184	ref = VCO_REF_CLK_RATE;185	ref /= 1000;186	step_size = div_u64(step_size, ref);187	step_size <<= 20;188	step_size = div_u64(step_size, 1000);189	step_size *= pconf->ssc_spread;190	step_size = div_u64(step_size, 1000);191	step_size *= (pconf->ssc_adj_period + 1);192 193	rem = 0;194	step_size = div_u64_rem(step_size, ssc_period + 1, &rem);195	if (rem)196		step_size++;197 198	DBG("step_size=%lld", step_size);199 200	step_size &= 0x0ffff;	/* take lower 16 bits */201 202	pconf->ssc_step_size = step_size;203}204 205static void pll_14nm_dec_frac_calc(struct dsi_pll_14nm *pll, struct dsi_pll_config *pconf)206{207	u64 multiplier = BIT(20);208	u64 dec_start_multiple, dec_start, pll_comp_val;209	u32 duration, div_frac_start;210	u64 vco_clk_rate = pconf->vco_current_rate;211	u64 fref = VCO_REF_CLK_RATE;212 213	DBG("vco_clk_rate=%lld ref_clk_rate=%lld", vco_clk_rate, fref);214 215	dec_start_multiple = div_u64(vco_clk_rate * multiplier, fref);216	dec_start = div_u64_rem(dec_start_multiple, multiplier, &div_frac_start);217 218	pconf->dec_start = (u32)dec_start;219	pconf->div_frac_start = div_frac_start;220 221	if (pconf->plllock_cnt == 0)222		duration = 1024;223	else if (pconf->plllock_cnt == 1)224		duration = 256;225	else if (pconf->plllock_cnt == 2)226		duration = 128;227	else228		duration = 32;229 230	pll_comp_val = duration * dec_start_multiple;231	pll_comp_val = div_u64(pll_comp_val, multiplier);232	do_div(pll_comp_val, 10);233 234	pconf->plllock_cmp = (u32)pll_comp_val;235}236 237static u32 pll_14nm_kvco_slop(u32 vrate)238{239	u32 slop = 0;240 241	if (vrate > VCO_MIN_RATE && vrate <= 1800000000UL)242		slop =  600;243	else if (vrate > 1800000000UL && vrate < 2300000000UL)244		slop = 400;245	else if (vrate > 2300000000UL && vrate < VCO_MAX_RATE)246		slop = 280;247 248	return slop;249}250 251static void pll_14nm_calc_vco_count(struct dsi_pll_14nm *pll, struct dsi_pll_config *pconf)252{253	u64 vco_clk_rate = pconf->vco_current_rate;254	u64 fref = VCO_REF_CLK_RATE;255	u32 vco_measure_time = 5;256	u32 kvco_measure_time = 5;257	u64 data;258	u32 cnt;259 260	data = fref * vco_measure_time;261	do_div(data, 1000000);262	data &= 0x03ff;	/* 10 bits */263	data -= 2;264	pconf->pll_vco_div_ref = data;265 266	data = div_u64(vco_clk_rate, 1000000);	/* unit is Mhz */267	data *= vco_measure_time;268	do_div(data, 10);269	pconf->pll_vco_count = data;270 271	data = fref * kvco_measure_time;272	do_div(data, 1000000);273	data &= 0x03ff;	/* 10 bits */274	data -= 1;275	pconf->pll_kvco_div_ref = data;276 277	cnt = pll_14nm_kvco_slop(vco_clk_rate);278	cnt *= 2;279	cnt /= 100;280	cnt *= kvco_measure_time;281	pconf->pll_kvco_count = cnt;282}283 284static void pll_db_commit_ssc(struct dsi_pll_14nm *pll, struct dsi_pll_config *pconf)285{286	void __iomem *base = pll->phy->pll_base;287	u8 data;288 289	data = pconf->ssc_adj_period;290	data &= 0x0ff;291	writel(data, base + REG_DSI_14nm_PHY_PLL_SSC_ADJ_PER1);292	data = (pconf->ssc_adj_period >> 8);293	data &= 0x03;294	writel(data, base + REG_DSI_14nm_PHY_PLL_SSC_ADJ_PER2);295 296	data = pconf->ssc_period;297	data &= 0x0ff;298	writel(data, base + REG_DSI_14nm_PHY_PLL_SSC_PER1);299	data = (pconf->ssc_period >> 8);300	data &= 0x0ff;301	writel(data, base + REG_DSI_14nm_PHY_PLL_SSC_PER2);302 303	data = pconf->ssc_step_size;304	data &= 0x0ff;305	writel(data, base + REG_DSI_14nm_PHY_PLL_SSC_STEP_SIZE1);306	data = (pconf->ssc_step_size >> 8);307	data &= 0x0ff;308	writel(data, base + REG_DSI_14nm_PHY_PLL_SSC_STEP_SIZE2);309 310	data = (pconf->ssc_center & 0x01);311	data <<= 1;312	data |= 0x01; /* enable */313	writel(data, base + REG_DSI_14nm_PHY_PLL_SSC_EN_CENTER);314 315	wmb();	/* make sure register committed */316}317 318static void pll_db_commit_common(struct dsi_pll_14nm *pll,319				 struct dsi_pll_config *pconf)320{321	void __iomem *base = pll->phy->pll_base;322	u8 data;323 324	/* confgiure the non frequency dependent pll registers */325	data = 0;326	writel(data, base + REG_DSI_14nm_PHY_PLL_SYSCLK_EN_RESET);327 328	writel(1, base + REG_DSI_14nm_PHY_PLL_TXCLK_EN);329 330	writel(48, base + REG_DSI_14nm_PHY_PLL_RESETSM_CNTRL);331	/* bandgap_timer */332	writel(4 << 3, base + REG_DSI_14nm_PHY_PLL_RESETSM_CNTRL2);333	/* pll_wakeup_timer */334	writel(5, base + REG_DSI_14nm_PHY_PLL_RESETSM_CNTRL5);335 336	data = pconf->pll_vco_div_ref & 0xff;337	writel(data, base + REG_DSI_14nm_PHY_PLL_VCO_DIV_REF1);338	data = (pconf->pll_vco_div_ref >> 8) & 0x3;339	writel(data, base + REG_DSI_14nm_PHY_PLL_VCO_DIV_REF2);340 341	data = pconf->pll_kvco_div_ref & 0xff;342	writel(data, base + REG_DSI_14nm_PHY_PLL_KVCO_DIV_REF1);343	data = (pconf->pll_kvco_div_ref >> 8) & 0x3;344	writel(data, base + REG_DSI_14nm_PHY_PLL_KVCO_DIV_REF2);345 346	writel(16, base + REG_DSI_14nm_PHY_PLL_PLL_MISC1);347 348	writel(4, base + REG_DSI_14nm_PHY_PLL_IE_TRIM);349 350	writel(4, base + REG_DSI_14nm_PHY_PLL_IP_TRIM);351 352	writel(1 << 3 | 1, base + REG_DSI_14nm_PHY_PLL_CP_SET_CUR);353 354	writel(0 << 3 | 0, base + REG_DSI_14nm_PHY_PLL_PLL_ICPCSET);355 356	writel(0 << 3 | 0, base + REG_DSI_14nm_PHY_PLL_PLL_ICPMSET);357 358	writel(4 << 3 | 4, base + REG_DSI_14nm_PHY_PLL_PLL_ICP_SET);359 360	writel(1 << 4 | 11, base + REG_DSI_14nm_PHY_PLL_PLL_LPF1);361 362	writel(7, base + REG_DSI_14nm_PHY_PLL_IPTAT_TRIM);363 364	writel(1 << 4 | 2, base + REG_DSI_14nm_PHY_PLL_PLL_CRCTRL);365}366 367static void pll_14nm_software_reset(struct dsi_pll_14nm *pll_14nm)368{369	void __iomem *cmn_base = pll_14nm->phy->base;370 371	/* de assert pll start and apply pll sw reset */372 373	/* stop pll */374	writel(0, cmn_base + REG_DSI_14nm_PHY_CMN_PLL_CNTRL);375 376	/* pll sw reset */377	writel(0x20, cmn_base + REG_DSI_14nm_PHY_CMN_CTRL_1);378	udelay(10);379	wmb();	/* make sure register committed */380 381	writel(0, cmn_base + REG_DSI_14nm_PHY_CMN_CTRL_1);382	wmb();	/* make sure register committed */383}384 385static void pll_db_commit_14nm(struct dsi_pll_14nm *pll,386			       struct dsi_pll_config *pconf)387{388	void __iomem *base = pll->phy->pll_base;389	void __iomem *cmn_base = pll->phy->base;390	u8 data;391 392	DBG("DSI%d PLL", pll->phy->id);393 394	writel(0x3c, cmn_base + REG_DSI_14nm_PHY_CMN_LDO_CNTRL);395 396	pll_db_commit_common(pll, pconf);397 398	pll_14nm_software_reset(pll);399 400	/* Use the /2 path in Mux */401	writel(1, cmn_base + REG_DSI_14nm_PHY_CMN_CLK_CFG1);402 403	data = 0xff; /* data, clk, pll normal operation */404	writel(data, cmn_base + REG_DSI_14nm_PHY_CMN_CTRL_0);405 406	/* configure the frequency dependent pll registers */407	data = pconf->dec_start;408	writel(data, base + REG_DSI_14nm_PHY_PLL_DEC_START);409 410	data = pconf->div_frac_start & 0xff;411	writel(data, base + REG_DSI_14nm_PHY_PLL_DIV_FRAC_START1);412	data = (pconf->div_frac_start >> 8) & 0xff;413	writel(data, base + REG_DSI_14nm_PHY_PLL_DIV_FRAC_START2);414	data = (pconf->div_frac_start >> 16) & 0xf;415	writel(data, base + REG_DSI_14nm_PHY_PLL_DIV_FRAC_START3);416 417	data = pconf->plllock_cmp & 0xff;418	writel(data, base + REG_DSI_14nm_PHY_PLL_PLLLOCK_CMP1);419 420	data = (pconf->plllock_cmp >> 8) & 0xff;421	writel(data, base + REG_DSI_14nm_PHY_PLL_PLLLOCK_CMP2);422 423	data = (pconf->plllock_cmp >> 16) & 0x3;424	writel(data, base + REG_DSI_14nm_PHY_PLL_PLLLOCK_CMP3);425 426	data = pconf->plllock_cnt << 1 | 0 << 3; /* plllock_rng */427	writel(data, base + REG_DSI_14nm_PHY_PLL_PLLLOCK_CMP_EN);428 429	data = pconf->pll_vco_count & 0xff;430	writel(data, base + REG_DSI_14nm_PHY_PLL_VCO_COUNT1);431	data = (pconf->pll_vco_count >> 8) & 0xff;432	writel(data, base + REG_DSI_14nm_PHY_PLL_VCO_COUNT2);433 434	data = pconf->pll_kvco_count & 0xff;435	writel(data, base + REG_DSI_14nm_PHY_PLL_KVCO_COUNT1);436	data = (pconf->pll_kvco_count >> 8) & 0x3;437	writel(data, base + REG_DSI_14nm_PHY_PLL_KVCO_COUNT2);438 439	/*440	 * High nibble configures the post divider internal to the VCO. It's441	 * fixed to divide by 1 for now.442	 *443	 * 0: divided by 1444	 * 1: divided by 2445	 * 2: divided by 4446	 * 3: divided by 8447	 */448	writel(0 << 4 | 3, base + REG_DSI_14nm_PHY_PLL_PLL_LPF2_POSTDIV);449 450	if (pconf->ssc_en)451		pll_db_commit_ssc(pll, pconf);452 453	wmb();	/* make sure register committed */454}455 456/*457 * VCO clock Callbacks458 */459static int dsi_pll_14nm_vco_set_rate(struct clk_hw *hw, unsigned long rate,460				     unsigned long parent_rate)461{462	struct dsi_pll_14nm *pll_14nm = to_pll_14nm(hw);463	struct dsi_pll_config conf;464 465	DBG("DSI PLL%d rate=%lu, parent's=%lu", pll_14nm->phy->id, rate,466	    parent_rate);467 468	dsi_pll_14nm_config_init(&conf);469	conf.vco_current_rate = rate;470 471	pll_14nm_dec_frac_calc(pll_14nm, &conf);472 473	if (conf.ssc_en)474		pll_14nm_ssc_calc(pll_14nm, &conf);475 476	pll_14nm_calc_vco_count(pll_14nm, &conf);477 478	/* commit the slave DSI PLL registers if we're master. Note that we479	 * don't lock the slave PLL. We just ensure that the PLL/PHY registers480	 * of the master and slave are identical481	 */482	if (pll_14nm->phy->usecase == MSM_DSI_PHY_MASTER) {483		struct dsi_pll_14nm *pll_14nm_slave = pll_14nm->slave;484 485		pll_db_commit_14nm(pll_14nm_slave, &conf);486	}487 488	pll_db_commit_14nm(pll_14nm, &conf);489 490	return 0;491}492 493static unsigned long dsi_pll_14nm_vco_recalc_rate(struct clk_hw *hw,494						  unsigned long parent_rate)495{496	struct dsi_pll_14nm *pll_14nm = to_pll_14nm(hw);497	void __iomem *base = pll_14nm->phy->pll_base;498	u64 vco_rate, multiplier = BIT(20);499	u32 div_frac_start;500	u32 dec_start;501	u64 ref_clk = parent_rate;502 503	dec_start = readl(base + REG_DSI_14nm_PHY_PLL_DEC_START);504	dec_start &= 0x0ff;505 506	DBG("dec_start = %x", dec_start);507 508	div_frac_start = (readl(base + REG_DSI_14nm_PHY_PLL_DIV_FRAC_START3)509				& 0xf) << 16;510	div_frac_start |= (readl(base + REG_DSI_14nm_PHY_PLL_DIV_FRAC_START2)511				& 0xff) << 8;512	div_frac_start |= readl(base + REG_DSI_14nm_PHY_PLL_DIV_FRAC_START1)513				& 0xff;514 515	DBG("div_frac_start = %x", div_frac_start);516 517	vco_rate = ref_clk * dec_start;518 519	vco_rate += ((ref_clk * div_frac_start) / multiplier);520 521	/*522	 * Recalculating the rate from dec_start and frac_start doesn't end up523	 * the rate we originally set. Convert the freq to KHz, round it up and524	 * convert it back to MHz.525	 */526	vco_rate = DIV_ROUND_UP_ULL(vco_rate, 1000) * 1000;527 528	DBG("returning vco rate = %lu", (unsigned long)vco_rate);529 530	return (unsigned long)vco_rate;531}532 533static int dsi_pll_14nm_vco_prepare(struct clk_hw *hw)534{535	struct dsi_pll_14nm *pll_14nm = to_pll_14nm(hw);536	void __iomem *base = pll_14nm->phy->pll_base;537	void __iomem *cmn_base = pll_14nm->phy->base;538	bool locked;539 540	DBG("");541 542	if (unlikely(pll_14nm->phy->pll_on))543		return 0;544 545	if (dsi_pll_14nm_vco_recalc_rate(hw, VCO_REF_CLK_RATE) == 0)546		dsi_pll_14nm_vco_set_rate(hw, pll_14nm->phy->cfg->min_pll_rate, VCO_REF_CLK_RATE);547 548	writel(0x10, base + REG_DSI_14nm_PHY_PLL_VREF_CFG1);549	writel(1, cmn_base + REG_DSI_14nm_PHY_CMN_PLL_CNTRL);550 551	locked = pll_14nm_poll_for_ready(pll_14nm, POLL_MAX_READS,552					 POLL_TIMEOUT_US);553 554	if (unlikely(!locked)) {555		DRM_DEV_ERROR(&pll_14nm->phy->pdev->dev, "DSI PLL lock failed\n");556		return -EINVAL;557	}558 559	DBG("DSI PLL lock success");560	pll_14nm->phy->pll_on = true;561 562	return 0;563}564 565static void dsi_pll_14nm_vco_unprepare(struct clk_hw *hw)566{567	struct dsi_pll_14nm *pll_14nm = to_pll_14nm(hw);568	void __iomem *cmn_base = pll_14nm->phy->base;569 570	DBG("");571 572	if (unlikely(!pll_14nm->phy->pll_on))573		return;574 575	writel(0, cmn_base + REG_DSI_14nm_PHY_CMN_PLL_CNTRL);576 577	pll_14nm->phy->pll_on = false;578}579 580static long dsi_pll_14nm_clk_round_rate(struct clk_hw *hw,581		unsigned long rate, unsigned long *parent_rate)582{583	struct dsi_pll_14nm *pll_14nm = to_pll_14nm(hw);584 585	if      (rate < pll_14nm->phy->cfg->min_pll_rate)586		return  pll_14nm->phy->cfg->min_pll_rate;587	else if (rate > pll_14nm->phy->cfg->max_pll_rate)588		return  pll_14nm->phy->cfg->max_pll_rate;589	else590		return rate;591}592 593static const struct clk_ops clk_ops_dsi_pll_14nm_vco = {594	.round_rate = dsi_pll_14nm_clk_round_rate,595	.set_rate = dsi_pll_14nm_vco_set_rate,596	.recalc_rate = dsi_pll_14nm_vco_recalc_rate,597	.prepare = dsi_pll_14nm_vco_prepare,598	.unprepare = dsi_pll_14nm_vco_unprepare,599};600 601/*602 * N1 and N2 post-divider clock callbacks603 */604#define div_mask(width)	((1 << (width)) - 1)605static unsigned long dsi_pll_14nm_postdiv_recalc_rate(struct clk_hw *hw,606						      unsigned long parent_rate)607{608	struct dsi_pll_14nm_postdiv *postdiv = to_pll_14nm_postdiv(hw);609	struct dsi_pll_14nm *pll_14nm = postdiv->pll;610	void __iomem *base = pll_14nm->phy->base;611	u8 shift = postdiv->shift;612	u8 width = postdiv->width;613	u32 val;614 615	DBG("DSI%d PLL parent rate=%lu", pll_14nm->phy->id, parent_rate);616 617	val = readl(base + REG_DSI_14nm_PHY_CMN_CLK_CFG0) >> shift;618	val &= div_mask(width);619 620	return divider_recalc_rate(hw, parent_rate, val, NULL,621				   postdiv->flags, width);622}623 624static long dsi_pll_14nm_postdiv_round_rate(struct clk_hw *hw,625					    unsigned long rate,626					    unsigned long *prate)627{628	struct dsi_pll_14nm_postdiv *postdiv = to_pll_14nm_postdiv(hw);629	struct dsi_pll_14nm *pll_14nm = postdiv->pll;630 631	DBG("DSI%d PLL parent rate=%lu", pll_14nm->phy->id, rate);632 633	return divider_round_rate(hw, rate, prate, NULL,634				  postdiv->width,635				  postdiv->flags);636}637 638static int dsi_pll_14nm_postdiv_set_rate(struct clk_hw *hw, unsigned long rate,639					 unsigned long parent_rate)640{641	struct dsi_pll_14nm_postdiv *postdiv = to_pll_14nm_postdiv(hw);642	struct dsi_pll_14nm *pll_14nm = postdiv->pll;643	void __iomem *base = pll_14nm->phy->base;644	spinlock_t *lock = &pll_14nm->postdiv_lock;645	u8 shift = postdiv->shift;646	u8 width = postdiv->width;647	unsigned int value;648	unsigned long flags = 0;649	u32 val;650 651	DBG("DSI%d PLL parent rate=%lu parent rate %lu", pll_14nm->phy->id, rate,652	    parent_rate);653 654	value = divider_get_val(rate, parent_rate, NULL, postdiv->width,655				postdiv->flags);656 657	spin_lock_irqsave(lock, flags);658 659	val = readl(base + REG_DSI_14nm_PHY_CMN_CLK_CFG0);660	val &= ~(div_mask(width) << shift);661 662	val |= value << shift;663	writel(val, base + REG_DSI_14nm_PHY_CMN_CLK_CFG0);664 665	/* If we're master in bonded DSI mode, then the slave PLL's post-dividers666	 * follow the master's post dividers667	 */668	if (pll_14nm->phy->usecase == MSM_DSI_PHY_MASTER) {669		struct dsi_pll_14nm *pll_14nm_slave = pll_14nm->slave;670		void __iomem *slave_base = pll_14nm_slave->phy->base;671 672		writel(val, slave_base + REG_DSI_14nm_PHY_CMN_CLK_CFG0);673	}674 675	spin_unlock_irqrestore(lock, flags);676 677	return 0;678}679 680static const struct clk_ops clk_ops_dsi_pll_14nm_postdiv = {681	.recalc_rate = dsi_pll_14nm_postdiv_recalc_rate,682	.round_rate = dsi_pll_14nm_postdiv_round_rate,683	.set_rate = dsi_pll_14nm_postdiv_set_rate,684};685 686/*687 * PLL Callbacks688 */689 690static void dsi_14nm_pll_save_state(struct msm_dsi_phy *phy)691{692	struct dsi_pll_14nm *pll_14nm = to_pll_14nm(phy->vco_hw);693	struct pll_14nm_cached_state *cached_state = &pll_14nm->cached_state;694	void __iomem *cmn_base = pll_14nm->phy->base;695	u32 data;696 697	data = readl(cmn_base + REG_DSI_14nm_PHY_CMN_CLK_CFG0);698 699	cached_state->n1postdiv = data & 0xf;700	cached_state->n2postdiv = (data >> 4) & 0xf;701 702	DBG("DSI%d PLL save state %x %x", pll_14nm->phy->id,703	    cached_state->n1postdiv, cached_state->n2postdiv);704 705	cached_state->vco_rate = clk_hw_get_rate(phy->vco_hw);706}707 708static int dsi_14nm_pll_restore_state(struct msm_dsi_phy *phy)709{710	struct dsi_pll_14nm *pll_14nm = to_pll_14nm(phy->vco_hw);711	struct pll_14nm_cached_state *cached_state = &pll_14nm->cached_state;712	void __iomem *cmn_base = pll_14nm->phy->base;713	u32 data;714	int ret;715 716	ret = dsi_pll_14nm_vco_set_rate(phy->vco_hw,717					cached_state->vco_rate, 0);718	if (ret) {719		DRM_DEV_ERROR(&pll_14nm->phy->pdev->dev,720			      "restore vco rate failed. ret=%d\n", ret);721		return ret;722	}723 724	data = cached_state->n1postdiv | (cached_state->n2postdiv << 4);725 726	DBG("DSI%d PLL restore state %x %x", pll_14nm->phy->id,727	    cached_state->n1postdiv, cached_state->n2postdiv);728 729	writel(data, cmn_base + REG_DSI_14nm_PHY_CMN_CLK_CFG0);730 731	/* also restore post-dividers for slave DSI PLL */732	if (phy->usecase == MSM_DSI_PHY_MASTER) {733		struct dsi_pll_14nm *pll_14nm_slave = pll_14nm->slave;734		void __iomem *slave_base = pll_14nm_slave->phy->base;735 736		writel(data, slave_base + REG_DSI_14nm_PHY_CMN_CLK_CFG0);737	}738 739	return 0;740}741 742static int dsi_14nm_set_usecase(struct msm_dsi_phy *phy)743{744	struct dsi_pll_14nm *pll_14nm = to_pll_14nm(phy->vco_hw);745	void __iomem *base = phy->pll_base;746	u32 clkbuflr_en, bandgap = 0;747 748	switch (phy->usecase) {749	case MSM_DSI_PHY_STANDALONE:750		clkbuflr_en = 0x1;751		break;752	case MSM_DSI_PHY_MASTER:753		clkbuflr_en = 0x3;754		pll_14nm->slave = pll_14nm_list[(pll_14nm->phy->id + 1) % DSI_MAX];755		break;756	case MSM_DSI_PHY_SLAVE:757		clkbuflr_en = 0x0;758		bandgap = 0x3;759		break;760	default:761		return -EINVAL;762	}763 764	writel(clkbuflr_en, base + REG_DSI_14nm_PHY_PLL_CLKBUFLR_EN);765	if (bandgap)766		writel(bandgap, base + REG_DSI_14nm_PHY_PLL_PLL_BANDGAP);767 768	return 0;769}770 771static struct clk_hw *pll_14nm_postdiv_register(struct dsi_pll_14nm *pll_14nm,772						const char *name,773						const struct clk_hw *parent_hw,774						unsigned long flags,775						u8 shift)776{777	struct dsi_pll_14nm_postdiv *pll_postdiv;778	struct device *dev = &pll_14nm->phy->pdev->dev;779	struct clk_init_data postdiv_init = {780		.parent_hws = (const struct clk_hw *[]) { parent_hw },781		.num_parents = 1,782		.name = name,783		.flags = flags,784		.ops = &clk_ops_dsi_pll_14nm_postdiv,785	};786	int ret;787 788	pll_postdiv = devm_kzalloc(dev, sizeof(*pll_postdiv), GFP_KERNEL);789	if (!pll_postdiv)790		return ERR_PTR(-ENOMEM);791 792	pll_postdiv->pll = pll_14nm;793	pll_postdiv->shift = shift;794	/* both N1 and N2 postdividers are 4 bits wide */795	pll_postdiv->width = 4;796	/* range of each divider is from 1 to 15 */797	pll_postdiv->flags = CLK_DIVIDER_ONE_BASED;798	pll_postdiv->hw.init = &postdiv_init;799 800	ret = devm_clk_hw_register(dev, &pll_postdiv->hw);801	if (ret)802		return ERR_PTR(ret);803 804	return &pll_postdiv->hw;805}806 807static int pll_14nm_register(struct dsi_pll_14nm *pll_14nm, struct clk_hw **provided_clocks)808{809	char clk_name[32];810	struct clk_init_data vco_init = {811		.parent_data = &(const struct clk_parent_data) {812			.fw_name = "ref",813		},814		.num_parents = 1,815		.name = clk_name,816		.flags = CLK_IGNORE_UNUSED,817		.ops = &clk_ops_dsi_pll_14nm_vco,818	};819	struct device *dev = &pll_14nm->phy->pdev->dev;820	struct clk_hw *hw, *n1_postdiv, *n1_postdivby2;821	int ret;822 823	DBG("DSI%d", pll_14nm->phy->id);824 825	snprintf(clk_name, sizeof(clk_name), "dsi%dvco_clk", pll_14nm->phy->id);826	pll_14nm->clk_hw.init = &vco_init;827 828	ret = devm_clk_hw_register(dev, &pll_14nm->clk_hw);829	if (ret)830		return ret;831 832	snprintf(clk_name, sizeof(clk_name), "dsi%dn1_postdiv_clk", pll_14nm->phy->id);833 834	/* N1 postdiv, bits 0-3 in REG_DSI_14nm_PHY_CMN_CLK_CFG0 */835	n1_postdiv = pll_14nm_postdiv_register(pll_14nm, clk_name,836			&pll_14nm->clk_hw, CLK_SET_RATE_PARENT, 0);837	if (IS_ERR(n1_postdiv))838		return PTR_ERR(n1_postdiv);839 840	snprintf(clk_name, sizeof(clk_name), "dsi%dpllbyte", pll_14nm->phy->id);841 842	/* DSI Byte clock = VCO_CLK / N1 / 8 */843	hw = devm_clk_hw_register_fixed_factor_parent_hw(dev, clk_name,844			n1_postdiv, CLK_SET_RATE_PARENT, 1, 8);845	if (IS_ERR(hw))846		return PTR_ERR(hw);847 848	provided_clocks[DSI_BYTE_PLL_CLK] = hw;849 850	snprintf(clk_name, sizeof(clk_name), "dsi%dn1_postdivby2_clk", pll_14nm->phy->id);851 852	/*853	 * Skip the mux for now, force DSICLK_SEL to 1, Add a /2 divider854	 * on the way. Don't let it set parent.855	 */856	n1_postdivby2 = devm_clk_hw_register_fixed_factor_parent_hw(dev,857			clk_name, n1_postdiv, 0, 1, 2);858	if (IS_ERR(n1_postdivby2))859		return PTR_ERR(n1_postdivby2);860 861	snprintf(clk_name, sizeof(clk_name), "dsi%dpll", pll_14nm->phy->id);862 863	/* DSI pixel clock = VCO_CLK / N1 / 2 / N2864	 * This is the output of N2 post-divider, bits 4-7 in865	 * REG_DSI_14nm_PHY_CMN_CLK_CFG0. Don't let it set parent.866	 */867	hw = pll_14nm_postdiv_register(pll_14nm, clk_name, n1_postdivby2,868			0, 4);869	if (IS_ERR(hw))870		return PTR_ERR(hw);871 872	provided_clocks[DSI_PIXEL_PLL_CLK] = hw;873 874	return 0;875}876 877static int dsi_pll_14nm_init(struct msm_dsi_phy *phy)878{879	struct platform_device *pdev = phy->pdev;880	struct dsi_pll_14nm *pll_14nm;881	int ret;882 883	if (!pdev)884		return -ENODEV;885 886	pll_14nm = devm_kzalloc(&pdev->dev, sizeof(*pll_14nm), GFP_KERNEL);887	if (!pll_14nm)888		return -ENOMEM;889 890	DBG("PLL%d", phy->id);891 892	pll_14nm_list[phy->id] = pll_14nm;893 894	spin_lock_init(&pll_14nm->postdiv_lock);895 896	pll_14nm->phy = phy;897 898	ret = pll_14nm_register(pll_14nm, phy->provided_clocks->hws);899	if (ret) {900		DRM_DEV_ERROR(&pdev->dev, "failed to register PLL: %d\n", ret);901		return ret;902	}903 904	phy->vco_hw = &pll_14nm->clk_hw;905 906	return 0;907}908 909static void dsi_14nm_dphy_set_timing(struct msm_dsi_phy *phy,910				     struct msm_dsi_dphy_timing *timing,911				     int lane_idx)912{913	void __iomem *base = phy->lane_base;914	bool clk_ln = (lane_idx == PHY_14NM_CKLN_IDX);915	u32 zero = clk_ln ? timing->clk_zero : timing->hs_zero;916	u32 prepare = clk_ln ? timing->clk_prepare : timing->hs_prepare;917	u32 trail = clk_ln ? timing->clk_trail : timing->hs_trail;918	u32 rqst = clk_ln ? timing->hs_rqst_ckln : timing->hs_rqst;919	u32 prep_dly = clk_ln ? timing->hs_prep_dly_ckln : timing->hs_prep_dly;920	u32 halfbyte_en = clk_ln ? timing->hs_halfbyte_en_ckln :921				   timing->hs_halfbyte_en;922 923	writel(DSI_14nm_PHY_LN_TIMING_CTRL_4_HS_EXIT(timing->hs_exit),924	       base + REG_DSI_14nm_PHY_LN_TIMING_CTRL_4(lane_idx));925	writel(DSI_14nm_PHY_LN_TIMING_CTRL_5_HS_ZERO(zero),926	       base + REG_DSI_14nm_PHY_LN_TIMING_CTRL_5(lane_idx));927	writel(DSI_14nm_PHY_LN_TIMING_CTRL_6_HS_PREPARE(prepare),928	       base + REG_DSI_14nm_PHY_LN_TIMING_CTRL_6(lane_idx));929	writel(DSI_14nm_PHY_LN_TIMING_CTRL_7_HS_TRAIL(trail),930	       base + REG_DSI_14nm_PHY_LN_TIMING_CTRL_7(lane_idx));931	writel(DSI_14nm_PHY_LN_TIMING_CTRL_8_HS_RQST(rqst),932	       base + REG_DSI_14nm_PHY_LN_TIMING_CTRL_8(lane_idx));933	writel(DSI_14nm_PHY_LN_CFG0_PREPARE_DLY(prep_dly),934	       base + REG_DSI_14nm_PHY_LN_CFG0(lane_idx));935	writel(halfbyte_en ? DSI_14nm_PHY_LN_CFG1_HALFBYTECLK_EN : 0,936	       base + REG_DSI_14nm_PHY_LN_CFG1(lane_idx));937	writel(DSI_14nm_PHY_LN_TIMING_CTRL_9_TA_GO(timing->ta_go) |938	       DSI_14nm_PHY_LN_TIMING_CTRL_9_TA_SURE(timing->ta_sure),939	       base + REG_DSI_14nm_PHY_LN_TIMING_CTRL_9(lane_idx));940	writel(DSI_14nm_PHY_LN_TIMING_CTRL_10_TA_GET(timing->ta_get),941	       base + REG_DSI_14nm_PHY_LN_TIMING_CTRL_10(lane_idx));942	writel(DSI_14nm_PHY_LN_TIMING_CTRL_11_TRIG3_CMD(0xa0),943	       base + REG_DSI_14nm_PHY_LN_TIMING_CTRL_11(lane_idx));944}945 946static int dsi_14nm_phy_enable(struct msm_dsi_phy *phy,947			       struct msm_dsi_phy_clk_request *clk_req)948{949	struct msm_dsi_dphy_timing *timing = &phy->timing;950	u32 data;951	int i;952	int ret;953	void __iomem *base = phy->base;954	void __iomem *lane_base = phy->lane_base;955	u32 glbl_test_ctrl;956 957	if (msm_dsi_dphy_timing_calc_v2(timing, clk_req)) {958		DRM_DEV_ERROR(&phy->pdev->dev,959			      "%s: D-PHY timing calculation failed\n",960			      __func__);961		return -EINVAL;962	}963 964	data = 0x1c;965	if (phy->usecase != MSM_DSI_PHY_STANDALONE)966		data |= DSI_14nm_PHY_CMN_LDO_CNTRL_VREG_CTRL(32);967	writel(data, base + REG_DSI_14nm_PHY_CMN_LDO_CNTRL);968 969	writel(0x1, base + REG_DSI_14nm_PHY_CMN_GLBL_TEST_CTRL);970 971	/* 4 data lanes + 1 clk lane configuration */972	for (i = 0; i < 5; i++) {973		writel(0x1d, lane_base + REG_DSI_14nm_PHY_LN_VREG_CNTRL(i));974 975		writel(0xff, lane_base + REG_DSI_14nm_PHY_LN_STRENGTH_CTRL_0(i));976		writel(i == PHY_14NM_CKLN_IDX ? 0x00 : 0x06,977		       lane_base + REG_DSI_14nm_PHY_LN_STRENGTH_CTRL_1(i));978 979		writel(i == PHY_14NM_CKLN_IDX ? 0x8f : 0x0f,980		       lane_base + REG_DSI_14nm_PHY_LN_CFG3(i));981		writel(0x10, lane_base + REG_DSI_14nm_PHY_LN_CFG2(i));982		writel(0, lane_base + REG_DSI_14nm_PHY_LN_TEST_DATAPATH(i));983		writel(0x88, lane_base + REG_DSI_14nm_PHY_LN_TEST_STR(i));984 985		dsi_14nm_dphy_set_timing(phy, timing, i);986	}987 988	/* Make sure PLL is not start */989	writel(0x00, base + REG_DSI_14nm_PHY_CMN_PLL_CNTRL);990 991	wmb(); /* make sure everything is written before reset and enable */992 993	/* reset digital block */994	writel(0x80, base + REG_DSI_14nm_PHY_CMN_CTRL_1);995	wmb(); /* ensure reset is asserted */996	udelay(100);997	writel(0x00, base + REG_DSI_14nm_PHY_CMN_CTRL_1);998 999	glbl_test_ctrl = readl(base + REG_DSI_14nm_PHY_CMN_GLBL_TEST_CTRL);1000	if (phy->id == DSI_1 && phy->usecase == MSM_DSI_PHY_SLAVE)1001		glbl_test_ctrl |= DSI_14nm_PHY_CMN_GLBL_TEST_CTRL_BITCLK_HS_SEL;1002	else1003		glbl_test_ctrl &= ~DSI_14nm_PHY_CMN_GLBL_TEST_CTRL_BITCLK_HS_SEL;1004	writel(glbl_test_ctrl, base + REG_DSI_14nm_PHY_CMN_GLBL_TEST_CTRL);1005	ret = dsi_14nm_set_usecase(phy);1006	if (ret) {1007		DRM_DEV_ERROR(&phy->pdev->dev, "%s: set pll usecase failed, %d\n",1008			      __func__, ret);1009		return ret;1010	}1011 1012	/* Remove power down from PLL and all lanes */1013	writel(0xff, base + REG_DSI_14nm_PHY_CMN_CTRL_0);1014 1015	return 0;1016}1017 1018static void dsi_14nm_phy_disable(struct msm_dsi_phy *phy)1019{1020	writel(0, phy->base + REG_DSI_14nm_PHY_CMN_GLBL_TEST_CTRL);1021	writel(0, phy->base + REG_DSI_14nm_PHY_CMN_CTRL_0);1022 1023	/* ensure that the phy is completely disabled */1024	wmb();1025}1026 1027static const struct regulator_bulk_data dsi_phy_14nm_17mA_regulators[] = {1028	{ .supply = "vcca", .init_load_uA = 17000 },1029};1030 1031static const struct regulator_bulk_data dsi_phy_14nm_73p4mA_regulators[] = {1032	{ .supply = "vcca", .init_load_uA = 73400 },1033};1034 1035const struct msm_dsi_phy_cfg dsi_phy_14nm_cfgs = {1036	.has_phy_lane = true,1037	.regulator_data = dsi_phy_14nm_17mA_regulators,1038	.num_regulators = ARRAY_SIZE(dsi_phy_14nm_17mA_regulators),1039	.ops = {1040		.enable = dsi_14nm_phy_enable,1041		.disable = dsi_14nm_phy_disable,1042		.pll_init = dsi_pll_14nm_init,1043		.save_pll_state = dsi_14nm_pll_save_state,1044		.restore_pll_state = dsi_14nm_pll_restore_state,1045	},1046	.min_pll_rate = VCO_MIN_RATE,1047	.max_pll_rate = VCO_MAX_RATE,1048	.io_start = { 0x994400, 0x996400 },1049	.num_dsi_phy = 2,1050};1051 1052const struct msm_dsi_phy_cfg dsi_phy_14nm_660_cfgs = {1053	.has_phy_lane = true,1054	.regulator_data = dsi_phy_14nm_73p4mA_regulators,1055	.num_regulators = ARRAY_SIZE(dsi_phy_14nm_73p4mA_regulators),1056	.ops = {1057		.enable = dsi_14nm_phy_enable,1058		.disable = dsi_14nm_phy_disable,1059		.pll_init = dsi_pll_14nm_init,1060		.save_pll_state = dsi_14nm_pll_save_state,1061		.restore_pll_state = dsi_14nm_pll_restore_state,1062	},1063	.min_pll_rate = VCO_MIN_RATE,1064	.max_pll_rate = VCO_MAX_RATE,1065	.io_start = { 0xc994400, 0xc996400 },1066	.num_dsi_phy = 2,1067};1068 1069const struct msm_dsi_phy_cfg dsi_phy_14nm_8953_cfgs = {1070	.has_phy_lane = true,1071	.regulator_data = dsi_phy_14nm_17mA_regulators,1072	.num_regulators = ARRAY_SIZE(dsi_phy_14nm_17mA_regulators),1073	.ops = {1074		.enable = dsi_14nm_phy_enable,1075		.disable = dsi_14nm_phy_disable,1076		.pll_init = dsi_pll_14nm_init,1077		.save_pll_state = dsi_14nm_pll_save_state,1078		.restore_pll_state = dsi_14nm_pll_restore_state,1079	},1080	.min_pll_rate = VCO_MIN_RATE,1081	.max_pll_rate = VCO_MAX_RATE,1082	.io_start = { 0x1a94400, 0x1a96400 },1083	.num_dsi_phy = 2,1084};1085 1086const struct msm_dsi_phy_cfg dsi_phy_14nm_2290_cfgs = {1087	.has_phy_lane = true,1088	.ops = {1089		.enable = dsi_14nm_phy_enable,1090		.disable = dsi_14nm_phy_disable,1091		.pll_init = dsi_pll_14nm_init,1092		.save_pll_state = dsi_14nm_pll_save_state,1093		.restore_pll_state = dsi_14nm_pll_restore_state,1094	},1095	.min_pll_rate = VCO_MIN_RATE,1096	.max_pll_rate = VCO_MAX_RATE,1097	.io_start = { 0x5e94400 },1098	.num_dsi_phy = 1,1099};1100