Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Copyright (c) 2017, 2020, The Linux Foundation. All rights reserved.
0004  * Copyright (c) 2021, Linaro Ltd.
0005  */
0006 
0007 #include <linux/clk.h>
0008 #include <linux/clk-provider.h>
0009 #include <linux/delay.h>
0010 #include <linux/err.h>
0011 #include <linux/io.h>
0012 #include <linux/iopoll.h>
0013 #include <linux/kernel.h>
0014 #include <linux/module.h>
0015 #include <linux/of.h>
0016 #include <linux/of_device.h>
0017 #include <linux/of_address.h>
0018 #include <linux/phy/phy.h>
0019 #include <linux/platform_device.h>
0020 #include <linux/regulator/consumer.h>
0021 #include <linux/reset.h>
0022 #include <linux/slab.h>
0023 
0024 #include <dt-bindings/phy/phy.h>
0025 
0026 #include "phy-qcom-qmp.h"
0027 
0028 /* EDP_PHY registers */
0029 #define DP_PHY_CFG                              0x0010
0030 #define DP_PHY_CFG_1                            0x0014
0031 #define DP_PHY_PD_CTL                           0x001c
0032 #define DP_PHY_MODE                             0x0020
0033 
0034 #define DP_PHY_AUX_CFG0             0x0024
0035 #define DP_PHY_AUX_CFG1             0x0028
0036 #define DP_PHY_AUX_CFG2             0x002C
0037 #define DP_PHY_AUX_CFG3             0x0030
0038 #define DP_PHY_AUX_CFG4             0x0034
0039 #define DP_PHY_AUX_CFG5             0x0038
0040 #define DP_PHY_AUX_CFG6             0x003C
0041 #define DP_PHY_AUX_CFG7             0x0040
0042 #define DP_PHY_AUX_CFG8             0x0044
0043 #define DP_PHY_AUX_CFG9             0x0048
0044 
0045 #define DP_PHY_AUX_INTERRUPT_MASK       0x0058
0046 
0047 #define DP_PHY_VCO_DIV                          0x0074
0048 #define DP_PHY_TX0_TX1_LANE_CTL                 0x007c
0049 #define DP_PHY_TX2_TX3_LANE_CTL                 0x00a0
0050 
0051 #define DP_PHY_STATUS                           0x00e0
0052 
0053 /* LANE_TXn registers */
0054 #define TXn_CLKBUF_ENABLE                       0x0000
0055 #define TXn_TX_EMP_POST1_LVL                    0x0004
0056 
0057 #define TXn_TX_DRV_LVL                          0x0014
0058 #define TXn_TX_DRV_LVL_OFFSET                   0x0018
0059 #define TXn_RESET_TSYNC_EN                      0x001c
0060 #define TXn_LDO_CONFIG                          0x0084
0061 #define TXn_TX_BAND                             0x0028
0062 
0063 #define TXn_RES_CODE_LANE_OFFSET_TX0            0x0044
0064 #define TXn_RES_CODE_LANE_OFFSET_TX1            0x0048
0065 
0066 #define TXn_TRANSCEIVER_BIAS_EN                 0x0054
0067 #define TXn_HIGHZ_DRVR_EN                       0x0058
0068 #define TXn_TX_POL_INV                          0x005c
0069 #define TXn_LANE_MODE_1                         0x0064
0070 
0071 #define TXn_TRAN_DRVR_EMP_EN                    0x0078
0072 
0073 struct qcom_edp {
0074     struct device *dev;
0075 
0076     struct phy *phy;
0077 
0078     void __iomem *edp;
0079     void __iomem *tx0;
0080     void __iomem *tx1;
0081     void __iomem *pll;
0082 
0083     struct clk_hw dp_link_hw;
0084     struct clk_hw dp_pixel_hw;
0085 
0086     struct phy_configure_opts_dp dp_opts;
0087 
0088     struct clk_bulk_data clks[2];
0089     struct regulator_bulk_data supplies[2];
0090 };
0091 
0092 static int qcom_edp_phy_init(struct phy *phy)
0093 {
0094     struct qcom_edp *edp = phy_get_drvdata(phy);
0095     int ret;
0096 
0097     ret = regulator_bulk_enable(ARRAY_SIZE(edp->supplies), edp->supplies);
0098     if (ret)
0099         return ret;
0100 
0101     ret = clk_bulk_prepare_enable(ARRAY_SIZE(edp->clks), edp->clks);
0102     if (ret)
0103         goto out_disable_supplies;
0104 
0105     writel(DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN |
0106            DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN,
0107            edp->edp + DP_PHY_PD_CTL);
0108 
0109     /* Turn on BIAS current for PHY/PLL */
0110     writel(0x17, edp->pll + QSERDES_V4_COM_BIAS_EN_CLKBUFLR_EN);
0111 
0112     writel(DP_PHY_PD_CTL_PSR_PWRDN, edp->edp + DP_PHY_PD_CTL);
0113     msleep(20);
0114 
0115     writel(DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN |
0116            DP_PHY_PD_CTL_LANE_0_1_PWRDN | DP_PHY_PD_CTL_LANE_2_3_PWRDN |
0117            DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN,
0118            edp->edp + DP_PHY_PD_CTL);
0119 
0120     writel(0x00, edp->edp + DP_PHY_AUX_CFG0);
0121     writel(0x13, edp->edp + DP_PHY_AUX_CFG1);
0122     writel(0x24, edp->edp + DP_PHY_AUX_CFG2);
0123     writel(0x00, edp->edp + DP_PHY_AUX_CFG3);
0124     writel(0x0a, edp->edp + DP_PHY_AUX_CFG4);
0125     writel(0x26, edp->edp + DP_PHY_AUX_CFG5);
0126     writel(0x0a, edp->edp + DP_PHY_AUX_CFG6);
0127     writel(0x03, edp->edp + DP_PHY_AUX_CFG7);
0128     writel(0x37, edp->edp + DP_PHY_AUX_CFG8);
0129     writel(0x03, edp->edp + DP_PHY_AUX_CFG9);
0130 
0131     writel(PHY_AUX_STOP_ERR_MASK | PHY_AUX_DEC_ERR_MASK |
0132            PHY_AUX_SYNC_ERR_MASK | PHY_AUX_ALIGN_ERR_MASK |
0133            PHY_AUX_REQ_ERR_MASK, edp->edp + DP_PHY_AUX_INTERRUPT_MASK);
0134 
0135     msleep(20);
0136 
0137     return 0;
0138 
0139 out_disable_supplies:
0140     regulator_bulk_disable(ARRAY_SIZE(edp->supplies), edp->supplies);
0141 
0142     return ret;
0143 }
0144 
0145 static int qcom_edp_phy_configure(struct phy *phy, union phy_configure_opts *opts)
0146 {
0147     const struct phy_configure_opts_dp *dp_opts = &opts->dp;
0148     struct qcom_edp *edp = phy_get_drvdata(phy);
0149 
0150     memcpy(&edp->dp_opts, dp_opts, sizeof(*dp_opts));
0151 
0152     return 0;
0153 }
0154 
0155 static int qcom_edp_configure_ssc(const struct qcom_edp *edp)
0156 {
0157     const struct phy_configure_opts_dp *dp_opts = &edp->dp_opts;
0158     u32 step1;
0159     u32 step2;
0160 
0161     switch (dp_opts->link_rate) {
0162     case 1620:
0163     case 2700:
0164     case 8100:
0165         step1 = 0x45;
0166         step2 = 0x06;
0167         break;
0168 
0169     case 5400:
0170         step1 = 0x5c;
0171         step2 = 0x08;
0172         break;
0173 
0174     default:
0175         /* Other link rates aren't supported */
0176         return -EINVAL;
0177     }
0178 
0179     writel(0x01, edp->pll + QSERDES_V4_COM_SSC_EN_CENTER);
0180     writel(0x00, edp->pll + QSERDES_V4_COM_SSC_ADJ_PER1);
0181     writel(0x36, edp->pll + QSERDES_V4_COM_SSC_PER1);
0182     writel(0x01, edp->pll + QSERDES_V4_COM_SSC_PER2);
0183     writel(step1, edp->pll + QSERDES_V4_COM_SSC_STEP_SIZE1_MODE0);
0184     writel(step2, edp->pll + QSERDES_V4_COM_SSC_STEP_SIZE2_MODE0);
0185 
0186     return 0;
0187 }
0188 
0189 static int qcom_edp_configure_pll(const struct qcom_edp *edp)
0190 {
0191     const struct phy_configure_opts_dp *dp_opts = &edp->dp_opts;
0192     u32 div_frac_start2_mode0;
0193     u32 div_frac_start3_mode0;
0194     u32 dec_start_mode0;
0195     u32 lock_cmp1_mode0;
0196     u32 lock_cmp2_mode0;
0197     u32 hsclk_sel;
0198 
0199     switch (dp_opts->link_rate) {
0200     case 1620:
0201         hsclk_sel = 0x5;
0202         dec_start_mode0 = 0x69;
0203         div_frac_start2_mode0 = 0x80;
0204         div_frac_start3_mode0 = 0x07;
0205         lock_cmp1_mode0 = 0x6f;
0206         lock_cmp2_mode0 = 0x08;
0207         break;
0208 
0209     case 2700:
0210         hsclk_sel = 0x3;
0211         dec_start_mode0 = 0x69;
0212         div_frac_start2_mode0 = 0x80;
0213         div_frac_start3_mode0 = 0x07;
0214         lock_cmp1_mode0 = 0x0f;
0215         lock_cmp2_mode0 = 0x0e;
0216         break;
0217 
0218     case 5400:
0219         hsclk_sel = 0x1;
0220         dec_start_mode0 = 0x8c;
0221         div_frac_start2_mode0 = 0x00;
0222         div_frac_start3_mode0 = 0x0a;
0223         lock_cmp1_mode0 = 0x1f;
0224         lock_cmp2_mode0 = 0x1c;
0225         break;
0226 
0227     case 8100:
0228         hsclk_sel = 0x0;
0229         dec_start_mode0 = 0x69;
0230         div_frac_start2_mode0 = 0x80;
0231         div_frac_start3_mode0 = 0x07;
0232         lock_cmp1_mode0 = 0x2f;
0233         lock_cmp2_mode0 = 0x2a;
0234         break;
0235 
0236     default:
0237         /* Other link rates aren't supported */
0238         return -EINVAL;
0239     }
0240 
0241     writel(0x01, edp->pll + QSERDES_V4_COM_SVS_MODE_CLK_SEL);
0242     writel(0x0b, edp->pll + QSERDES_V4_COM_SYSCLK_EN_SEL);
0243     writel(0x02, edp->pll + QSERDES_V4_COM_SYS_CLK_CTRL);
0244     writel(0x0c, edp->pll + QSERDES_V4_COM_CLK_ENABLE1);
0245     writel(0x06, edp->pll + QSERDES_V4_COM_SYSCLK_BUF_ENABLE);
0246     writel(0x30, edp->pll + QSERDES_V4_COM_CLK_SELECT);
0247     writel(hsclk_sel, edp->pll + QSERDES_V4_COM_HSCLK_SEL);
0248     writel(0x0f, edp->pll + QSERDES_V4_COM_PLL_IVCO);
0249     writel(0x08, edp->pll + QSERDES_V4_COM_LOCK_CMP_EN);
0250     writel(0x36, edp->pll + QSERDES_V4_COM_PLL_CCTRL_MODE0);
0251     writel(0x16, edp->pll + QSERDES_V4_COM_PLL_RCTRL_MODE0);
0252     writel(0x06, edp->pll + QSERDES_V4_COM_CP_CTRL_MODE0);
0253     writel(dec_start_mode0, edp->pll + QSERDES_V4_COM_DEC_START_MODE0);
0254     writel(0x00, edp->pll + QSERDES_V4_COM_DIV_FRAC_START1_MODE0);
0255     writel(div_frac_start2_mode0, edp->pll + QSERDES_V4_COM_DIV_FRAC_START2_MODE0);
0256     writel(div_frac_start3_mode0, edp->pll + QSERDES_V4_COM_DIV_FRAC_START3_MODE0);
0257     writel(0x02, edp->pll + QSERDES_V4_COM_CMN_CONFIG);
0258     writel(0x3f, edp->pll + QSERDES_V4_COM_INTEGLOOP_GAIN0_MODE0);
0259     writel(0x00, edp->pll + QSERDES_V4_COM_INTEGLOOP_GAIN1_MODE0);
0260     writel(0x00, edp->pll + QSERDES_V4_COM_VCO_TUNE_MAP);
0261     writel(lock_cmp1_mode0, edp->pll + QSERDES_V4_COM_LOCK_CMP1_MODE0);
0262     writel(lock_cmp2_mode0, edp->pll + QSERDES_V4_COM_LOCK_CMP2_MODE0);
0263 
0264     writel(0x0a, edp->pll + QSERDES_V4_COM_BG_TIMER);
0265     writel(0x14, edp->pll + QSERDES_V4_COM_CORECLK_DIV_MODE0);
0266     writel(0x00, edp->pll + QSERDES_V4_COM_VCO_TUNE_CTRL);
0267     writel(0x17, edp->pll + QSERDES_V4_COM_BIAS_EN_CLKBUFLR_EN);
0268     writel(0x0f, edp->pll + QSERDES_V4_COM_CORE_CLK_EN);
0269     writel(0xa0, edp->pll + QSERDES_V4_COM_VCO_TUNE1_MODE0);
0270     writel(0x03, edp->pll + QSERDES_V4_COM_VCO_TUNE2_MODE0);
0271 
0272     return 0;
0273 }
0274 
0275 static int qcom_edp_set_vco_div(const struct qcom_edp *edp)
0276 {
0277     const struct phy_configure_opts_dp *dp_opts = &edp->dp_opts;
0278     unsigned long pixel_freq;
0279     u32 vco_div;
0280 
0281     switch (dp_opts->link_rate) {
0282     case 1620:
0283         vco_div = 0x1;
0284         pixel_freq = 1620000000UL / 2;
0285         break;
0286 
0287     case 2700:
0288         vco_div = 0x1;
0289         pixel_freq = 2700000000UL / 2;
0290         break;
0291 
0292     case 5400:
0293         vco_div = 0x2;
0294         pixel_freq = 5400000000UL / 4;
0295         break;
0296 
0297     case 8100:
0298         vco_div = 0x0;
0299         pixel_freq = 8100000000UL / 6;
0300         break;
0301 
0302     default:
0303         /* Other link rates aren't supported */
0304         return -EINVAL;
0305     }
0306 
0307     writel(vco_div, edp->edp + DP_PHY_VCO_DIV);
0308 
0309     clk_set_rate(edp->dp_link_hw.clk, dp_opts->link_rate * 100000);
0310     clk_set_rate(edp->dp_pixel_hw.clk, pixel_freq);
0311 
0312     return 0;
0313 }
0314 
0315 static int qcom_edp_phy_power_on(struct phy *phy)
0316 {
0317     const struct qcom_edp *edp = phy_get_drvdata(phy);
0318     int timeout;
0319     int ret;
0320     u32 val;
0321 
0322     writel(DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN |
0323            DP_PHY_PD_CTL_LANE_0_1_PWRDN | DP_PHY_PD_CTL_LANE_2_3_PWRDN |
0324            DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN,
0325            edp->edp + DP_PHY_PD_CTL);
0326     writel(0xfc, edp->edp + DP_PHY_MODE);
0327 
0328     timeout = readl_poll_timeout(edp->pll + QSERDES_V4_COM_CMN_STATUS,
0329                      val, val & BIT(7), 5, 200);
0330     if (timeout)
0331         return timeout;
0332 
0333     writel(0x01, edp->tx0 + TXn_LDO_CONFIG);
0334     writel(0x01, edp->tx1 + TXn_LDO_CONFIG);
0335     writel(0x00, edp->tx0 + TXn_LANE_MODE_1);
0336     writel(0x00, edp->tx1 + TXn_LANE_MODE_1);
0337 
0338     if (edp->dp_opts.ssc) {
0339         ret = qcom_edp_configure_ssc(edp);
0340         if (ret)
0341             return ret;
0342     }
0343 
0344     ret = qcom_edp_configure_pll(edp);
0345     if (ret)
0346         return ret;
0347 
0348     /* TX Lane configuration */
0349     writel(0x05, edp->edp + DP_PHY_TX0_TX1_LANE_CTL);
0350     writel(0x05, edp->edp + DP_PHY_TX2_TX3_LANE_CTL);
0351 
0352     /* TX-0 register configuration */
0353     writel(0x03, edp->tx0 + TXn_TRANSCEIVER_BIAS_EN);
0354     writel(0x0f, edp->tx0 + TXn_CLKBUF_ENABLE);
0355     writel(0x03, edp->tx0 + TXn_RESET_TSYNC_EN);
0356     writel(0x01, edp->tx0 + TXn_TRAN_DRVR_EMP_EN);
0357     writel(0x04, edp->tx0 + TXn_TX_BAND);
0358 
0359     /* TX-1 register configuration */
0360     writel(0x03, edp->tx1 + TXn_TRANSCEIVER_BIAS_EN);
0361     writel(0x0f, edp->tx1 + TXn_CLKBUF_ENABLE);
0362     writel(0x03, edp->tx1 + TXn_RESET_TSYNC_EN);
0363     writel(0x01, edp->tx1 + TXn_TRAN_DRVR_EMP_EN);
0364     writel(0x04, edp->tx1 + TXn_TX_BAND);
0365 
0366     ret = qcom_edp_set_vco_div(edp);
0367     if (ret)
0368         return ret;
0369 
0370     writel(0x01, edp->edp + DP_PHY_CFG);
0371     writel(0x05, edp->edp + DP_PHY_CFG);
0372     writel(0x01, edp->edp + DP_PHY_CFG);
0373     writel(0x09, edp->edp + DP_PHY_CFG);
0374 
0375     writel(0x20, edp->pll + QSERDES_V4_COM_RESETSM_CNTRL);
0376 
0377     timeout = readl_poll_timeout(edp->pll + QSERDES_V4_COM_C_READY_STATUS,
0378                      val, val & BIT(0), 500, 10000);
0379     if (timeout)
0380         return timeout;
0381 
0382     writel(0x19, edp->edp + DP_PHY_CFG);
0383     writel(0x1f, edp->tx0 + TXn_HIGHZ_DRVR_EN);
0384     writel(0x04, edp->tx0 + TXn_HIGHZ_DRVR_EN);
0385     writel(0x00, edp->tx0 + TXn_TX_POL_INV);
0386     writel(0x1f, edp->tx1 + TXn_HIGHZ_DRVR_EN);
0387     writel(0x04, edp->tx1 + TXn_HIGHZ_DRVR_EN);
0388     writel(0x00, edp->tx1 + TXn_TX_POL_INV);
0389     writel(0x10, edp->tx0 + TXn_TX_DRV_LVL_OFFSET);
0390     writel(0x10, edp->tx1 + TXn_TX_DRV_LVL_OFFSET);
0391     writel(0x11, edp->tx0 + TXn_RES_CODE_LANE_OFFSET_TX0);
0392     writel(0x11, edp->tx0 + TXn_RES_CODE_LANE_OFFSET_TX1);
0393     writel(0x11, edp->tx1 + TXn_RES_CODE_LANE_OFFSET_TX0);
0394     writel(0x11, edp->tx1 + TXn_RES_CODE_LANE_OFFSET_TX1);
0395 
0396     writel(0x10, edp->tx0 + TXn_TX_EMP_POST1_LVL);
0397     writel(0x10, edp->tx1 + TXn_TX_EMP_POST1_LVL);
0398     writel(0x1f, edp->tx0 + TXn_TX_DRV_LVL);
0399     writel(0x1f, edp->tx1 + TXn_TX_DRV_LVL);
0400 
0401     writel(0x4, edp->tx0 + TXn_HIGHZ_DRVR_EN);
0402     writel(0x3, edp->tx0 + TXn_TRANSCEIVER_BIAS_EN);
0403     writel(0x4, edp->tx1 + TXn_HIGHZ_DRVR_EN);
0404     writel(0x0, edp->tx1 + TXn_TRANSCEIVER_BIAS_EN);
0405     writel(0x3, edp->edp + DP_PHY_CFG_1);
0406 
0407     writel(0x18, edp->edp + DP_PHY_CFG);
0408     usleep_range(100, 1000);
0409 
0410     writel(0x19, edp->edp + DP_PHY_CFG);
0411 
0412     return readl_poll_timeout(edp->edp + DP_PHY_STATUS,
0413                   val, val & BIT(1), 500, 10000);
0414 }
0415 
0416 static int qcom_edp_phy_power_off(struct phy *phy)
0417 {
0418     const struct qcom_edp *edp = phy_get_drvdata(phy);
0419 
0420     writel(DP_PHY_PD_CTL_PSR_PWRDN, edp->edp + DP_PHY_PD_CTL);
0421 
0422     return 0;
0423 }
0424 
0425 static int qcom_edp_phy_exit(struct phy *phy)
0426 {
0427     struct qcom_edp *edp = phy_get_drvdata(phy);
0428 
0429     clk_bulk_disable_unprepare(ARRAY_SIZE(edp->clks), edp->clks);
0430     regulator_bulk_disable(ARRAY_SIZE(edp->supplies), edp->supplies);
0431 
0432     return 0;
0433 }
0434 
0435 static const struct phy_ops qcom_edp_ops = {
0436     .init       = qcom_edp_phy_init,
0437     .configure  = qcom_edp_phy_configure,
0438     .power_on   = qcom_edp_phy_power_on,
0439     .power_off  = qcom_edp_phy_power_off,
0440     .exit       = qcom_edp_phy_exit,
0441     .owner      = THIS_MODULE,
0442 };
0443 
0444 /*
0445  * Embedded Display Port PLL driver block diagram for branch clocks
0446  *
0447  *              +------------------------------+
0448  *              |        EDP_VCO_CLK           |
0449  *              |                              |
0450  *              |    +-------------------+     |
0451  *              |    |  (EDP PLL/VCO)    |     |
0452  *              |    +---------+---------+     |
0453  *              |              v               |
0454  *              |   +----------+-----------+   |
0455  *              |   | hsclk_divsel_clk_src |   |
0456  *              |   +----------+-----------+   |
0457  *              +------------------------------+
0458  *                              |
0459  *          +---------<---------v------------>----------+
0460  *          |                                           |
0461  * +--------v----------------+                          |
0462  * |   edp_phy_pll_link_clk  |                          |
0463  * |     link_clk            |                          |
0464  * +--------+----------------+                          |
0465  *          |                                           |
0466  *          |                                           |
0467  *          v                                           v
0468  * Input to DISPCC block                                |
0469  * for link clk, crypto clk                             |
0470  * and interface clock                                  |
0471  *                                                      |
0472  *                                                      |
0473  *      +--------<------------+-----------------+---<---+
0474  *      |                     |                 |
0475  * +----v---------+  +--------v-----+  +--------v------+
0476  * | vco_divided  |  | vco_divided  |  | vco_divided   |
0477  * |    _clk_src  |  |    _clk_src  |  |    _clk_src   |
0478  * |              |  |              |  |               |
0479  * |divsel_six    |  |  divsel_two  |  |  divsel_four  |
0480  * +-------+------+  +-----+--------+  +--------+------+
0481  *         |                 |                  |
0482  *         v---->----------v-------------<------v
0483  *                         |
0484  *              +----------+-----------------+
0485  *              |   edp_phy_pll_vco_div_clk  |
0486  *              +---------+------------------+
0487  *                        |
0488  *                        v
0489  *              Input to DISPCC block
0490  *              for EDP pixel clock
0491  *
0492  */
0493 static int qcom_edp_dp_pixel_clk_determine_rate(struct clk_hw *hw,
0494                         struct clk_rate_request *req)
0495 {
0496     switch (req->rate) {
0497     case 1620000000UL / 2:
0498     case 2700000000UL / 2:
0499     /* 5.4 and 8.1 GHz are same link rate as 2.7GHz, i.e. div 4 and div 6 */
0500         return 0;
0501 
0502     default:
0503         return -EINVAL;
0504     }
0505 }
0506 
0507 static unsigned long
0508 qcom_edp_dp_pixel_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
0509 {
0510     const struct qcom_edp *edp = container_of(hw, struct qcom_edp, dp_pixel_hw);
0511     const struct phy_configure_opts_dp *dp_opts = &edp->dp_opts;
0512 
0513     switch (dp_opts->link_rate) {
0514     case 1620:
0515         return 1620000000UL / 2;
0516     case 2700:
0517         return 2700000000UL / 2;
0518     case 5400:
0519         return 5400000000UL / 4;
0520     case 8100:
0521         return 8100000000UL / 6;
0522     default:
0523         return 0;
0524     }
0525 }
0526 
0527 static const struct clk_ops qcom_edp_dp_pixel_clk_ops = {
0528     .determine_rate = qcom_edp_dp_pixel_clk_determine_rate,
0529     .recalc_rate = qcom_edp_dp_pixel_clk_recalc_rate,
0530 };
0531 
0532 static int qcom_edp_dp_link_clk_determine_rate(struct clk_hw *hw,
0533                            struct clk_rate_request *req)
0534 {
0535     switch (req->rate) {
0536     case 162000000:
0537     case 270000000:
0538     case 540000000:
0539     case 810000000:
0540         return 0;
0541 
0542     default:
0543         return -EINVAL;
0544     }
0545 }
0546 
0547 static unsigned long
0548 qcom_edp_dp_link_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
0549 {
0550     const struct qcom_edp *edp = container_of(hw, struct qcom_edp, dp_link_hw);
0551     const struct phy_configure_opts_dp *dp_opts = &edp->dp_opts;
0552 
0553     switch (dp_opts->link_rate) {
0554     case 1620:
0555     case 2700:
0556     case 5400:
0557     case 8100:
0558         return dp_opts->link_rate * 100000;
0559 
0560     default:
0561         return 0;
0562     }
0563 }
0564 
0565 static const struct clk_ops qcom_edp_dp_link_clk_ops = {
0566     .determine_rate = qcom_edp_dp_link_clk_determine_rate,
0567     .recalc_rate = qcom_edp_dp_link_clk_recalc_rate,
0568 };
0569 
0570 static int qcom_edp_clks_register(struct qcom_edp *edp, struct device_node *np)
0571 {
0572     struct clk_hw_onecell_data *data;
0573     struct clk_init_data init = { };
0574     int ret;
0575 
0576     data = devm_kzalloc(edp->dev, struct_size(data, hws, 2), GFP_KERNEL);
0577     if (!data)
0578         return -ENOMEM;
0579 
0580     init.ops = &qcom_edp_dp_link_clk_ops;
0581     init.name = "edp_phy_pll_link_clk";
0582     edp->dp_link_hw.init = &init;
0583     ret = devm_clk_hw_register(edp->dev, &edp->dp_link_hw);
0584     if (ret)
0585         return ret;
0586 
0587     init.ops = &qcom_edp_dp_pixel_clk_ops;
0588     init.name = "edp_phy_pll_vco_div_clk";
0589     edp->dp_pixel_hw.init = &init;
0590     ret = devm_clk_hw_register(edp->dev, &edp->dp_pixel_hw);
0591     if (ret)
0592         return ret;
0593 
0594     data->hws[0] = &edp->dp_link_hw;
0595     data->hws[1] = &edp->dp_pixel_hw;
0596     data->num = 2;
0597 
0598     return devm_of_clk_add_hw_provider(edp->dev, of_clk_hw_onecell_get, data);
0599 }
0600 
0601 static int qcom_edp_phy_probe(struct platform_device *pdev)
0602 {
0603     struct phy_provider *phy_provider;
0604     struct device *dev = &pdev->dev;
0605     struct qcom_edp *edp;
0606     int ret;
0607 
0608     edp = devm_kzalloc(dev, sizeof(*edp), GFP_KERNEL);
0609     if (!edp)
0610         return -ENOMEM;
0611 
0612     edp->dev = dev;
0613 
0614     edp->edp = devm_platform_ioremap_resource(pdev, 0);
0615     if (IS_ERR(edp->edp))
0616         return PTR_ERR(edp->edp);
0617 
0618     edp->tx0 = devm_platform_ioremap_resource(pdev, 1);
0619     if (IS_ERR(edp->tx0))
0620         return PTR_ERR(edp->tx0);
0621 
0622     edp->tx1 = devm_platform_ioremap_resource(pdev, 2);
0623     if (IS_ERR(edp->tx1))
0624         return PTR_ERR(edp->tx1);
0625 
0626     edp->pll = devm_platform_ioremap_resource(pdev, 3);
0627     if (IS_ERR(edp->pll))
0628         return PTR_ERR(edp->pll);
0629 
0630     edp->clks[0].id = "aux";
0631     edp->clks[1].id = "cfg_ahb";
0632     ret = devm_clk_bulk_get(dev, ARRAY_SIZE(edp->clks), edp->clks);
0633     if (ret)
0634         return ret;
0635 
0636     edp->supplies[0].supply = "vdda-phy";
0637     edp->supplies[1].supply = "vdda-pll";
0638     ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(edp->supplies), edp->supplies);
0639     if (ret)
0640         return ret;
0641 
0642     ret = regulator_set_load(edp->supplies[0].consumer, 21800); /* 1.2 V vdda-phy */
0643     if (ret) {
0644         dev_err(dev, "failed to set load at %s\n", edp->supplies[0].supply);
0645         return ret;
0646     }
0647 
0648     ret = regulator_set_load(edp->supplies[1].consumer, 36000); /* 0.9 V vdda-pll */
0649     if (ret) {
0650         dev_err(dev, "failed to set load at %s\n", edp->supplies[1].supply);
0651         return ret;
0652     }
0653 
0654     ret = qcom_edp_clks_register(edp, pdev->dev.of_node);
0655     if (ret)
0656         return ret;
0657 
0658     edp->phy = devm_phy_create(dev, pdev->dev.of_node, &qcom_edp_ops);
0659     if (IS_ERR(edp->phy)) {
0660         dev_err(dev, "failed to register phy\n");
0661         return PTR_ERR(edp->phy);
0662     }
0663 
0664     phy_set_drvdata(edp->phy, edp);
0665 
0666     phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
0667     return PTR_ERR_OR_ZERO(phy_provider);
0668 }
0669 
0670 static const struct of_device_id qcom_edp_phy_match_table[] = {
0671     { .compatible = "qcom,sc7280-edp-phy" },
0672     { .compatible = "qcom,sc8180x-edp-phy" },
0673     { }
0674 };
0675 MODULE_DEVICE_TABLE(of, qcom_edp_phy_match_table);
0676 
0677 static struct platform_driver qcom_edp_phy_driver = {
0678     .probe      = qcom_edp_phy_probe,
0679     .driver = {
0680         .name   = "qcom-edp-phy",
0681         .of_match_table = qcom_edp_phy_match_table,
0682     },
0683 };
0684 
0685 module_platform_driver(qcom_edp_phy_driver);
0686 
0687 MODULE_AUTHOR("Bjorn Andersson <bjorn.andersson@linaro.org>");
0688 MODULE_DESCRIPTION("Qualcomm eDP QMP PHY driver");
0689 MODULE_LICENSE("GPL v2");