File Index
Files and directories
Sign in
FILE

phy-qcom-edp.c

File preview with syntax highlighting.

linux-6.19.14/drivers/phy/qualcomm/phy-qcom-edp.c C
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Copyright (c) 2017, 2020, The Linux Foundation. All rights reserved.
   4 * Copyright (c) 2021, Linaro Ltd.
   5 */
   6
   7#include <linux/clk.h>
   8#include <linux/clk-provider.h>
   9#include <linux/delay.h>
  10#include <linux/err.h>
  11#include <linux/io.h>
  12#include <linux/iopoll.h>
  13#include <linux/kernel.h>
  14#include <linux/module.h>
  15#include <linux/of.h>
  16#include <linux/phy/phy.h>
  17#include <linux/phy/phy-dp.h>
  18#include <linux/platform_device.h>
  19#include <linux/regulator/consumer.h>
  20#include <linux/reset.h>
  21#include <linux/slab.h>
  22
  23#include <dt-bindings/phy/phy.h>
  24
  25#include "phy-qcom-qmp-dp-phy.h"
  26#include "phy-qcom-qmp-qserdes-com-v4.h"
  27#include "phy-qcom-qmp-qserdes-com-v6.h"
  28
  29/* EDP_PHY registers */
  30#define DP_PHY_CFG                              0x0010
  31#define DP_PHY_CFG_1                            0x0014
  32#define DP_PHY_PD_CTL                           0x001c
  33#define DP_PHY_MODE                             0x0020
  34
  35#define DP_AUX_CFG_SIZE                         10
  36#define DP_PHY_AUX_CFG(n)                       (0x24 + (0x04 * (n)))
  37
  38#define DP_PHY_AUX_INTERRUPT_MASK		0x0058
  39
  40#define DP_PHY_VCO_DIV                          0x0074
  41#define DP_PHY_TX0_TX1_LANE_CTL                 0x007c
  42#define DP_PHY_TX2_TX3_LANE_CTL                 0x00a0
  43
  44#define DP_PHY_STATUS                           0x00e0
  45
  46/* LANE_TXn registers */
  47#define TXn_CLKBUF_ENABLE                       0x0000
  48#define TXn_TX_EMP_POST1_LVL                    0x0004
  49
  50#define TXn_TX_DRV_LVL                          0x0014
  51#define TXn_TX_DRV_LVL_OFFSET                   0x0018
  52#define TXn_RESET_TSYNC_EN                      0x001c
  53#define TXn_LDO_CONFIG                          0x0084
  54#define TXn_TX_BAND                             0x0028
  55
  56#define TXn_RES_CODE_LANE_OFFSET_TX0            0x0044
  57#define TXn_RES_CODE_LANE_OFFSET_TX1            0x0048
  58
  59#define TXn_TRANSCEIVER_BIAS_EN                 0x0054
  60#define TXn_HIGHZ_DRVR_EN                       0x0058
  61#define TXn_TX_POL_INV                          0x005c
  62#define TXn_LANE_MODE_1                         0x0064
  63
  64#define TXn_TRAN_DRVR_EMP_EN                    0x0078
  65
  66struct qcom_edp_swing_pre_emph_cfg {
  67	const u8 (*swing_hbr_rbr)[4][4];
  68	const u8 (*swing_hbr3_hbr2)[4][4];
  69	const u8 (*pre_emphasis_hbr_rbr)[4][4];
  70	const u8 (*pre_emphasis_hbr3_hbr2)[4][4];
  71};
  72
  73struct qcom_edp;
  74
  75struct phy_ver_ops {
  76	int (*com_power_on)(const struct qcom_edp *edp);
  77	int (*com_resetsm_cntrl)(const struct qcom_edp *edp);
  78	int (*com_bias_en_clkbuflr)(const struct qcom_edp *edp);
  79	int (*com_configure_pll)(const struct qcom_edp *edp);
  80	int (*com_configure_ssc)(const struct qcom_edp *edp);
  81};
  82
  83struct qcom_edp_phy_cfg {
  84	bool is_edp;
  85	const u8 *aux_cfg;
  86	const struct qcom_edp_swing_pre_emph_cfg *swing_pre_emph_cfg;
  87	const struct phy_ver_ops *ver_ops;
  88};
  89
  90struct qcom_edp {
  91	struct device *dev;
  92	const struct qcom_edp_phy_cfg *cfg;
  93
  94	struct phy *phy;
  95
  96	void __iomem *edp;
  97	void __iomem *tx0;
  98	void __iomem *tx1;
  99	void __iomem *pll;
 100
 101	struct clk_hw dp_link_hw;
 102	struct clk_hw dp_pixel_hw;
 103
 104	struct phy_configure_opts_dp dp_opts;
 105
 106	struct clk_bulk_data *clks;
 107	int num_clks;
 108
 109	struct regulator_bulk_data supplies[2];
 110
 111	bool is_edp;
 112};
 113
 114static const u8 dp_swing_hbr_rbr[4][4] = {
 115	{ 0x08, 0x0f, 0x16, 0x1f },
 116	{ 0x11, 0x1e, 0x1f, 0xff },
 117	{ 0x16, 0x1f, 0xff, 0xff },
 118	{ 0x1f, 0xff, 0xff, 0xff }
 119};
 120
 121static const u8 dp_pre_emp_hbr_rbr[4][4] = {
 122	{ 0x00, 0x0d, 0x14, 0x1a },
 123	{ 0x00, 0x0e, 0x15, 0xff },
 124	{ 0x00, 0x0e, 0xff, 0xff },
 125	{ 0x03, 0xff, 0xff, 0xff }
 126};
 127
 128static const u8 dp_swing_hbr2_hbr3[4][4] = {
 129	{ 0x02, 0x12, 0x16, 0x1a },
 130	{ 0x09, 0x19, 0x1f, 0xff },
 131	{ 0x10, 0x1f, 0xff, 0xff },
 132	{ 0x1f, 0xff, 0xff, 0xff }
 133};
 134
 135static const u8 dp_pre_emp_hbr2_hbr3[4][4] = {
 136	{ 0x00, 0x0c, 0x15, 0x1b },
 137	{ 0x02, 0x0e, 0x16, 0xff },
 138	{ 0x02, 0x11, 0xff, 0xff },
 139	{ 0x04, 0xff, 0xff, 0xff }
 140};
 141
 142static const struct qcom_edp_swing_pre_emph_cfg dp_phy_swing_pre_emph_cfg = {
 143	.swing_hbr_rbr = &dp_swing_hbr_rbr,
 144	.swing_hbr3_hbr2 = &dp_swing_hbr2_hbr3,
 145	.pre_emphasis_hbr_rbr = &dp_pre_emp_hbr_rbr,
 146	.pre_emphasis_hbr3_hbr2 = &dp_pre_emp_hbr2_hbr3,
 147};
 148
 149static const u8 edp_swing_hbr_rbr[4][4] = {
 150	{ 0x07, 0x0f, 0x16, 0x1f },
 151	{ 0x0d, 0x16, 0x1e, 0xff },
 152	{ 0x11, 0x1b, 0xff, 0xff },
 153	{ 0x16, 0xff, 0xff, 0xff }
 154};
 155
 156static const u8 edp_pre_emp_hbr_rbr[4][4] = {
 157	{ 0x05, 0x12, 0x17, 0x1d },
 158	{ 0x05, 0x11, 0x18, 0xff },
 159	{ 0x06, 0x11, 0xff, 0xff },
 160	{ 0x00, 0xff, 0xff, 0xff }
 161};
 162
 163static const u8 edp_swing_hbr2_hbr3[4][4] = {
 164	{ 0x0b, 0x11, 0x17, 0x1c },
 165	{ 0x10, 0x19, 0x1f, 0xff },
 166	{ 0x19, 0x1f, 0xff, 0xff },
 167	{ 0x1f, 0xff, 0xff, 0xff }
 168};
 169
 170static const u8 edp_pre_emp_hbr2_hbr3[4][4] = {
 171	{ 0x08, 0x11, 0x17, 0x1b },
 172	{ 0x00, 0x0c, 0x13, 0xff },
 173	{ 0x05, 0x10, 0xff, 0xff },
 174	{ 0x00, 0xff, 0xff, 0xff }
 175};
 176
 177static const struct qcom_edp_swing_pre_emph_cfg edp_phy_swing_pre_emph_cfg = {
 178	.swing_hbr_rbr = &edp_swing_hbr_rbr,
 179	.swing_hbr3_hbr2 = &edp_swing_hbr2_hbr3,
 180	.pre_emphasis_hbr_rbr = &edp_pre_emp_hbr_rbr,
 181	.pre_emphasis_hbr3_hbr2 = &edp_pre_emp_hbr2_hbr3,
 182};
 183
 184static const u8 edp_phy_aux_cfg_v4[10] = {
 185	0x00, 0x13, 0x24, 0x00, 0x0a, 0x26, 0x0a, 0x03, 0x37, 0x03
 186};
 187
 188static const u8 edp_pre_emp_hbr_rbr_v5[4][4] = {
 189	{ 0x05, 0x11, 0x17, 0x1d },
 190	{ 0x05, 0x11, 0x18, 0xff },
 191	{ 0x06, 0x11, 0xff, 0xff },
 192	{ 0x00, 0xff, 0xff, 0xff }
 193};
 194
 195static const u8 edp_pre_emp_hbr2_hbr3_v5[4][4] = {
 196	{ 0x0c, 0x15, 0x19, 0x1e },
 197	{ 0x0b, 0x15, 0x19, 0xff },
 198	{ 0x0e, 0x14, 0xff, 0xff },
 199	{ 0x0d, 0xff, 0xff, 0xff }
 200};
 201
 202static const struct qcom_edp_swing_pre_emph_cfg edp_phy_swing_pre_emph_cfg_v5 = {
 203	.swing_hbr_rbr = &edp_swing_hbr_rbr,
 204	.swing_hbr3_hbr2 = &edp_swing_hbr2_hbr3,
 205	.pre_emphasis_hbr_rbr = &edp_pre_emp_hbr_rbr_v5,
 206	.pre_emphasis_hbr3_hbr2 = &edp_pre_emp_hbr2_hbr3_v5,
 207};
 208
 209static const u8 edp_phy_aux_cfg_v5[10] = {
 210	0x00, 0x13, 0xa4, 0x00, 0x0a, 0x26, 0x0a, 0x03, 0x37, 0x03
 211};
 212
 213static int qcom_edp_phy_init(struct phy *phy)
 214{
 215	struct qcom_edp *edp = phy_get_drvdata(phy);
 216	u8 aux_cfg[DP_AUX_CFG_SIZE];
 217	int ret;
 218
 219	ret = regulator_bulk_enable(ARRAY_SIZE(edp->supplies), edp->supplies);
 220	if (ret)
 221		return ret;
 222
 223	ret = clk_bulk_prepare_enable(edp->num_clks, edp->clks);
 224	if (ret)
 225		goto out_disable_supplies;
 226
 227	memcpy(aux_cfg, edp->cfg->aux_cfg, sizeof(aux_cfg));
 228
 229	writel(DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN |
 230	       DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN,
 231	       edp->edp + DP_PHY_PD_CTL);
 232
 233	ret = edp->cfg->ver_ops->com_bias_en_clkbuflr(edp);
 234	if (ret)
 235		return ret;
 236
 237	writel(DP_PHY_PD_CTL_PSR_PWRDN, edp->edp + DP_PHY_PD_CTL);
 238	msleep(20);
 239
 240	writel(DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN |
 241	       DP_PHY_PD_CTL_LANE_0_1_PWRDN | DP_PHY_PD_CTL_LANE_2_3_PWRDN |
 242	       DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN,
 243	       edp->edp + DP_PHY_PD_CTL);
 244
 245	/*
 246	 * TODO: Re-work the conditions around setting the cfg8 value
 247	 * when more information becomes available about why this is
 248	 * even needed.
 249	 */
 250	if (edp->cfg->swing_pre_emph_cfg && !edp->is_edp)
 251		aux_cfg[8] = 0xb7;
 252
 253	writel(0xfc, edp->edp + DP_PHY_MODE);
 254
 255	for (int i = 0; i < DP_AUX_CFG_SIZE; i++)
 256		writel(aux_cfg[i], edp->edp + DP_PHY_AUX_CFG(i));
 257
 258	writel(PHY_AUX_STOP_ERR_MASK | PHY_AUX_DEC_ERR_MASK |
 259	       PHY_AUX_SYNC_ERR_MASK | PHY_AUX_ALIGN_ERR_MASK |
 260	       PHY_AUX_REQ_ERR_MASK, edp->edp + DP_PHY_AUX_INTERRUPT_MASK);
 261
 262	msleep(20);
 263
 264	return 0;
 265
 266out_disable_supplies:
 267	regulator_bulk_disable(ARRAY_SIZE(edp->supplies), edp->supplies);
 268
 269	return ret;
 270}
 271
 272static int qcom_edp_set_voltages(struct qcom_edp *edp, const struct phy_configure_opts_dp *dp_opts)
 273{
 274	const struct qcom_edp_swing_pre_emph_cfg *cfg = edp->cfg->swing_pre_emph_cfg;
 275	unsigned int v_level = 0;
 276	unsigned int p_level = 0;
 277	u8 ldo_config;
 278	u8 swing;
 279	u8 emph;
 280	int i;
 281
 282	if (!cfg)
 283		return 0;
 284
 285	if (edp->is_edp)
 286		cfg = &edp_phy_swing_pre_emph_cfg;
 287
 288	for (i = 0; i < dp_opts->lanes; i++) {
 289		v_level = max(v_level, dp_opts->voltage[i]);
 290		p_level = max(p_level, dp_opts->pre[i]);
 291	}
 292
 293	if (dp_opts->link_rate <= 2700) {
 294		swing = (*cfg->swing_hbr_rbr)[v_level][p_level];
 295		emph = (*cfg->pre_emphasis_hbr_rbr)[v_level][p_level];
 296	} else {
 297		swing = (*cfg->swing_hbr3_hbr2)[v_level][p_level];
 298		emph = (*cfg->pre_emphasis_hbr3_hbr2)[v_level][p_level];
 299	}
 300
 301	if (swing == 0xff || emph == 0xff)
 302		return -EINVAL;
 303
 304	ldo_config = edp->is_edp ? 0x0 : 0x1;
 305
 306	writel(ldo_config, edp->tx0 + TXn_LDO_CONFIG);
 307	writel(swing, edp->tx0 + TXn_TX_DRV_LVL);
 308	writel(emph, edp->tx0 + TXn_TX_EMP_POST1_LVL);
 309
 310	writel(ldo_config, edp->tx1 + TXn_LDO_CONFIG);
 311	writel(swing, edp->tx1 + TXn_TX_DRV_LVL);
 312	writel(emph, edp->tx1 + TXn_TX_EMP_POST1_LVL);
 313
 314	return 0;
 315}
 316
 317static int qcom_edp_phy_configure(struct phy *phy, union phy_configure_opts *opts)
 318{
 319	const struct phy_configure_opts_dp *dp_opts = &opts->dp;
 320	struct qcom_edp *edp = phy_get_drvdata(phy);
 321	int ret = 0;
 322
 323	memcpy(&edp->dp_opts, dp_opts, sizeof(*dp_opts));
 324
 325	if (dp_opts->set_voltages)
 326		ret = qcom_edp_set_voltages(edp, dp_opts);
 327
 328	return ret;
 329}
 330
 331static int qcom_edp_configure_ssc(const struct qcom_edp *edp)
 332{
 333	return edp->cfg->ver_ops->com_configure_ssc(edp);
 334}
 335
 336static int qcom_edp_configure_pll(const struct qcom_edp *edp)
 337{
 338	return edp->cfg->ver_ops->com_configure_pll(edp);
 339}
 340
 341static int qcom_edp_set_vco_div(const struct qcom_edp *edp, unsigned long *pixel_freq)
 342{
 343	const struct phy_configure_opts_dp *dp_opts = &edp->dp_opts;
 344	u32 vco_div;
 345
 346	switch (dp_opts->link_rate) {
 347	case 1620:
 348		vco_div = 0x1;
 349		*pixel_freq = 1620000000UL / 2;
 350		break;
 351
 352	case 2700:
 353		vco_div = 0x1;
 354		*pixel_freq = 2700000000UL / 2;
 355		break;
 356
 357	case 5400:
 358		vco_div = 0x2;
 359		*pixel_freq = 5400000000UL / 4;
 360		break;
 361
 362	case 8100:
 363		vco_div = 0x0;
 364		*pixel_freq = 8100000000UL / 6;
 365		break;
 366
 367	default:
 368		/* Other link rates aren't supported */
 369		return -EINVAL;
 370	}
 371
 372	writel(vco_div, edp->edp + DP_PHY_VCO_DIV);
 373
 374	return 0;
 375}
 376
 377static int qcom_edp_phy_power_on_v4(const struct qcom_edp *edp)
 378{
 379	u32 val;
 380
 381	writel(DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN |
 382	       DP_PHY_PD_CTL_LANE_0_1_PWRDN | DP_PHY_PD_CTL_LANE_2_3_PWRDN |
 383	       DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN,
 384	       edp->edp + DP_PHY_PD_CTL);
 385	writel(0xfc, edp->edp + DP_PHY_MODE);
 386
 387	return readl_poll_timeout(edp->pll + QSERDES_V4_COM_CMN_STATUS,
 388				     val, val & BIT(7), 5, 200);
 389}
 390
 391static int qcom_edp_phy_com_resetsm_cntrl_v4(const struct qcom_edp *edp)
 392{
 393	u32 val;
 394
 395	writel(0x20, edp->pll + QSERDES_V4_COM_RESETSM_CNTRL);
 396
 397	return readl_poll_timeout(edp->pll + QSERDES_V4_COM_C_READY_STATUS,
 398				     val, val & BIT(0), 500, 10000);
 399}
 400
 401static int qcom_edp_com_bias_en_clkbuflr_v4(const struct qcom_edp *edp)
 402{
 403	/* Turn on BIAS current for PHY/PLL */
 404	writel(0x17, edp->pll + QSERDES_V4_COM_BIAS_EN_CLKBUFLR_EN);
 405
 406	return 0;
 407}
 408
 409static int qcom_edp_com_configure_ssc_v4(const struct qcom_edp *edp)
 410{
 411	const struct phy_configure_opts_dp *dp_opts = &edp->dp_opts;
 412	u32 step1;
 413	u32 step2;
 414
 415	switch (dp_opts->link_rate) {
 416	case 1620:
 417	case 2700:
 418	case 8100:
 419		step1 = 0x45;
 420		step2 = 0x06;
 421		break;
 422
 423	case 5400:
 424		step1 = 0x5c;
 425		step2 = 0x08;
 426		break;
 427
 428	default:
 429		/* Other link rates aren't supported */
 430		return -EINVAL;
 431	}
 432
 433	writel(0x01, edp->pll + QSERDES_V4_COM_SSC_EN_CENTER);
 434	writel(0x00, edp->pll + QSERDES_V4_COM_SSC_ADJ_PER1);
 435	writel(0x36, edp->pll + QSERDES_V4_COM_SSC_PER1);
 436	writel(0x01, edp->pll + QSERDES_V4_COM_SSC_PER2);
 437	writel(step1, edp->pll + QSERDES_V4_COM_SSC_STEP_SIZE1_MODE0);
 438	writel(step2, edp->pll + QSERDES_V4_COM_SSC_STEP_SIZE2_MODE0);
 439
 440	return 0;
 441}
 442
 443static int qcom_edp_com_configure_pll_v4(const struct qcom_edp *edp)
 444{
 445	const struct phy_configure_opts_dp *dp_opts = &edp->dp_opts;
 446	u32 div_frac_start2_mode0;
 447	u32 div_frac_start3_mode0;
 448	u32 dec_start_mode0;
 449	u32 lock_cmp1_mode0;
 450	u32 lock_cmp2_mode0;
 451	u32 hsclk_sel;
 452
 453	switch (dp_opts->link_rate) {
 454	case 1620:
 455		hsclk_sel = 0x5;
 456		dec_start_mode0 = 0x69;
 457		div_frac_start2_mode0 = 0x80;
 458		div_frac_start3_mode0 = 0x07;
 459		lock_cmp1_mode0 = 0x6f;
 460		lock_cmp2_mode0 = 0x08;
 461		break;
 462
 463	case 2700:
 464		hsclk_sel = 0x3;
 465		dec_start_mode0 = 0x69;
 466		div_frac_start2_mode0 = 0x80;
 467		div_frac_start3_mode0 = 0x07;
 468		lock_cmp1_mode0 = 0x0f;
 469		lock_cmp2_mode0 = 0x0e;
 470		break;
 471
 472	case 5400:
 473		hsclk_sel = 0x1;
 474		dec_start_mode0 = 0x8c;
 475		div_frac_start2_mode0 = 0x00;
 476		div_frac_start3_mode0 = 0x0a;
 477		lock_cmp1_mode0 = 0x1f;
 478		lock_cmp2_mode0 = 0x1c;
 479		break;
 480
 481	case 8100:
 482		hsclk_sel = 0x0;
 483		dec_start_mode0 = 0x69;
 484		div_frac_start2_mode0 = 0x80;
 485		div_frac_start3_mode0 = 0x07;
 486		lock_cmp1_mode0 = 0x2f;
 487		lock_cmp2_mode0 = 0x2a;
 488		break;
 489
 490	default:
 491		/* Other link rates aren't supported */
 492		return -EINVAL;
 493	}
 494
 495	writel(0x01, edp->pll + QSERDES_V4_COM_SVS_MODE_CLK_SEL);
 496	writel(0x0b, edp->pll + QSERDES_V4_COM_SYSCLK_EN_SEL);
 497	writel(0x02, edp->pll + QSERDES_V4_COM_SYS_CLK_CTRL);
 498	writel(0x0c, edp->pll + QSERDES_V4_COM_CLK_ENABLE1);
 499	writel(0x06, edp->pll + QSERDES_V4_COM_SYSCLK_BUF_ENABLE);
 500	writel(0x30, edp->pll + QSERDES_V4_COM_CLK_SELECT);
 501	writel(hsclk_sel, edp->pll + QSERDES_V4_COM_HSCLK_SEL);
 502	writel(0x0f, edp->pll + QSERDES_V4_COM_PLL_IVCO);
 503	writel(0x08, edp->pll + QSERDES_V4_COM_LOCK_CMP_EN);
 504	writel(0x36, edp->pll + QSERDES_V4_COM_PLL_CCTRL_MODE0);
 505	writel(0x16, edp->pll + QSERDES_V4_COM_PLL_RCTRL_MODE0);
 506	writel(0x06, edp->pll + QSERDES_V4_COM_CP_CTRL_MODE0);
 507	writel(dec_start_mode0, edp->pll + QSERDES_V4_COM_DEC_START_MODE0);
 508	writel(0x00, edp->pll + QSERDES_V4_COM_DIV_FRAC_START1_MODE0);
 509	writel(div_frac_start2_mode0, edp->pll + QSERDES_V4_COM_DIV_FRAC_START2_MODE0);
 510	writel(div_frac_start3_mode0, edp->pll + QSERDES_V4_COM_DIV_FRAC_START3_MODE0);
 511	writel(0x02, edp->pll + QSERDES_V4_COM_CMN_CONFIG);
 512	writel(0x3f, edp->pll + QSERDES_V4_COM_INTEGLOOP_GAIN0_MODE0);
 513	writel(0x00, edp->pll + QSERDES_V4_COM_INTEGLOOP_GAIN1_MODE0);
 514	writel(0x00, edp->pll + QSERDES_V4_COM_VCO_TUNE_MAP);
 515	writel(lock_cmp1_mode0, edp->pll + QSERDES_V4_COM_LOCK_CMP1_MODE0);
 516	writel(lock_cmp2_mode0, edp->pll + QSERDES_V4_COM_LOCK_CMP2_MODE0);
 517
 518	writel(0x0a, edp->pll + QSERDES_V4_COM_BG_TIMER);
 519	writel(0x14, edp->pll + QSERDES_V4_COM_CORECLK_DIV_MODE0);
 520	writel(0x00, edp->pll + QSERDES_V4_COM_VCO_TUNE_CTRL);
 521	writel(0x17, edp->pll + QSERDES_V4_COM_BIAS_EN_CLKBUFLR_EN);
 522	writel(0x0f, edp->pll + QSERDES_V4_COM_CORE_CLK_EN);
 523	writel(0xa0, edp->pll + QSERDES_V4_COM_VCO_TUNE1_MODE0);
 524	writel(0x03, edp->pll + QSERDES_V4_COM_VCO_TUNE2_MODE0);
 525
 526	return 0;
 527}
 528
 529static const struct phy_ver_ops qcom_edp_phy_ops_v4 = {
 530	.com_power_on		= qcom_edp_phy_power_on_v4,
 531	.com_resetsm_cntrl	= qcom_edp_phy_com_resetsm_cntrl_v4,
 532	.com_bias_en_clkbuflr	= qcom_edp_com_bias_en_clkbuflr_v4,
 533	.com_configure_pll	= qcom_edp_com_configure_pll_v4,
 534	.com_configure_ssc	= qcom_edp_com_configure_ssc_v4,
 535};
 536
 537static const struct qcom_edp_phy_cfg sa8775p_dp_phy_cfg = {
 538	.is_edp = false,
 539	.aux_cfg = edp_phy_aux_cfg_v5,
 540	.swing_pre_emph_cfg = &edp_phy_swing_pre_emph_cfg_v5,
 541	.ver_ops = &qcom_edp_phy_ops_v4,
 542};
 543
 544static const struct qcom_edp_phy_cfg sc7280_dp_phy_cfg = {
 545	.aux_cfg = edp_phy_aux_cfg_v4,
 546	.ver_ops = &qcom_edp_phy_ops_v4,
 547};
 548
 549static const struct qcom_edp_phy_cfg sc8280xp_dp_phy_cfg = {
 550	.aux_cfg = edp_phy_aux_cfg_v4,
 551	.swing_pre_emph_cfg = &dp_phy_swing_pre_emph_cfg,
 552	.ver_ops = &qcom_edp_phy_ops_v4,
 553};
 554
 555static const struct qcom_edp_phy_cfg sc8280xp_edp_phy_cfg = {
 556	.is_edp = true,
 557	.aux_cfg = edp_phy_aux_cfg_v4,
 558	.swing_pre_emph_cfg = &edp_phy_swing_pre_emph_cfg,
 559	.ver_ops = &qcom_edp_phy_ops_v4,
 560};
 561
 562static int qcom_edp_phy_power_on_v6(const struct qcom_edp *edp)
 563{
 564	u32 val;
 565
 566	writel(DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN |
 567	       DP_PHY_PD_CTL_LANE_0_1_PWRDN | DP_PHY_PD_CTL_LANE_2_3_PWRDN |
 568	       DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN,
 569	       edp->edp + DP_PHY_PD_CTL);
 570	writel(0xfc, edp->edp + DP_PHY_MODE);
 571
 572	return readl_poll_timeout(edp->pll + QSERDES_V6_COM_CMN_STATUS,
 573				     val, val & BIT(7), 5, 200);
 574}
 575
 576static int qcom_edp_phy_com_resetsm_cntrl_v6(const struct qcom_edp *edp)
 577{
 578	u32 val;
 579
 580	writel(0x20, edp->pll + QSERDES_V6_COM_RESETSM_CNTRL);
 581
 582	return readl_poll_timeout(edp->pll + QSERDES_V6_COM_C_READY_STATUS,
 583				     val, val & BIT(0), 500, 10000);
 584}
 585
 586static int qcom_edp_com_bias_en_clkbuflr_v6(const struct qcom_edp *edp)
 587{
 588	/* Turn on BIAS current for PHY/PLL */
 589	writel(0x1f, edp->pll + QSERDES_V6_COM_PLL_BIAS_EN_CLK_BUFLR_EN);
 590
 591	return 0;
 592}
 593
 594static int qcom_edp_com_configure_ssc_v6(const struct qcom_edp *edp)
 595{
 596	const struct phy_configure_opts_dp *dp_opts = &edp->dp_opts;
 597	u32 step1;
 598	u32 step2;
 599
 600	switch (dp_opts->link_rate) {
 601	case 1620:
 602	case 2700:
 603	case 8100:
 604		step1 = 0x92;
 605		step2 = 0x01;
 606		break;
 607
 608	case 5400:
 609		step1 = 0x18;
 610		step2 = 0x02;
 611		break;
 612
 613	default:
 614		/* Other link rates aren't supported */
 615		return -EINVAL;
 616	}
 617
 618	writel(0x01, edp->pll + QSERDES_V6_COM_SSC_EN_CENTER);
 619	writel(0x00, edp->pll + QSERDES_V6_COM_SSC_ADJ_PER1);
 620	writel(0x36, edp->pll + QSERDES_V6_COM_SSC_PER1);
 621	writel(0x01, edp->pll + QSERDES_V6_COM_SSC_PER2);
 622	writel(step1, edp->pll + QSERDES_V6_COM_SSC_STEP_SIZE1_MODE0);
 623	writel(step2, edp->pll + QSERDES_V6_COM_SSC_STEP_SIZE2_MODE0);
 624
 625	return 0;
 626}
 627
 628static int qcom_edp_com_configure_pll_v6(const struct qcom_edp *edp)
 629{
 630	const struct phy_configure_opts_dp *dp_opts = &edp->dp_opts;
 631	u32 div_frac_start2_mode0;
 632	u32 div_frac_start3_mode0;
 633	u32 dec_start_mode0;
 634	u32 lock_cmp1_mode0;
 635	u32 lock_cmp2_mode0;
 636	u32 code1_mode0;
 637	u32 code2_mode0;
 638	u32 hsclk_sel;
 639
 640	switch (dp_opts->link_rate) {
 641	case 1620:
 642		hsclk_sel = 0x5;
 643		dec_start_mode0 = 0x34;
 644		div_frac_start2_mode0 = 0xc0;
 645		div_frac_start3_mode0 = 0x0b;
 646		lock_cmp1_mode0 = 0x37;
 647		lock_cmp2_mode0 = 0x04;
 648		code1_mode0 = 0x71;
 649		code2_mode0 = 0x0c;
 650		break;
 651
 652	case 2700:
 653		hsclk_sel = 0x3;
 654		dec_start_mode0 = 0x34;
 655		div_frac_start2_mode0 = 0xc0;
 656		div_frac_start3_mode0 = 0x0b;
 657		lock_cmp1_mode0 = 0x07;
 658		lock_cmp2_mode0 = 0x07;
 659		code1_mode0 = 0x71;
 660		code2_mode0 = 0x0c;
 661		break;
 662
 663	case 5400:
 664		hsclk_sel = 0x1;
 665		dec_start_mode0 = 0x46;
 666		div_frac_start2_mode0 = 0x00;
 667		div_frac_start3_mode0 = 0x05;
 668		lock_cmp1_mode0 = 0x0f;
 669		lock_cmp2_mode0 = 0x0e;
 670		code1_mode0 = 0x97;
 671		code2_mode0 = 0x10;
 672		break;
 673
 674	case 8100:
 675		hsclk_sel = 0x0;
 676		dec_start_mode0 = 0x34;
 677		div_frac_start2_mode0 = 0xc0;
 678		div_frac_start3_mode0 = 0x0b;
 679		lock_cmp1_mode0 = 0x17;
 680		lock_cmp2_mode0 = 0x15;
 681		code1_mode0 = 0x71;
 682		code2_mode0 = 0x0c;
 683		break;
 684
 685	default:
 686		/* Other link rates aren't supported */
 687		return -EINVAL;
 688	}
 689
 690	writel(0x01, edp->pll + QSERDES_V6_COM_SVS_MODE_CLK_SEL);
 691	writel(0x0b, edp->pll + QSERDES_V6_COM_SYSCLK_EN_SEL);
 692	writel(0x02, edp->pll + QSERDES_V6_COM_SYS_CLK_CTRL);
 693	writel(0x0c, edp->pll + QSERDES_V6_COM_CLK_ENABLE1);
 694	writel(0x06, edp->pll + QSERDES_V6_COM_SYSCLK_BUF_ENABLE);
 695	writel(0x30, edp->pll + QSERDES_V6_COM_CLK_SELECT);
 696	writel(hsclk_sel, edp->pll + QSERDES_V6_COM_HSCLK_SEL_1);
 697	writel(0x07, edp->pll + QSERDES_V6_COM_PLL_IVCO);
 698	writel(0x08, edp->pll + QSERDES_V6_COM_LOCK_CMP_EN);
 699	writel(0x36, edp->pll + QSERDES_V6_COM_PLL_CCTRL_MODE0);
 700	writel(0x16, edp->pll + QSERDES_V6_COM_PLL_RCTRL_MODE0);
 701	writel(0x06, edp->pll + QSERDES_V6_COM_CP_CTRL_MODE0);
 702	writel(dec_start_mode0, edp->pll + QSERDES_V6_COM_DEC_START_MODE0);
 703	writel(0x00, edp->pll + QSERDES_V6_COM_DIV_FRAC_START1_MODE0);
 704	writel(div_frac_start2_mode0, edp->pll + QSERDES_V6_COM_DIV_FRAC_START2_MODE0);
 705	writel(div_frac_start3_mode0, edp->pll + QSERDES_V6_COM_DIV_FRAC_START3_MODE0);
 706	writel(0x12, edp->pll + QSERDES_V6_COM_CMN_CONFIG_1);
 707	writel(0x3f, edp->pll + QSERDES_V6_COM_INTEGLOOP_GAIN0_MODE0);
 708	writel(0x00, edp->pll + QSERDES_V6_COM_INTEGLOOP_GAIN1_MODE0);
 709	writel(0x00, edp->pll + QSERDES_V6_COM_VCO_TUNE_MAP);
 710	writel(lock_cmp1_mode0, edp->pll + QSERDES_V6_COM_LOCK_CMP1_MODE0);
 711	writel(lock_cmp2_mode0, edp->pll + QSERDES_V6_COM_LOCK_CMP2_MODE0);
 712
 713	writel(0x0a, edp->pll + QSERDES_V6_COM_BG_TIMER);
 714	writel(0x14, edp->pll + QSERDES_V6_COM_PLL_CORE_CLK_DIV_MODE0);
 715	writel(0x00, edp->pll + QSERDES_V6_COM_VCO_TUNE_CTRL);
 716	writel(0x1f, edp->pll + QSERDES_V6_COM_PLL_BIAS_EN_CLK_BUFLR_EN);
 717	writel(0x0f, edp->pll + QSERDES_V6_COM_CORE_CLK_EN);
 718	writel(0xa0, edp->pll + QSERDES_V6_COM_VCO_TUNE1_MODE0);
 719	writel(0x03, edp->pll + QSERDES_V6_COM_VCO_TUNE2_MODE0);
 720
 721	writel(code1_mode0, edp->pll + QSERDES_V6_COM_BIN_VCOCAL_CMP_CODE1_MODE0);
 722	writel(code2_mode0, edp->pll + QSERDES_V6_COM_BIN_VCOCAL_CMP_CODE2_MODE0);
 723
 724	return 0;
 725}
 726
 727static const struct phy_ver_ops qcom_edp_phy_ops_v6 = {
 728	.com_power_on		= qcom_edp_phy_power_on_v6,
 729	.com_resetsm_cntrl	= qcom_edp_phy_com_resetsm_cntrl_v6,
 730	.com_bias_en_clkbuflr	= qcom_edp_com_bias_en_clkbuflr_v6,
 731	.com_configure_pll	= qcom_edp_com_configure_pll_v6,
 732	.com_configure_ssc	= qcom_edp_com_configure_ssc_v6,
 733};
 734
 735static struct qcom_edp_phy_cfg x1e80100_phy_cfg = {
 736	.aux_cfg = edp_phy_aux_cfg_v4,
 737	.swing_pre_emph_cfg = &dp_phy_swing_pre_emph_cfg,
 738	.ver_ops = &qcom_edp_phy_ops_v6,
 739};
 740
 741static int qcom_edp_phy_power_on(struct phy *phy)
 742{
 743	const struct qcom_edp *edp = phy_get_drvdata(phy);
 744	u32 bias0_en, drvr0_en, bias1_en, drvr1_en;
 745	unsigned long pixel_freq;
 746	u8 ldo_config = 0x0;
 747	int ret;
 748	u32 val;
 749	u8 cfg1;
 750
 751	ret = edp->cfg->ver_ops->com_power_on(edp);
 752	if (ret)
 753		return ret;
 754
 755	if (edp->cfg->swing_pre_emph_cfg && !edp->is_edp)
 756		ldo_config = 0x1;
 757
 758	writel(ldo_config, edp->tx0 + TXn_LDO_CONFIG);
 759	writel(ldo_config, edp->tx1 + TXn_LDO_CONFIG);
 760	writel(0x00, edp->tx0 + TXn_LANE_MODE_1);
 761	writel(0x00, edp->tx1 + TXn_LANE_MODE_1);
 762
 763	if (edp->dp_opts.ssc) {
 764		ret = qcom_edp_configure_ssc(edp);
 765		if (ret)
 766			return ret;
 767	}
 768
 769	ret = qcom_edp_configure_pll(edp);
 770	if (ret)
 771		return ret;
 772
 773	/* TX Lane configuration */
 774	writel(0x05, edp->edp + DP_PHY_TX0_TX1_LANE_CTL);
 775	writel(0x05, edp->edp + DP_PHY_TX2_TX3_LANE_CTL);
 776
 777	/* TX-0 register configuration */
 778	writel(0x03, edp->tx0 + TXn_TRANSCEIVER_BIAS_EN);
 779	writel(0x0f, edp->tx0 + TXn_CLKBUF_ENABLE);
 780	writel(0x03, edp->tx0 + TXn_RESET_TSYNC_EN);
 781	writel(0x01, edp->tx0 + TXn_TRAN_DRVR_EMP_EN);
 782	writel(0x04, edp->tx0 + TXn_TX_BAND);
 783
 784	/* TX-1 register configuration */
 785	writel(0x03, edp->tx1 + TXn_TRANSCEIVER_BIAS_EN);
 786	writel(0x0f, edp->tx1 + TXn_CLKBUF_ENABLE);
 787	writel(0x03, edp->tx1 + TXn_RESET_TSYNC_EN);
 788	writel(0x01, edp->tx1 + TXn_TRAN_DRVR_EMP_EN);
 789	writel(0x04, edp->tx1 + TXn_TX_BAND);
 790
 791	ret = qcom_edp_set_vco_div(edp, &pixel_freq);
 792	if (ret)
 793		return ret;
 794
 795	writel(0x01, edp->edp + DP_PHY_CFG);
 796	writel(0x05, edp->edp + DP_PHY_CFG);
 797	writel(0x01, edp->edp + DP_PHY_CFG);
 798	writel(0x09, edp->edp + DP_PHY_CFG);
 799
 800	ret = edp->cfg->ver_ops->com_resetsm_cntrl(edp);
 801	if (ret)
 802		return ret;
 803
 804	writel(0x19, edp->edp + DP_PHY_CFG);
 805	writel(0x1f, edp->tx0 + TXn_HIGHZ_DRVR_EN);
 806	writel(0x04, edp->tx0 + TXn_HIGHZ_DRVR_EN);
 807	writel(0x00, edp->tx0 + TXn_TX_POL_INV);
 808	writel(0x1f, edp->tx1 + TXn_HIGHZ_DRVR_EN);
 809	writel(0x04, edp->tx1 + TXn_HIGHZ_DRVR_EN);
 810	writel(0x00, edp->tx1 + TXn_TX_POL_INV);
 811	writel(0x10, edp->tx0 + TXn_TX_DRV_LVL_OFFSET);
 812	writel(0x10, edp->tx1 + TXn_TX_DRV_LVL_OFFSET);
 813	writel(0x11, edp->tx0 + TXn_RES_CODE_LANE_OFFSET_TX0);
 814	writel(0x11, edp->tx0 + TXn_RES_CODE_LANE_OFFSET_TX1);
 815	writel(0x11, edp->tx1 + TXn_RES_CODE_LANE_OFFSET_TX0);
 816	writel(0x11, edp->tx1 + TXn_RES_CODE_LANE_OFFSET_TX1);
 817
 818	writel(0x10, edp->tx0 + TXn_TX_EMP_POST1_LVL);
 819	writel(0x10, edp->tx1 + TXn_TX_EMP_POST1_LVL);
 820	writel(0x1f, edp->tx0 + TXn_TX_DRV_LVL);
 821	writel(0x1f, edp->tx1 + TXn_TX_DRV_LVL);
 822
 823	if (edp->dp_opts.lanes == 1) {
 824		bias0_en = 0x01;
 825		bias1_en = 0x00;
 826		drvr0_en = 0x06;
 827		drvr1_en = 0x07;
 828		cfg1 = 0x1;
 829	} else if (edp->dp_opts.lanes == 2) {
 830		bias0_en = 0x03;
 831		bias1_en = 0x00;
 832		drvr0_en = 0x04;
 833		drvr1_en = 0x07;
 834		cfg1 = 0x3;
 835	} else {
 836		bias0_en = 0x03;
 837		bias1_en = 0x03;
 838		drvr0_en = 0x04;
 839		drvr1_en = 0x04;
 840		cfg1 = 0xf;
 841	}
 842
 843	writel(drvr0_en, edp->tx0 + TXn_HIGHZ_DRVR_EN);
 844	writel(bias0_en, edp->tx0 + TXn_TRANSCEIVER_BIAS_EN);
 845	writel(drvr1_en, edp->tx1 + TXn_HIGHZ_DRVR_EN);
 846	writel(bias1_en, edp->tx1 + TXn_TRANSCEIVER_BIAS_EN);
 847	writel(cfg1, edp->edp + DP_PHY_CFG_1);
 848
 849	writel(0x18, edp->edp + DP_PHY_CFG);
 850	usleep_range(100, 1000);
 851
 852	writel(0x19, edp->edp + DP_PHY_CFG);
 853
 854	ret = readl_poll_timeout(edp->edp + DP_PHY_STATUS,
 855				 val, val & BIT(1), 500, 10000);
 856	if (ret)
 857		return ret;
 858
 859	clk_set_rate(edp->dp_link_hw.clk, edp->dp_opts.link_rate * 100000);
 860	clk_set_rate(edp->dp_pixel_hw.clk, pixel_freq);
 861
 862	return 0;
 863}
 864
 865static int qcom_edp_phy_power_off(struct phy *phy)
 866{
 867	const struct qcom_edp *edp = phy_get_drvdata(phy);
 868
 869	writel(DP_PHY_PD_CTL_PSR_PWRDN, edp->edp + DP_PHY_PD_CTL);
 870
 871	return 0;
 872}
 873
 874static int qcom_edp_phy_set_mode(struct phy *phy, enum phy_mode mode, int submode)
 875{
 876	struct qcom_edp *edp = phy_get_drvdata(phy);
 877
 878	if (mode != PHY_MODE_DP)
 879		return -EINVAL;
 880
 881	edp->is_edp = submode == PHY_SUBMODE_EDP;
 882
 883	return 0;
 884}
 885
 886static int qcom_edp_phy_exit(struct phy *phy)
 887{
 888	struct qcom_edp *edp = phy_get_drvdata(phy);
 889
 890	clk_bulk_disable_unprepare(edp->num_clks, edp->clks);
 891	regulator_bulk_disable(ARRAY_SIZE(edp->supplies), edp->supplies);
 892
 893	return 0;
 894}
 895
 896static const struct phy_ops qcom_edp_ops = {
 897	.init		= qcom_edp_phy_init,
 898	.configure	= qcom_edp_phy_configure,
 899	.power_on	= qcom_edp_phy_power_on,
 900	.power_off	= qcom_edp_phy_power_off,
 901	.set_mode	= qcom_edp_phy_set_mode,
 902	.exit		= qcom_edp_phy_exit,
 903	.owner		= THIS_MODULE,
 904};
 905
 906/*
 907 * Embedded Display Port PLL driver block diagram for branch clocks
 908 *
 909 *              +------------------------------+
 910 *              |        EDP_VCO_CLK           |
 911 *              |                              |
 912 *              |    +-------------------+     |
 913 *              |    |  (EDP PLL/VCO)    |     |
 914 *              |    +---------+---------+     |
 915 *              |              v               |
 916 *              |   +----------+-----------+   |
 917 *              |   | hsclk_divsel_clk_src |   |
 918 *              |   +----------+-----------+   |
 919 *              +------------------------------+
 920 *                              |
 921 *          +---------<---------v------------>----------+
 922 *          |                                           |
 923 * +--------v----------------+                          |
 924 * |   edp_phy_pll_link_clk  |                          |
 925 * |     link_clk            |                          |
 926 * +--------+----------------+                          |
 927 *          |                                           |
 928 *          |                                           |
 929 *          v                                           v
 930 * Input to DISPCC block                                |
 931 * for link clk, crypto clk                             |
 932 * and interface clock                                  |
 933 *                                                      |
 934 *                                                      |
 935 *      +--------<------------+-----------------+---<---+
 936 *      |                     |                 |
 937 * +----v---------+  +--------v-----+  +--------v------+
 938 * | vco_divided  |  | vco_divided  |  | vco_divided   |
 939 * |    _clk_src  |  |    _clk_src  |  |    _clk_src   |
 940 * |              |  |              |  |               |
 941 * |divsel_six    |  |  divsel_two  |  |  divsel_four  |
 942 * +-------+------+  +-----+--------+  +--------+------+
 943 *         |                 |                  |
 944 *         v---->----------v-------------<------v
 945 *                         |
 946 *              +----------+-----------------+
 947 *              |   edp_phy_pll_vco_div_clk  |
 948 *              +---------+------------------+
 949 *                        |
 950 *                        v
 951 *              Input to DISPCC block
 952 *              for EDP pixel clock
 953 *
 954 */
 955static int qcom_edp_dp_pixel_clk_determine_rate(struct clk_hw *hw,
 956						struct clk_rate_request *req)
 957{
 958	switch (req->rate) {
 959	case 1620000000UL / 2:
 960	case 2700000000UL / 2:
 961	/* 5.4 and 8.1 GHz are same link rate as 2.7GHz, i.e. div 4 and div 6 */
 962		return 0;
 963
 964	default:
 965		return -EINVAL;
 966	}
 967}
 968
 969static unsigned long
 970qcom_edp_dp_pixel_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
 971{
 972	const struct qcom_edp *edp = container_of(hw, struct qcom_edp, dp_pixel_hw);
 973	const struct phy_configure_opts_dp *dp_opts = &edp->dp_opts;
 974
 975	switch (dp_opts->link_rate) {
 976	case 1620:
 977		return 1620000000UL / 2;
 978	case 2700:
 979		return 2700000000UL / 2;
 980	case 5400:
 981		return 5400000000UL / 4;
 982	case 8100:
 983		return 8100000000UL / 6;
 984	default:
 985		return 0;
 986	}
 987}
 988
 989static const struct clk_ops qcom_edp_dp_pixel_clk_ops = {
 990	.determine_rate = qcom_edp_dp_pixel_clk_determine_rate,
 991	.recalc_rate = qcom_edp_dp_pixel_clk_recalc_rate,
 992};
 993
 994static int qcom_edp_dp_link_clk_determine_rate(struct clk_hw *hw,
 995					       struct clk_rate_request *req)
 996{
 997	switch (req->rate) {
 998	case 162000000:
 999	case 270000000:
1000	case 540000000:
1001	case 810000000:
1002		return 0;
1003
1004	default:
1005		return -EINVAL;
1006	}
1007}
1008
1009static unsigned long
1010qcom_edp_dp_link_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
1011{
1012	const struct qcom_edp *edp = container_of(hw, struct qcom_edp, dp_link_hw);
1013	const struct phy_configure_opts_dp *dp_opts = &edp->dp_opts;
1014
1015	switch (dp_opts->link_rate) {
1016	case 1620:
1017	case 2700:
1018	case 5400:
1019	case 8100:
1020		return dp_opts->link_rate * 100000;
1021
1022	default:
1023		return 0;
1024	}
1025}
1026
1027static const struct clk_ops qcom_edp_dp_link_clk_ops = {
1028	.determine_rate = qcom_edp_dp_link_clk_determine_rate,
1029	.recalc_rate = qcom_edp_dp_link_clk_recalc_rate,
1030};
1031
1032static int qcom_edp_clks_register(struct qcom_edp *edp, struct device_node *np)
1033{
1034	struct clk_hw_onecell_data *data;
1035	struct clk_init_data init = { };
1036	char name[64];
1037	int ret;
1038
1039	data = devm_kzalloc(edp->dev, struct_size(data, hws, 2), GFP_KERNEL);
1040	if (!data)
1041		return -ENOMEM;
1042	data->num = 2;
1043
1044	snprintf(name, sizeof(name), "%s::link_clk", dev_name(edp->dev));
1045	init.ops = &qcom_edp_dp_link_clk_ops;
1046	init.name = name;
1047	edp->dp_link_hw.init = &init;
1048	ret = devm_clk_hw_register(edp->dev, &edp->dp_link_hw);
1049	if (ret)
1050		return ret;
1051
1052	snprintf(name, sizeof(name), "%s::vco_div_clk", dev_name(edp->dev));
1053	init.ops = &qcom_edp_dp_pixel_clk_ops;
1054	init.name = name;
1055	edp->dp_pixel_hw.init = &init;
1056	ret = devm_clk_hw_register(edp->dev, &edp->dp_pixel_hw);
1057	if (ret)
1058		return ret;
1059
1060	data->hws[0] = &edp->dp_link_hw;
1061	data->hws[1] = &edp->dp_pixel_hw;
1062
1063	return devm_of_clk_add_hw_provider(edp->dev, of_clk_hw_onecell_get, data);
1064}
1065
1066static int qcom_edp_phy_probe(struct platform_device *pdev)
1067{
1068	struct phy_provider *phy_provider;
1069	struct device *dev = &pdev->dev;
1070	struct qcom_edp *edp;
1071	int ret;
1072
1073	edp = devm_kzalloc(dev, sizeof(*edp), GFP_KERNEL);
1074	if (!edp)
1075		return -ENOMEM;
1076
1077	edp->dev = dev;
1078	edp->cfg = of_device_get_match_data(&pdev->dev);
1079	edp->is_edp = edp->cfg->is_edp;
1080
1081	edp->edp = devm_platform_ioremap_resource(pdev, 0);
1082	if (IS_ERR(edp->edp))
1083		return PTR_ERR(edp->edp);
1084
1085	edp->tx0 = devm_platform_ioremap_resource(pdev, 1);
1086	if (IS_ERR(edp->tx0))
1087		return PTR_ERR(edp->tx0);
1088
1089	edp->tx1 = devm_platform_ioremap_resource(pdev, 2);
1090	if (IS_ERR(edp->tx1))
1091		return PTR_ERR(edp->tx1);
1092
1093	edp->pll = devm_platform_ioremap_resource(pdev, 3);
1094	if (IS_ERR(edp->pll))
1095		return PTR_ERR(edp->pll);
1096
1097	edp->num_clks = devm_clk_bulk_get_all(dev, &edp->clks);
1098	if (edp->num_clks < 0)
1099		return dev_err_probe(dev, edp->num_clks, "failed to get clocks\n");
1100
1101	edp->supplies[0].supply = "vdda-phy";
1102	edp->supplies[1].supply = "vdda-pll";
1103	ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(edp->supplies), edp->supplies);
1104	if (ret)
1105		return ret;
1106
1107	ret = regulator_set_load(edp->supplies[0].consumer, 21800); /* 1.2 V vdda-phy */
1108	if (ret) {
1109		dev_err(dev, "failed to set load at %s\n", edp->supplies[0].supply);
1110		return ret;
1111	}
1112
1113	ret = regulator_set_load(edp->supplies[1].consumer, 36000); /* 0.9 V vdda-pll */
1114	if (ret) {
1115		dev_err(dev, "failed to set load at %s\n", edp->supplies[1].supply);
1116		return ret;
1117	}
1118
1119	ret = qcom_edp_clks_register(edp, pdev->dev.of_node);
1120	if (ret)
1121		return ret;
1122
1123	edp->phy = devm_phy_create(dev, pdev->dev.of_node, &qcom_edp_ops);
1124	if (IS_ERR(edp->phy)) {
1125		dev_err(dev, "failed to register phy\n");
1126		return PTR_ERR(edp->phy);
1127	}
1128
1129	phy_set_drvdata(edp->phy, edp);
1130
1131	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
1132	return PTR_ERR_OR_ZERO(phy_provider);
1133}
1134
1135static const struct of_device_id qcom_edp_phy_match_table[] = {
1136	{ .compatible = "qcom,sa8775p-edp-phy", .data = &sa8775p_dp_phy_cfg, },
1137	{ .compatible = "qcom,sc7280-edp-phy", .data = &sc7280_dp_phy_cfg, },
1138	{ .compatible = "qcom,sc8180x-edp-phy", .data = &sc7280_dp_phy_cfg, },
1139	{ .compatible = "qcom,sc8280xp-dp-phy", .data = &sc8280xp_dp_phy_cfg, },
1140	{ .compatible = "qcom,sc8280xp-edp-phy", .data = &sc8280xp_edp_phy_cfg, },
1141	{ .compatible = "qcom,x1e80100-dp-phy", .data = &x1e80100_phy_cfg, },
1142	{ }
1143};
1144MODULE_DEVICE_TABLE(of, qcom_edp_phy_match_table);
1145
1146static struct platform_driver qcom_edp_phy_driver = {
1147	.probe		= qcom_edp_phy_probe,
1148	.driver = {
1149		.name	= "qcom-edp-phy",
1150		.of_match_table = qcom_edp_phy_match_table,
1151	},
1152};
1153
1154module_platform_driver(qcom_edp_phy_driver);
1155
1156MODULE_AUTHOR("Bjorn Andersson <bjorn.andersson@linaro.org>");
1157MODULE_DESCRIPTION("Qualcomm eDP QMP PHY driver");
1158MODULE_LICENSE("GPL v2");
~/ Read-only file preview.