phy-qcom-edp.c 31 KB

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