brintos

brintos / linux-shallow public Read only

0
0
Text · 27.6 KiB · 1383e3a Raw
957 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (c) 2015, The Linux Foundation. All rights reserved.4 */5 6#include <linux/clk.h>7#include <linux/clk-provider.h>8 9#include "dsi_phy.h"10#include "dsi.xml.h"11#include "dsi_phy_28nm.xml.h"12 13/*14 * DSI PLL 28nm - clock diagram (eg: DSI0):15 *16 *         dsi0analog_postdiv_clk17 *                             |         dsi0indirect_path_div2_clk18 *                             |          |19 *                   +------+  |  +----+  |  |\   dsi0byte_mux20 *  dsi0vco_clk --o--| DIV1 |--o--| /2 |--o--| \   |21 *                |  +------+     +----+     | m|  |  +----+22 *                |                          | u|--o--| /4 |-- dsi0pllbyte23 *                |                          | x|     +----+24 *                o--------------------------| /25 *                |                          |/26 *                |          +------+27 *                o----------| DIV3 |------------------------- dsi0pll28 *                           +------+29 */30 31#define POLL_MAX_READS			1032#define POLL_TIMEOUT_US		5033 34#define VCO_REF_CLK_RATE		1920000035#define VCO_MIN_RATE			35000000036#define VCO_MAX_RATE			75000000037 38/* v2.0.0 28nm LP implementation */39#define DSI_PHY_28NM_QUIRK_PHY_LP	BIT(0)40#define DSI_PHY_28NM_QUIRK_PHY_8226	BIT(1)41 42#define LPFR_LUT_SIZE			1043struct lpfr_cfg {44	unsigned long vco_rate;45	u32 resistance;46};47 48/* Loop filter resistance: */49static const struct lpfr_cfg lpfr_lut[LPFR_LUT_SIZE] = {50	{ 479500000,  8 },51	{ 480000000, 11 },52	{ 575500000,  8 },53	{ 576000000, 12 },54	{ 610500000,  8 },55	{ 659500000,  9 },56	{ 671500000, 10 },57	{ 672000000, 14 },58	{ 708500000, 10 },59	{ 750000000, 11 },60};61 62struct pll_28nm_cached_state {63	unsigned long vco_rate;64	u8 postdiv3;65	u8 postdiv1;66	u8 byte_mux;67};68 69struct dsi_pll_28nm {70	struct clk_hw clk_hw;71 72	struct msm_dsi_phy *phy;73 74	struct pll_28nm_cached_state cached_state;75};76 77#define to_pll_28nm(x)	container_of(x, struct dsi_pll_28nm, clk_hw)78 79static bool pll_28nm_poll_for_ready(struct dsi_pll_28nm *pll_28nm,80				u32 nb_tries, u32 timeout_us)81{82	bool pll_locked = false;83	u32 val;84 85	while (nb_tries--) {86		val = readl(pll_28nm->phy->pll_base + REG_DSI_28nm_PHY_PLL_STATUS);87		pll_locked = !!(val & DSI_28nm_PHY_PLL_STATUS_PLL_RDY);88 89		if (pll_locked)90			break;91 92		udelay(timeout_us);93	}94	DBG("DSI PLL is %slocked", pll_locked ? "" : "*not* ");95 96	return pll_locked;97}98 99static void pll_28nm_software_reset(struct dsi_pll_28nm *pll_28nm)100{101	void __iomem *base = pll_28nm->phy->pll_base;102 103	/*104	 * Add HW recommended delays after toggling the software105	 * reset bit off and back on.106	 */107	writel(DSI_28nm_PHY_PLL_TEST_CFG_PLL_SW_RESET, base + REG_DSI_28nm_PHY_PLL_TEST_CFG);108	udelay(1);109	writel(0, base + REG_DSI_28nm_PHY_PLL_TEST_CFG);110	udelay(1);111}112 113/*114 * Clock Callbacks115 */116static int dsi_pll_28nm_clk_set_rate(struct clk_hw *hw, unsigned long rate,117		unsigned long parent_rate)118{119	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(hw);120	struct device *dev = &pll_28nm->phy->pdev->dev;121	void __iomem *base = pll_28nm->phy->pll_base;122	unsigned long div_fbx1000, gen_vco_clk;123	u32 refclk_cfg, frac_n_mode, frac_n_value;124	u32 sdm_cfg0, sdm_cfg1, sdm_cfg2, sdm_cfg3;125	u32 cal_cfg10, cal_cfg11;126	u32 rem;127	int i;128 129	VERB("rate=%lu, parent's=%lu", rate, parent_rate);130 131	/* Force postdiv2 to be div-4 */132	writel(3, base + REG_DSI_28nm_PHY_PLL_POSTDIV2_CFG);133 134	/* Configure the Loop filter resistance */135	for (i = 0; i < LPFR_LUT_SIZE; i++)136		if (rate <= lpfr_lut[i].vco_rate)137			break;138	if (i == LPFR_LUT_SIZE) {139		DRM_DEV_ERROR(dev, "unable to get loop filter resistance. vco=%lu\n",140				rate);141		return -EINVAL;142	}143	writel(lpfr_lut[i].resistance, base + REG_DSI_28nm_PHY_PLL_LPFR_CFG);144 145	/* Loop filter capacitance values : c1 and c2 */146	writel(0x70, base + REG_DSI_28nm_PHY_PLL_LPFC1_CFG);147	writel(0x15, base + REG_DSI_28nm_PHY_PLL_LPFC2_CFG);148 149	rem = rate % VCO_REF_CLK_RATE;150	if (rem) {151		refclk_cfg = DSI_28nm_PHY_PLL_REFCLK_CFG_DBLR;152		frac_n_mode = 1;153		div_fbx1000 = rate / (VCO_REF_CLK_RATE / 500);154		gen_vco_clk = div_fbx1000 * (VCO_REF_CLK_RATE / 500);155	} else {156		refclk_cfg = 0x0;157		frac_n_mode = 0;158		div_fbx1000 = rate / (VCO_REF_CLK_RATE / 1000);159		gen_vco_clk = div_fbx1000 * (VCO_REF_CLK_RATE / 1000);160	}161 162	DBG("refclk_cfg = %d", refclk_cfg);163 164	rem = div_fbx1000 % 1000;165	frac_n_value = (rem << 16) / 1000;166 167	DBG("div_fb = %lu", div_fbx1000);168	DBG("frac_n_value = %d", frac_n_value);169 170	DBG("Generated VCO Clock: %lu", gen_vco_clk);171	rem = 0;172	sdm_cfg1 = readl(base + REG_DSI_28nm_PHY_PLL_SDM_CFG1);173	sdm_cfg1 &= ~DSI_28nm_PHY_PLL_SDM_CFG1_DC_OFFSET__MASK;174	if (frac_n_mode) {175		sdm_cfg0 = 0x0;176		sdm_cfg0 |= DSI_28nm_PHY_PLL_SDM_CFG0_BYP_DIV(0);177		sdm_cfg1 |= DSI_28nm_PHY_PLL_SDM_CFG1_DC_OFFSET(178				(u32)(((div_fbx1000 / 1000) & 0x3f) - 1));179		sdm_cfg3 = frac_n_value >> 8;180		sdm_cfg2 = frac_n_value & 0xff;181	} else {182		sdm_cfg0 = DSI_28nm_PHY_PLL_SDM_CFG0_BYP;183		sdm_cfg0 |= DSI_28nm_PHY_PLL_SDM_CFG0_BYP_DIV(184				(u32)(((div_fbx1000 / 1000) & 0x3f) - 1));185		sdm_cfg1 |= DSI_28nm_PHY_PLL_SDM_CFG1_DC_OFFSET(0);186		sdm_cfg2 = 0;187		sdm_cfg3 = 0;188	}189 190	DBG("sdm_cfg0=%d", sdm_cfg0);191	DBG("sdm_cfg1=%d", sdm_cfg1);192	DBG("sdm_cfg2=%d", sdm_cfg2);193	DBG("sdm_cfg3=%d", sdm_cfg3);194 195	cal_cfg11 = (u32)(gen_vco_clk / (256 * 1000000));196	cal_cfg10 = (u32)((gen_vco_clk % (256 * 1000000)) / 1000000);197	DBG("cal_cfg10=%d, cal_cfg11=%d", cal_cfg10, cal_cfg11);198 199	writel(0x02, base + REG_DSI_28nm_PHY_PLL_CHGPUMP_CFG);200	writel(0x2b, base + REG_DSI_28nm_PHY_PLL_CAL_CFG3);201	writel(0x06, base + REG_DSI_28nm_PHY_PLL_CAL_CFG4);202	writel(0x0d, base + REG_DSI_28nm_PHY_PLL_LKDET_CFG2);203 204	writel(sdm_cfg1, base + REG_DSI_28nm_PHY_PLL_SDM_CFG1);205	writel(DSI_28nm_PHY_PLL_SDM_CFG2_FREQ_SEED_7_0(sdm_cfg2),206	       base + REG_DSI_28nm_PHY_PLL_SDM_CFG2);207	writel(DSI_28nm_PHY_PLL_SDM_CFG3_FREQ_SEED_15_8(sdm_cfg3),208	       base + REG_DSI_28nm_PHY_PLL_SDM_CFG3);209	writel(0, base + REG_DSI_28nm_PHY_PLL_SDM_CFG4);210 211	/* Add hardware recommended delay for correct PLL configuration */212	if (pll_28nm->phy->cfg->quirks & DSI_PHY_28NM_QUIRK_PHY_LP)213		udelay(1000);214	else215		udelay(1);216 217	writel(refclk_cfg, base + REG_DSI_28nm_PHY_PLL_REFCLK_CFG);218	writel(0x00, base + REG_DSI_28nm_PHY_PLL_PWRGEN_CFG);219	writel(0x31, base + REG_DSI_28nm_PHY_PLL_VCOLPF_CFG);220	writel(sdm_cfg0, base + REG_DSI_28nm_PHY_PLL_SDM_CFG0);221	writel(0x12, base + REG_DSI_28nm_PHY_PLL_CAL_CFG0);222	writel(0x30, base + REG_DSI_28nm_PHY_PLL_CAL_CFG6);223	writel(0x00, base + REG_DSI_28nm_PHY_PLL_CAL_CFG7);224	writel(0x60, base + REG_DSI_28nm_PHY_PLL_CAL_CFG8);225	writel(0x00, base + REG_DSI_28nm_PHY_PLL_CAL_CFG9);226	writel(cal_cfg10 & 0xff, base + REG_DSI_28nm_PHY_PLL_CAL_CFG10);227	writel(cal_cfg11 & 0xff, base + REG_DSI_28nm_PHY_PLL_CAL_CFG11);228	writel(0x20, base + REG_DSI_28nm_PHY_PLL_EFUSE_CFG);229 230	return 0;231}232 233static int dsi_pll_28nm_clk_is_enabled(struct clk_hw *hw)234{235	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(hw);236 237	return pll_28nm_poll_for_ready(pll_28nm, POLL_MAX_READS,238					POLL_TIMEOUT_US);239}240 241static unsigned long dsi_pll_28nm_clk_recalc_rate(struct clk_hw *hw,242		unsigned long parent_rate)243{244	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(hw);245	void __iomem *base = pll_28nm->phy->pll_base;246	u32 sdm0, doubler, sdm_byp_div;247	u32 sdm_dc_off, sdm_freq_seed, sdm2, sdm3;248	u32 ref_clk = VCO_REF_CLK_RATE;249	unsigned long vco_rate;250 251	VERB("parent_rate=%lu", parent_rate);252 253	/* Check to see if the ref clk doubler is enabled */254	doubler = readl(base + REG_DSI_28nm_PHY_PLL_REFCLK_CFG) &255			DSI_28nm_PHY_PLL_REFCLK_CFG_DBLR;256	ref_clk += (doubler * VCO_REF_CLK_RATE);257 258	/* see if it is integer mode or sdm mode */259	sdm0 = readl(base + REG_DSI_28nm_PHY_PLL_SDM_CFG0);260	if (sdm0 & DSI_28nm_PHY_PLL_SDM_CFG0_BYP) {261		/* integer mode */262		sdm_byp_div = FIELD(263				readl(base + REG_DSI_28nm_PHY_PLL_SDM_CFG0),264				DSI_28nm_PHY_PLL_SDM_CFG0_BYP_DIV) + 1;265		vco_rate = ref_clk * sdm_byp_div;266	} else {267		/* sdm mode */268		sdm_dc_off = FIELD(269				readl(base + REG_DSI_28nm_PHY_PLL_SDM_CFG1),270				DSI_28nm_PHY_PLL_SDM_CFG1_DC_OFFSET);271		DBG("sdm_dc_off = %d", sdm_dc_off);272		sdm2 = FIELD(readl(base + REG_DSI_28nm_PHY_PLL_SDM_CFG2),273				DSI_28nm_PHY_PLL_SDM_CFG2_FREQ_SEED_7_0);274		sdm3 = FIELD(readl(base + REG_DSI_28nm_PHY_PLL_SDM_CFG3),275				DSI_28nm_PHY_PLL_SDM_CFG3_FREQ_SEED_15_8);276		sdm_freq_seed = (sdm3 << 8) | sdm2;277		DBG("sdm_freq_seed = %d", sdm_freq_seed);278 279		vco_rate = (ref_clk * (sdm_dc_off + 1)) +280			mult_frac(ref_clk, sdm_freq_seed, BIT(16));281		DBG("vco rate = %lu", vco_rate);282	}283 284	DBG("returning vco rate = %lu", vco_rate);285 286	return vco_rate;287}288 289static int _dsi_pll_28nm_vco_prepare_hpm(struct dsi_pll_28nm *pll_28nm)290{291	struct device *dev = &pll_28nm->phy->pdev->dev;292	void __iomem *base = pll_28nm->phy->pll_base;293	u32 max_reads = 5, timeout_us = 100;294	bool locked;295	u32 val;296	int i;297 298	DBG("id=%d", pll_28nm->phy->id);299 300	pll_28nm_software_reset(pll_28nm);301 302	/*303	 * PLL power up sequence.304	 * Add necessary delays recommended by hardware.305	 */306	val = DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRDN_B;307	writel(val, base + REG_DSI_28nm_PHY_PLL_GLB_CFG);308	udelay(1);309 310	val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRGEN_PWRDN_B;311	writel(val, base + REG_DSI_28nm_PHY_PLL_GLB_CFG);312	udelay(200);313 314	val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_LDO_PWRDN_B;315	writel(val, base + REG_DSI_28nm_PHY_PLL_GLB_CFG);316	udelay(500);317 318	val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_ENABLE;319	writel(val, base + REG_DSI_28nm_PHY_PLL_GLB_CFG);320	udelay(600);321 322	for (i = 0; i < 2; i++) {323		/* DSI Uniphy lock detect setting */324		writel(0x0c, base + REG_DSI_28nm_PHY_PLL_LKDET_CFG2);325		udelay(100);326		writel(0x0d, base + REG_DSI_28nm_PHY_PLL_LKDET_CFG2);327 328		/* poll for PLL ready status */329		locked = pll_28nm_poll_for_ready(pll_28nm, max_reads,330						 timeout_us);331		if (locked)332			break;333 334		pll_28nm_software_reset(pll_28nm);335 336		/*337		 * PLL power up sequence.338		 * Add necessary delays recommended by hardware.339		 */340		val = DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRDN_B;341		writel(val, base + REG_DSI_28nm_PHY_PLL_GLB_CFG);342		udelay(1);343 344		val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRGEN_PWRDN_B;345		writel(val, base + REG_DSI_28nm_PHY_PLL_GLB_CFG);346		udelay(200);347 348		val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_LDO_PWRDN_B;349		writel(val, base + REG_DSI_28nm_PHY_PLL_GLB_CFG);350		udelay(250);351 352		val &= ~DSI_28nm_PHY_PLL_GLB_CFG_PLL_LDO_PWRDN_B;353		writel(val, base + REG_DSI_28nm_PHY_PLL_GLB_CFG);354		udelay(200);355 356		val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_LDO_PWRDN_B;357		writel(val, base + REG_DSI_28nm_PHY_PLL_GLB_CFG);358		udelay(500);359 360		val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_ENABLE;361		writel(val, base + REG_DSI_28nm_PHY_PLL_GLB_CFG);362		udelay(600);363	}364 365	if (unlikely(!locked))366		DRM_DEV_ERROR(dev, "DSI PLL lock failed\n");367	else368		DBG("DSI PLL Lock success");369 370	return locked ? 0 : -EINVAL;371}372 373static int dsi_pll_28nm_vco_prepare_hpm(struct clk_hw *hw)374{375	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(hw);376	int i, ret;377 378	if (unlikely(pll_28nm->phy->pll_on))379		return 0;380 381	for (i = 0; i < 3; i++) {382		ret = _dsi_pll_28nm_vco_prepare_hpm(pll_28nm);383		if (!ret) {384			pll_28nm->phy->pll_on = true;385			return 0;386		}387	}388 389	return ret;390}391 392static int dsi_pll_28nm_vco_prepare_8226(struct clk_hw *hw)393{394	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(hw);395	struct device *dev = &pll_28nm->phy->pdev->dev;396	void __iomem *base = pll_28nm->phy->pll_base;397	u32 max_reads = 5, timeout_us = 100;398	bool locked;399	u32 val;400	int i;401 402	DBG("id=%d", pll_28nm->phy->id);403 404	pll_28nm_software_reset(pll_28nm);405 406	/*407	 * PLL power up sequence.408	 * Add necessary delays recommended by hardware.409	 */410	writel(0x34, base + REG_DSI_28nm_PHY_PLL_CAL_CFG1);411 412	val = DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRDN_B;413	writel(val, base + REG_DSI_28nm_PHY_PLL_GLB_CFG);414	udelay(200);415 416	val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRGEN_PWRDN_B;417	writel(val, base + REG_DSI_28nm_PHY_PLL_GLB_CFG);418	udelay(200);419 420	val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_LDO_PWRDN_B;421	val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_ENABLE;422	writel(val, base + REG_DSI_28nm_PHY_PLL_GLB_CFG);423	udelay(600);424 425	for (i = 0; i < 7; i++) {426		/* DSI Uniphy lock detect setting */427		writel(0x0d, base + REG_DSI_28nm_PHY_PLL_LKDET_CFG2);428		writel(0x0c, base + REG_DSI_28nm_PHY_PLL_LKDET_CFG2);429		udelay(100);430		writel(0x0d, base + REG_DSI_28nm_PHY_PLL_LKDET_CFG2);431 432		/* poll for PLL ready status */433		locked = pll_28nm_poll_for_ready(pll_28nm,434						max_reads, timeout_us);435		if (locked)436			break;437 438		pll_28nm_software_reset(pll_28nm);439 440		/*441		 * PLL power up sequence.442		 * Add necessary delays recommended by hardware.443		 */444		writel(0x00, base + REG_DSI_28nm_PHY_PLL_PWRGEN_CFG);445		udelay(50);446 447		val = DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRDN_B;448		val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRGEN_PWRDN_B;449		writel(val, base + REG_DSI_28nm_PHY_PLL_GLB_CFG);450		udelay(100);451 452		val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_LDO_PWRDN_B;453		val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_ENABLE;454		writel(val, base + REG_DSI_28nm_PHY_PLL_GLB_CFG);455		udelay(600);456	}457 458	if (unlikely(!locked))459		DRM_DEV_ERROR(dev, "DSI PLL lock failed\n");460	else461		DBG("DSI PLL Lock success");462 463	return locked ? 0 : -EINVAL;464}465 466static int dsi_pll_28nm_vco_prepare_lp(struct clk_hw *hw)467{468	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(hw);469	struct device *dev = &pll_28nm->phy->pdev->dev;470	void __iomem *base = pll_28nm->phy->pll_base;471	bool locked;472	u32 max_reads = 10, timeout_us = 50;473	u32 val;474 475	DBG("id=%d", pll_28nm->phy->id);476 477	if (unlikely(pll_28nm->phy->pll_on))478		return 0;479 480	pll_28nm_software_reset(pll_28nm);481 482	/*483	 * PLL power up sequence.484	 * Add necessary delays recommended by hardware.485	 */486	writel(0x34, base + REG_DSI_28nm_PHY_PLL_CAL_CFG1);487	ndelay(500);488 489	val = DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRDN_B;490	writel(val, base + REG_DSI_28nm_PHY_PLL_GLB_CFG);491	ndelay(500);492 493	val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRGEN_PWRDN_B;494	writel(val, base + REG_DSI_28nm_PHY_PLL_GLB_CFG);495	ndelay(500);496 497	val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_LDO_PWRDN_B |498		DSI_28nm_PHY_PLL_GLB_CFG_PLL_ENABLE;499	writel(val, base + REG_DSI_28nm_PHY_PLL_GLB_CFG);500	ndelay(500);501 502	/* DSI PLL toggle lock detect setting */503	writel(0x04, base + REG_DSI_28nm_PHY_PLL_LKDET_CFG2);504	ndelay(500);505	writel(0x05, base + REG_DSI_28nm_PHY_PLL_LKDET_CFG2);506	udelay(512);507 508	locked = pll_28nm_poll_for_ready(pll_28nm, max_reads, timeout_us);509 510	if (unlikely(!locked)) {511		DRM_DEV_ERROR(dev, "DSI PLL lock failed\n");512		return -EINVAL;513	}514 515	DBG("DSI PLL lock success");516	pll_28nm->phy->pll_on = true;517 518	return 0;519}520 521static void dsi_pll_28nm_vco_unprepare(struct clk_hw *hw)522{523	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(hw);524 525	DBG("id=%d", pll_28nm->phy->id);526 527	if (unlikely(!pll_28nm->phy->pll_on))528		return;529 530	writel(0, pll_28nm->phy->pll_base + REG_DSI_28nm_PHY_PLL_GLB_CFG);531 532	pll_28nm->phy->pll_on = false;533}534 535static long dsi_pll_28nm_clk_round_rate(struct clk_hw *hw,536		unsigned long rate, unsigned long *parent_rate)537{538	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(hw);539 540	if      (rate < pll_28nm->phy->cfg->min_pll_rate)541		return  pll_28nm->phy->cfg->min_pll_rate;542	else if (rate > pll_28nm->phy->cfg->max_pll_rate)543		return  pll_28nm->phy->cfg->max_pll_rate;544	else545		return rate;546}547 548static const struct clk_ops clk_ops_dsi_pll_28nm_vco_hpm = {549	.round_rate = dsi_pll_28nm_clk_round_rate,550	.set_rate = dsi_pll_28nm_clk_set_rate,551	.recalc_rate = dsi_pll_28nm_clk_recalc_rate,552	.prepare = dsi_pll_28nm_vco_prepare_hpm,553	.unprepare = dsi_pll_28nm_vco_unprepare,554	.is_enabled = dsi_pll_28nm_clk_is_enabled,555};556 557static const struct clk_ops clk_ops_dsi_pll_28nm_vco_lp = {558	.round_rate = dsi_pll_28nm_clk_round_rate,559	.set_rate = dsi_pll_28nm_clk_set_rate,560	.recalc_rate = dsi_pll_28nm_clk_recalc_rate,561	.prepare = dsi_pll_28nm_vco_prepare_lp,562	.unprepare = dsi_pll_28nm_vco_unprepare,563	.is_enabled = dsi_pll_28nm_clk_is_enabled,564};565 566static const struct clk_ops clk_ops_dsi_pll_28nm_vco_8226 = {567	.round_rate = dsi_pll_28nm_clk_round_rate,568	.set_rate = dsi_pll_28nm_clk_set_rate,569	.recalc_rate = dsi_pll_28nm_clk_recalc_rate,570	.prepare = dsi_pll_28nm_vco_prepare_8226,571	.unprepare = dsi_pll_28nm_vco_unprepare,572	.is_enabled = dsi_pll_28nm_clk_is_enabled,573};574 575/*576 * PLL Callbacks577 */578 579static void dsi_28nm_pll_save_state(struct msm_dsi_phy *phy)580{581	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(phy->vco_hw);582	struct pll_28nm_cached_state *cached_state = &pll_28nm->cached_state;583	void __iomem *base = pll_28nm->phy->pll_base;584 585	cached_state->postdiv3 =586			readl(base + REG_DSI_28nm_PHY_PLL_POSTDIV3_CFG);587	cached_state->postdiv1 =588			readl(base + REG_DSI_28nm_PHY_PLL_POSTDIV1_CFG);589	cached_state->byte_mux = readl(base + REG_DSI_28nm_PHY_PLL_VREG_CFG);590	if (dsi_pll_28nm_clk_is_enabled(phy->vco_hw))591		cached_state->vco_rate = clk_hw_get_rate(phy->vco_hw);592	else593		cached_state->vco_rate = 0;594}595 596static int dsi_28nm_pll_restore_state(struct msm_dsi_phy *phy)597{598	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(phy->vco_hw);599	struct pll_28nm_cached_state *cached_state = &pll_28nm->cached_state;600	void __iomem *base = pll_28nm->phy->pll_base;601	int ret;602 603	ret = dsi_pll_28nm_clk_set_rate(phy->vco_hw,604					cached_state->vco_rate, 0);605	if (ret) {606		DRM_DEV_ERROR(&pll_28nm->phy->pdev->dev,607			"restore vco rate failed. ret=%d\n", ret);608		return ret;609	}610 611	writel(cached_state->postdiv3, base + REG_DSI_28nm_PHY_PLL_POSTDIV3_CFG);612	writel(cached_state->postdiv1, base + REG_DSI_28nm_PHY_PLL_POSTDIV1_CFG);613	writel(cached_state->byte_mux, base + REG_DSI_28nm_PHY_PLL_VREG_CFG);614 615	return 0;616}617 618static int pll_28nm_register(struct dsi_pll_28nm *pll_28nm, struct clk_hw **provided_clocks)619{620	char clk_name[32];621	struct clk_init_data vco_init = {622		.parent_data = &(const struct clk_parent_data) {623			.fw_name = "ref", .name = "xo",624		},625		.num_parents = 1,626		.name = clk_name,627		.flags = CLK_IGNORE_UNUSED,628	};629	struct device *dev = &pll_28nm->phy->pdev->dev;630	struct clk_hw *hw, *analog_postdiv, *indirect_path_div2, *byte_mux;631	int ret;632 633	DBG("%d", pll_28nm->phy->id);634 635	if (pll_28nm->phy->cfg->quirks & DSI_PHY_28NM_QUIRK_PHY_LP)636		vco_init.ops = &clk_ops_dsi_pll_28nm_vco_lp;637	else if (pll_28nm->phy->cfg->quirks & DSI_PHY_28NM_QUIRK_PHY_8226)638		vco_init.ops = &clk_ops_dsi_pll_28nm_vco_8226;639	else640		vco_init.ops = &clk_ops_dsi_pll_28nm_vco_hpm;641 642	snprintf(clk_name, sizeof(clk_name), "dsi%dvco_clk", pll_28nm->phy->id);643	pll_28nm->clk_hw.init = &vco_init;644	ret = devm_clk_hw_register(dev, &pll_28nm->clk_hw);645	if (ret)646		return ret;647 648	snprintf(clk_name, sizeof(clk_name), "dsi%danalog_postdiv_clk", pll_28nm->phy->id);649	analog_postdiv = devm_clk_hw_register_divider_parent_hw(dev, clk_name,650			&pll_28nm->clk_hw, CLK_SET_RATE_PARENT,651			pll_28nm->phy->pll_base +652				REG_DSI_28nm_PHY_PLL_POSTDIV1_CFG,653			0, 4, 0, NULL);654	if (IS_ERR(analog_postdiv))655		return PTR_ERR(analog_postdiv);656 657	snprintf(clk_name, sizeof(clk_name), "dsi%dindirect_path_div2_clk", pll_28nm->phy->id);658	indirect_path_div2 = devm_clk_hw_register_fixed_factor_parent_hw(dev,659			clk_name, analog_postdiv, CLK_SET_RATE_PARENT, 1, 2);660	if (IS_ERR(indirect_path_div2))661		return PTR_ERR(indirect_path_div2);662 663	snprintf(clk_name, sizeof(clk_name), "dsi%dpll", pll_28nm->phy->id);664	hw = devm_clk_hw_register_divider_parent_hw(dev, clk_name,665			&pll_28nm->clk_hw, 0, pll_28nm->phy->pll_base +666				REG_DSI_28nm_PHY_PLL_POSTDIV3_CFG,667			0, 8, 0, NULL);668	if (IS_ERR(hw))669		return PTR_ERR(hw);670	provided_clocks[DSI_PIXEL_PLL_CLK] = hw;671 672	snprintf(clk_name, sizeof(clk_name), "dsi%dbyte_mux", pll_28nm->phy->id);673	byte_mux = devm_clk_hw_register_mux_parent_hws(dev, clk_name,674			((const struct clk_hw *[]){675				&pll_28nm->clk_hw,676				indirect_path_div2,677			}), 2, CLK_SET_RATE_PARENT, pll_28nm->phy->pll_base +678				REG_DSI_28nm_PHY_PLL_VREG_CFG, 1, 1, 0, NULL);679	if (IS_ERR(byte_mux))680		return PTR_ERR(byte_mux);681 682	snprintf(clk_name, sizeof(clk_name), "dsi%dpllbyte", pll_28nm->phy->id);683	hw = devm_clk_hw_register_fixed_factor_parent_hw(dev, clk_name,684			byte_mux, CLK_SET_RATE_PARENT, 1, 4);685	if (IS_ERR(hw))686		return PTR_ERR(hw);687	provided_clocks[DSI_BYTE_PLL_CLK] = hw;688 689	return 0;690}691 692static int dsi_pll_28nm_init(struct msm_dsi_phy *phy)693{694	struct platform_device *pdev = phy->pdev;695	struct dsi_pll_28nm *pll_28nm;696	int ret;697 698	if (!pdev)699		return -ENODEV;700 701	pll_28nm = devm_kzalloc(&pdev->dev, sizeof(*pll_28nm), GFP_KERNEL);702	if (!pll_28nm)703		return -ENOMEM;704 705	pll_28nm->phy = phy;706 707	ret = pll_28nm_register(pll_28nm, phy->provided_clocks->hws);708	if (ret) {709		DRM_DEV_ERROR(&pdev->dev, "failed to register PLL: %d\n", ret);710		return ret;711	}712 713	phy->vco_hw = &pll_28nm->clk_hw;714 715	return 0;716}717 718static void dsi_28nm_dphy_set_timing(struct msm_dsi_phy *phy,719		struct msm_dsi_dphy_timing *timing)720{721	void __iomem *base = phy->base;722 723	writel(DSI_28nm_PHY_TIMING_CTRL_0_CLK_ZERO(timing->clk_zero),724	       base + REG_DSI_28nm_PHY_TIMING_CTRL_0);725	writel(DSI_28nm_PHY_TIMING_CTRL_1_CLK_TRAIL(timing->clk_trail),726	       base + REG_DSI_28nm_PHY_TIMING_CTRL_1);727	writel(DSI_28nm_PHY_TIMING_CTRL_2_CLK_PREPARE(timing->clk_prepare),728	       base + REG_DSI_28nm_PHY_TIMING_CTRL_2);729	if (timing->clk_zero & BIT(8))730		writel(DSI_28nm_PHY_TIMING_CTRL_3_CLK_ZERO_8,731		       base + REG_DSI_28nm_PHY_TIMING_CTRL_3);732	writel(DSI_28nm_PHY_TIMING_CTRL_4_HS_EXIT(timing->hs_exit),733	       base + REG_DSI_28nm_PHY_TIMING_CTRL_4);734	writel(DSI_28nm_PHY_TIMING_CTRL_5_HS_ZERO(timing->hs_zero),735	       base + REG_DSI_28nm_PHY_TIMING_CTRL_5);736	writel(DSI_28nm_PHY_TIMING_CTRL_6_HS_PREPARE(timing->hs_prepare),737	       base + REG_DSI_28nm_PHY_TIMING_CTRL_6);738	writel(DSI_28nm_PHY_TIMING_CTRL_7_HS_TRAIL(timing->hs_trail),739	       base + REG_DSI_28nm_PHY_TIMING_CTRL_7);740	writel(DSI_28nm_PHY_TIMING_CTRL_8_HS_RQST(timing->hs_rqst),741	       base + REG_DSI_28nm_PHY_TIMING_CTRL_8);742	writel(DSI_28nm_PHY_TIMING_CTRL_9_TA_GO(timing->ta_go) |743	       DSI_28nm_PHY_TIMING_CTRL_9_TA_SURE(timing->ta_sure),744	       base + REG_DSI_28nm_PHY_TIMING_CTRL_9);745	writel(DSI_28nm_PHY_TIMING_CTRL_10_TA_GET(timing->ta_get),746	       base + REG_DSI_28nm_PHY_TIMING_CTRL_10);747	writel(DSI_28nm_PHY_TIMING_CTRL_11_TRIG3_CMD(0),748	       base + REG_DSI_28nm_PHY_TIMING_CTRL_11);749}750 751static void dsi_28nm_phy_regulator_enable_dcdc(struct msm_dsi_phy *phy)752{753	void __iomem *base = phy->reg_base;754 755	writel(0x0, base + REG_DSI_28nm_PHY_REGULATOR_CTRL_0);756	writel(1, base + REG_DSI_28nm_PHY_REGULATOR_CAL_PWR_CFG);757	writel(0, base + REG_DSI_28nm_PHY_REGULATOR_CTRL_5);758	writel(0, base + REG_DSI_28nm_PHY_REGULATOR_CTRL_3);759	writel(0x3, base + REG_DSI_28nm_PHY_REGULATOR_CTRL_2);760	writel(0x9, base + REG_DSI_28nm_PHY_REGULATOR_CTRL_1);761	writel(0x7, base + REG_DSI_28nm_PHY_REGULATOR_CTRL_0);762	writel(0x20, base + REG_DSI_28nm_PHY_REGULATOR_CTRL_4);763	writel(0x00, phy->base + REG_DSI_28nm_PHY_LDO_CNTRL);764}765 766static void dsi_28nm_phy_regulator_enable_ldo(struct msm_dsi_phy *phy)767{768	void __iomem *base = phy->reg_base;769 770	writel(0x0, base + REG_DSI_28nm_PHY_REGULATOR_CTRL_0);771	writel(0, base + REG_DSI_28nm_PHY_REGULATOR_CAL_PWR_CFG);772	writel(0x7, base + REG_DSI_28nm_PHY_REGULATOR_CTRL_5);773	writel(0, base + REG_DSI_28nm_PHY_REGULATOR_CTRL_3);774	writel(0x1, base + REG_DSI_28nm_PHY_REGULATOR_CTRL_2);775	writel(0x1, base + REG_DSI_28nm_PHY_REGULATOR_CTRL_1);776	writel(0x20, base + REG_DSI_28nm_PHY_REGULATOR_CTRL_4);777 778	if (phy->cfg->quirks & DSI_PHY_28NM_QUIRK_PHY_LP)779		writel(0x05, phy->base + REG_DSI_28nm_PHY_LDO_CNTRL);780	else781		writel(0x0d, phy->base + REG_DSI_28nm_PHY_LDO_CNTRL);782}783 784static void dsi_28nm_phy_regulator_ctrl(struct msm_dsi_phy *phy, bool enable)785{786	if (!enable) {787		writel(0, phy->reg_base + REG_DSI_28nm_PHY_REGULATOR_CAL_PWR_CFG);788		return;789	}790 791	if (phy->regulator_ldo_mode)792		dsi_28nm_phy_regulator_enable_ldo(phy);793	else794		dsi_28nm_phy_regulator_enable_dcdc(phy);795}796 797static int dsi_28nm_phy_enable(struct msm_dsi_phy *phy,798				struct msm_dsi_phy_clk_request *clk_req)799{800	struct msm_dsi_dphy_timing *timing = &phy->timing;801	int i;802	void __iomem *base = phy->base;803	u32 val;804 805	DBG("");806 807	if (msm_dsi_dphy_timing_calc(timing, clk_req)) {808		DRM_DEV_ERROR(&phy->pdev->dev,809			      "%s: D-PHY timing calculation failed\n",810			      __func__);811		return -EINVAL;812	}813 814	writel(0xff, base + REG_DSI_28nm_PHY_STRENGTH_0);815 816	dsi_28nm_phy_regulator_ctrl(phy, true);817 818	dsi_28nm_dphy_set_timing(phy, timing);819 820	writel(0x00, base + REG_DSI_28nm_PHY_CTRL_1);821	writel(0x5f, base + REG_DSI_28nm_PHY_CTRL_0);822 823	writel(0x6, base + REG_DSI_28nm_PHY_STRENGTH_1);824 825	for (i = 0; i < 4; i++) {826		writel(0, base + REG_DSI_28nm_PHY_LN_CFG_0(i));827		writel(0, base + REG_DSI_28nm_PHY_LN_CFG_1(i));828		writel(0, base + REG_DSI_28nm_PHY_LN_CFG_2(i));829		writel(0, base + REG_DSI_28nm_PHY_LN_CFG_3(i));830		writel(0, base + REG_DSI_28nm_PHY_LN_CFG_4(i));831		writel(0, base + REG_DSI_28nm_PHY_LN_TEST_DATAPATH(i));832		writel(0, base + REG_DSI_28nm_PHY_LN_DEBUG_SEL(i));833		writel(0x1, base + REG_DSI_28nm_PHY_LN_TEST_STR_0(i));834		writel(0x97, base + REG_DSI_28nm_PHY_LN_TEST_STR_1(i));835	}836 837	writel(0, base + REG_DSI_28nm_PHY_LNCK_CFG_4);838	writel(0xc0, base + REG_DSI_28nm_PHY_LNCK_CFG_1);839	writel(0x1, base + REG_DSI_28nm_PHY_LNCK_TEST_STR0);840	writel(0xbb, base + REG_DSI_28nm_PHY_LNCK_TEST_STR1);841 842	writel(0x5f, base + REG_DSI_28nm_PHY_CTRL_0);843 844	val = readl(base + REG_DSI_28nm_PHY_GLBL_TEST_CTRL);845	if (phy->id == DSI_1 && phy->usecase == MSM_DSI_PHY_SLAVE)846		val &= ~DSI_28nm_PHY_GLBL_TEST_CTRL_BITCLK_HS_SEL;847	else848		val |= DSI_28nm_PHY_GLBL_TEST_CTRL_BITCLK_HS_SEL;849	writel(val, base + REG_DSI_28nm_PHY_GLBL_TEST_CTRL);850 851	return 0;852}853 854static void dsi_28nm_phy_disable(struct msm_dsi_phy *phy)855{856	writel(0, phy->base + REG_DSI_28nm_PHY_CTRL_0);857	dsi_28nm_phy_regulator_ctrl(phy, false);858 859	/*860	 * Wait for the registers writes to complete in order to861	 * ensure that the phy is completely disabled862	 */863	wmb();864}865 866static const struct regulator_bulk_data dsi_phy_28nm_regulators[] = {867	{ .supply = "vddio", .init_load_uA = 100000 },868};869 870const struct msm_dsi_phy_cfg dsi_phy_28nm_hpm_cfgs = {871	.has_phy_regulator = true,872	.regulator_data = dsi_phy_28nm_regulators,873	.num_regulators = ARRAY_SIZE(dsi_phy_28nm_regulators),874	.ops = {875		.enable = dsi_28nm_phy_enable,876		.disable = dsi_28nm_phy_disable,877		.pll_init = dsi_pll_28nm_init,878		.save_pll_state = dsi_28nm_pll_save_state,879		.restore_pll_state = dsi_28nm_pll_restore_state,880	},881	.min_pll_rate = VCO_MIN_RATE,882	.max_pll_rate = VCO_MAX_RATE,883	.io_start = { 0xfd922b00, 0xfd923100 },884	.num_dsi_phy = 2,885};886 887const struct msm_dsi_phy_cfg dsi_phy_28nm_hpm_famb_cfgs = {888	.has_phy_regulator = true,889	.regulator_data = dsi_phy_28nm_regulators,890	.num_regulators = ARRAY_SIZE(dsi_phy_28nm_regulators),891	.ops = {892		.enable = dsi_28nm_phy_enable,893		.disable = dsi_28nm_phy_disable,894		.pll_init = dsi_pll_28nm_init,895		.save_pll_state = dsi_28nm_pll_save_state,896		.restore_pll_state = dsi_28nm_pll_restore_state,897	},898	.min_pll_rate = VCO_MIN_RATE,899	.max_pll_rate = VCO_MAX_RATE,900	.io_start = { 0x1a94400, 0x1a96400 },901	.num_dsi_phy = 2,902};903 904const struct msm_dsi_phy_cfg dsi_phy_28nm_lp_cfgs = {905	.has_phy_regulator = true,906	.regulator_data = dsi_phy_28nm_regulators,907	.num_regulators = ARRAY_SIZE(dsi_phy_28nm_regulators),908	.ops = {909		.enable = dsi_28nm_phy_enable,910		.disable = dsi_28nm_phy_disable,911		.pll_init = dsi_pll_28nm_init,912		.save_pll_state = dsi_28nm_pll_save_state,913		.restore_pll_state = dsi_28nm_pll_restore_state,914	},915	.min_pll_rate = VCO_MIN_RATE,916	.max_pll_rate = VCO_MAX_RATE,917	.io_start = { 0x1a98500 },918	.num_dsi_phy = 1,919	.quirks = DSI_PHY_28NM_QUIRK_PHY_LP,920};921 922const struct msm_dsi_phy_cfg dsi_phy_28nm_8226_cfgs = {923	.has_phy_regulator = true,924	.regulator_data = dsi_phy_28nm_regulators,925	.num_regulators = ARRAY_SIZE(dsi_phy_28nm_regulators),926	.ops = {927		.enable = dsi_28nm_phy_enable,928		.disable = dsi_28nm_phy_disable,929		.pll_init = dsi_pll_28nm_init,930		.save_pll_state = dsi_28nm_pll_save_state,931		.restore_pll_state = dsi_28nm_pll_restore_state,932	},933	.min_pll_rate = VCO_MIN_RATE,934	.max_pll_rate = VCO_MAX_RATE,935	.io_start = { 0xfd922b00 },936	.num_dsi_phy = 1,937	.quirks = DSI_PHY_28NM_QUIRK_PHY_8226,938};939 940const struct msm_dsi_phy_cfg dsi_phy_28nm_8937_cfgs = {941	.has_phy_regulator = true,942	.regulator_data = dsi_phy_28nm_regulators,943	.num_regulators = ARRAY_SIZE(dsi_phy_28nm_regulators),944	.ops = {945		.enable = dsi_28nm_phy_enable,946		.disable = dsi_28nm_phy_disable,947		.pll_init = dsi_pll_28nm_init,948		.save_pll_state = dsi_28nm_pll_save_state,949		.restore_pll_state = dsi_28nm_pll_restore_state,950	},951	.min_pll_rate = VCO_MIN_RATE,952	.max_pll_rate = VCO_MAX_RATE,953	.io_start = { 0x1a94400, 0x1a96400 },954	.num_dsi_phy = 2,955	.quirks = DSI_PHY_28NM_QUIRK_PHY_LP,956};957