linux/drivers/phy/qualcomm/phy-qcom-edp.c
<<
>>
Prefs
   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/of_device.h>
  17#include <linux/of_address.h>
  18#include <linux/phy/phy.h>
  19#include <linux/platform_device.h>
  20#include <linux/regulator/consumer.h>
  21#include <linux/reset.h>
  22#include <linux/slab.h>
  23
  24#include <dt-bindings/phy/phy.h>
  25
  26#include "phy-qcom-qmp.h"
  27
  28/* EDP_PHY registers */
  29#define DP_PHY_CFG                              0x0010
  30#define DP_PHY_CFG_1                            0x0014
  31#define DP_PHY_PD_CTL                           0x001c
  32#define DP_PHY_MODE                             0x0020
  33
  34#define DP_PHY_AUX_CFG0                         0x0024
  35#define DP_PHY_AUX_CFG1                         0x0028
  36#define DP_PHY_AUX_CFG2                         0x002C
  37#define DP_PHY_AUX_CFG3                         0x0030
  38#define DP_PHY_AUX_CFG4                         0x0034
  39#define DP_PHY_AUX_CFG5                         0x0038
  40#define DP_PHY_AUX_CFG6                         0x003C
  41#define DP_PHY_AUX_CFG7                         0x0040
  42#define DP_PHY_AUX_CFG8                         0x0044
  43#define DP_PHY_AUX_CFG9                         0x0048
  44
  45#define DP_PHY_AUX_INTERRUPT_MASK               0x0058
  46
  47#define DP_PHY_VCO_DIV                          0x0074
  48#define DP_PHY_TX0_TX1_LANE_CTL                 0x007c
  49#define DP_PHY_TX2_TX3_LANE_CTL                 0x00a0
  50
  51#define DP_PHY_STATUS                           0x00e0
  52
  53/* LANE_TXn registers */
  54#define TXn_CLKBUF_ENABLE                       0x0000
  55#define TXn_TX_EMP_POST1_LVL                    0x0004
  56
  57#define TXn_TX_DRV_LVL                          0x0014
  58#define TXn_TX_DRV_LVL_OFFSET                   0x0018
  59#define TXn_RESET_TSYNC_EN                      0x001c
  60#define TXn_LDO_CONFIG                          0x0084
  61#define TXn_TX_BAND                             0x0028
  62
  63#define TXn_RES_CODE_LANE_OFFSET_TX0            0x0044
  64#define TXn_RES_CODE_LANE_OFFSET_TX1            0x0048
  65
  66#define TXn_TRANSCEIVER_BIAS_EN                 0x0054
  67#define TXn_HIGHZ_DRVR_EN                       0x0058
  68#define TXn_TX_POL_INV                          0x005c
  69#define TXn_LANE_MODE_1                         0x0064
  70
  71#define TXn_TRAN_DRVR_EMP_EN                    0x0078
  72
  73struct qcom_edp {
  74        struct device *dev;
  75
  76        struct phy *phy;
  77
  78        void __iomem *edp;
  79        void __iomem *tx0;
  80        void __iomem *tx1;
  81        void __iomem *pll;
  82
  83        struct clk_hw dp_link_hw;
  84        struct clk_hw dp_pixel_hw;
  85
  86        struct phy_configure_opts_dp dp_opts;
  87
  88        struct clk_bulk_data clks[2];
  89        struct regulator_bulk_data supplies[2];
  90};
  91
  92static int qcom_edp_phy_init(struct phy *phy)
  93{
  94        struct qcom_edp *edp = phy_get_drvdata(phy);
  95        int ret;
  96
  97        ret = regulator_bulk_enable(ARRAY_SIZE(edp->supplies), edp->supplies);
  98        if (ret)
  99                return ret;
 100
 101        ret = clk_bulk_prepare_enable(ARRAY_SIZE(edp->clks), edp->clks);
 102        if (ret)
 103                goto out_disable_supplies;
 104
 105        writel(DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN |
 106               DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN,
 107               edp->edp + DP_PHY_PD_CTL);
 108
 109        /* Turn on BIAS current for PHY/PLL */
 110        writel(0x17, edp->pll + QSERDES_V4_COM_BIAS_EN_CLKBUFLR_EN);
 111
 112        writel(DP_PHY_PD_CTL_PSR_PWRDN, edp->edp + DP_PHY_PD_CTL);
 113        msleep(20);
 114
 115        writel(DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN |
 116               DP_PHY_PD_CTL_LANE_0_1_PWRDN | DP_PHY_PD_CTL_LANE_2_3_PWRDN |
 117               DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN,
 118               edp->edp + DP_PHY_PD_CTL);
 119
 120        writel(0x00, edp->edp + DP_PHY_AUX_CFG0);
 121        writel(0x13, edp->edp + DP_PHY_AUX_CFG1);
 122        writel(0x24, edp->edp + DP_PHY_AUX_CFG2);
 123        writel(0x00, edp->edp + DP_PHY_AUX_CFG3);
 124        writel(0x0a, edp->edp + DP_PHY_AUX_CFG4);
 125        writel(0x26, edp->edp + DP_PHY_AUX_CFG5);
 126        writel(0x0a, edp->edp + DP_PHY_AUX_CFG6);
 127        writel(0x03, edp->edp + DP_PHY_AUX_CFG7);
 128        writel(0x37, edp->edp + DP_PHY_AUX_CFG8);
 129        writel(0x03, edp->edp + DP_PHY_AUX_CFG9);
 130
 131        writel(PHY_AUX_STOP_ERR_MASK | PHY_AUX_DEC_ERR_MASK |
 132               PHY_AUX_SYNC_ERR_MASK | PHY_AUX_ALIGN_ERR_MASK |
 133               PHY_AUX_REQ_ERR_MASK, edp->edp + DP_PHY_AUX_INTERRUPT_MASK);
 134
 135        msleep(20);
 136
 137        return 0;
 138
 139out_disable_supplies:
 140        regulator_bulk_disable(ARRAY_SIZE(edp->supplies), edp->supplies);
 141
 142        return ret;
 143}
 144
 145static int qcom_edp_phy_configure(struct phy *phy, union phy_configure_opts *opts)
 146{
 147        const struct phy_configure_opts_dp *dp_opts = &opts->dp;
 148        struct qcom_edp *edp = phy_get_drvdata(phy);
 149
 150        memcpy(&edp->dp_opts, dp_opts, sizeof(*dp_opts));
 151
 152        return 0;
 153}
 154
 155static int qcom_edp_configure_ssc(const struct qcom_edp *edp)
 156{
 157        const struct phy_configure_opts_dp *dp_opts = &edp->dp_opts;
 158        u32 step1;
 159        u32 step2;
 160
 161        switch (dp_opts->link_rate) {
 162        case 1620:
 163        case 2700:
 164        case 8100:
 165                step1 = 0x45;
 166                step2 = 0x06;
 167                break;
 168
 169        case 5400:
 170                step1 = 0x5c;
 171                step2 = 0x08;
 172                break;
 173
 174        default:
 175                /* Other link rates aren't supported */
 176                return -EINVAL;
 177        }
 178
 179        writel(0x01, edp->pll + QSERDES_V4_COM_SSC_EN_CENTER);
 180        writel(0x00, edp->pll + QSERDES_V4_COM_SSC_ADJ_PER1);
 181        writel(0x36, edp->pll + QSERDES_V4_COM_SSC_PER1);
 182        writel(0x01, edp->pll + QSERDES_V4_COM_SSC_PER2);
 183        writel(step1, edp->pll + QSERDES_V4_COM_SSC_STEP_SIZE1_MODE0);
 184        writel(step2, edp->pll + QSERDES_V4_COM_SSC_STEP_SIZE2_MODE0);
 185
 186        return 0;
 187}
 188
 189static int qcom_edp_configure_pll(const struct qcom_edp *edp)
 190{
 191        const struct phy_configure_opts_dp *dp_opts = &edp->dp_opts;
 192        u32 div_frac_start2_mode0;
 193        u32 div_frac_start3_mode0;
 194        u32 dec_start_mode0;
 195        u32 lock_cmp1_mode0;
 196        u32 lock_cmp2_mode0;
 197        u32 hsclk_sel;
 198
 199        switch (dp_opts->link_rate) {
 200        case 1620:
 201                hsclk_sel = 0x5;
 202                dec_start_mode0 = 0x69;
 203                div_frac_start2_mode0 = 0x80;
 204                div_frac_start3_mode0 = 0x07;
 205                lock_cmp1_mode0 = 0x6f;
 206                lock_cmp2_mode0 = 0x08;
 207                break;
 208
 209        case 2700:
 210                hsclk_sel = 0x3;
 211                dec_start_mode0 = 0x69;
 212                div_frac_start2_mode0 = 0x80;
 213                div_frac_start3_mode0 = 0x07;
 214                lock_cmp1_mode0 = 0x0f;
 215                lock_cmp2_mode0 = 0x0e;
 216                break;
 217
 218        case 5400:
 219                hsclk_sel = 0x1;
 220                dec_start_mode0 = 0x8c;
 221                div_frac_start2_mode0 = 0x00;
 222                div_frac_start3_mode0 = 0x0a;
 223                lock_cmp1_mode0 = 0x1f;
 224                lock_cmp2_mode0 = 0x1c;
 225                break;
 226
 227        case 8100:
 228                hsclk_sel = 0x0;
 229                dec_start_mode0 = 0x69;
 230                div_frac_start2_mode0 = 0x80;
 231                div_frac_start3_mode0 = 0x07;
 232                lock_cmp1_mode0 = 0x2f;
 233                lock_cmp2_mode0 = 0x2a;
 234                break;
 235
 236        default:
 237                /* Other link rates aren't supported */
 238                return -EINVAL;
 239        }
 240
 241        writel(0x01, edp->pll + QSERDES_V4_COM_SVS_MODE_CLK_SEL);
 242        writel(0x0b, edp->pll + QSERDES_V4_COM_SYSCLK_EN_SEL);
 243        writel(0x02, edp->pll + QSERDES_V4_COM_SYS_CLK_CTRL);
 244        writel(0x0c, edp->pll + QSERDES_V4_COM_CLK_ENABLE1);
 245        writel(0x06, edp->pll + QSERDES_V4_COM_SYSCLK_BUF_ENABLE);
 246        writel(0x30, edp->pll + QSERDES_V4_COM_CLK_SELECT);
 247        writel(hsclk_sel, edp->pll + QSERDES_V4_COM_HSCLK_SEL);
 248        writel(0x0f, edp->pll + QSERDES_V4_COM_PLL_IVCO);
 249        writel(0x08, edp->pll + QSERDES_V4_COM_LOCK_CMP_EN);
 250        writel(0x36, edp->pll + QSERDES_V4_COM_PLL_CCTRL_MODE0);
 251        writel(0x16, edp->pll + QSERDES_V4_COM_PLL_RCTRL_MODE0);
 252        writel(0x06, edp->pll + QSERDES_V4_COM_CP_CTRL_MODE0);
 253        writel(dec_start_mode0, edp->pll + QSERDES_V4_COM_DEC_START_MODE0);
 254        writel(0x00, edp->pll + QSERDES_V4_COM_DIV_FRAC_START1_MODE0);
 255        writel(div_frac_start2_mode0, edp->pll + QSERDES_V4_COM_DIV_FRAC_START2_MODE0);
 256        writel(div_frac_start3_mode0, edp->pll + QSERDES_V4_COM_DIV_FRAC_START3_MODE0);
 257        writel(0x02, edp->pll + QSERDES_V4_COM_CMN_CONFIG);
 258        writel(0x3f, edp->pll + QSERDES_V4_COM_INTEGLOOP_GAIN0_MODE0);
 259        writel(0x00, edp->pll + QSERDES_V4_COM_INTEGLOOP_GAIN1_MODE0);
 260        writel(0x00, edp->pll + QSERDES_V4_COM_VCO_TUNE_MAP);
 261        writel(lock_cmp1_mode0, edp->pll + QSERDES_V4_COM_LOCK_CMP1_MODE0);
 262        writel(lock_cmp2_mode0, edp->pll + QSERDES_V4_COM_LOCK_CMP2_MODE0);
 263
 264        writel(0x0a, edp->pll + QSERDES_V4_COM_BG_TIMER);
 265        writel(0x14, edp->pll + QSERDES_V4_COM_CORECLK_DIV_MODE0);
 266        writel(0x00, edp->pll + QSERDES_V4_COM_VCO_TUNE_CTRL);
 267        writel(0x17, edp->pll + QSERDES_V4_COM_BIAS_EN_CLKBUFLR_EN);
 268        writel(0x0f, edp->pll + QSERDES_V4_COM_CORE_CLK_EN);
 269        writel(0xa0, edp->pll + QSERDES_V4_COM_VCO_TUNE1_MODE0);
 270        writel(0x03, edp->pll + QSERDES_V4_COM_VCO_TUNE2_MODE0);
 271
 272        return 0;
 273}
 274
 275static int qcom_edp_set_vco_div(const struct qcom_edp *edp)
 276{
 277        const struct phy_configure_opts_dp *dp_opts = &edp->dp_opts;
 278        unsigned long pixel_freq;
 279        u32 vco_div;
 280
 281        switch (dp_opts->link_rate) {
 282        case 1620:
 283                vco_div = 0x1;
 284                pixel_freq = 1620000000UL / 2;
 285                break;
 286
 287        case 2700:
 288                vco_div = 0x1;
 289                pixel_freq = 2700000000UL / 2;
 290                break;
 291
 292        case 5400:
 293                vco_div = 0x2;
 294                pixel_freq = 5400000000UL / 4;
 295                break;
 296
 297        case 8100:
 298                vco_div = 0x0;
 299                pixel_freq = 8100000000UL / 6;
 300                break;
 301
 302        default:
 303                /* Other link rates aren't supported */
 304                return -EINVAL;
 305        }
 306
 307        writel(vco_div, edp->edp + DP_PHY_VCO_DIV);
 308
 309        clk_set_rate(edp->dp_link_hw.clk, dp_opts->link_rate * 100000);
 310        clk_set_rate(edp->dp_pixel_hw.clk, pixel_freq);
 311
 312        return 0;
 313}
 314
 315static int qcom_edp_phy_power_on(struct phy *phy)
 316{
 317        const struct qcom_edp *edp = phy_get_drvdata(phy);
 318        int timeout;
 319        int ret;
 320        u32 val;
 321
 322        writel(DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN |
 323               DP_PHY_PD_CTL_LANE_0_1_PWRDN | DP_PHY_PD_CTL_LANE_2_3_PWRDN |
 324               DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN,
 325               edp->edp + DP_PHY_PD_CTL);
 326        writel(0xfc, edp->edp + DP_PHY_MODE);
 327
 328        timeout = readl_poll_timeout(edp->pll + QSERDES_V4_COM_CMN_STATUS,
 329                                     val, val & BIT(7), 5, 200);
 330        if (timeout)
 331                return timeout;
 332
 333        writel(0x01, edp->tx0 + TXn_LDO_CONFIG);
 334        writel(0x01, edp->tx1 + TXn_LDO_CONFIG);
 335        writel(0x00, edp->tx0 + TXn_LANE_MODE_1);
 336        writel(0x00, edp->tx1 + TXn_LANE_MODE_1);
 337
 338        ret = qcom_edp_configure_ssc(edp);
 339        if (ret)
 340                return ret;
 341
 342        ret = qcom_edp_configure_pll(edp);
 343        if (ret)
 344                return ret;
 345
 346        /* TX Lane configuration */
 347        writel(0x05, edp->edp + DP_PHY_TX0_TX1_LANE_CTL);
 348        writel(0x05, edp->edp + DP_PHY_TX2_TX3_LANE_CTL);
 349
 350        /* TX-0 register configuration */
 351        writel(0x03, edp->tx0 + TXn_TRANSCEIVER_BIAS_EN);
 352        writel(0x0f, edp->tx0 + TXn_CLKBUF_ENABLE);
 353        writel(0x03, edp->tx0 + TXn_RESET_TSYNC_EN);
 354        writel(0x01, edp->tx0 + TXn_TRAN_DRVR_EMP_EN);
 355        writel(0x04, edp->tx0 + TXn_TX_BAND);
 356
 357        /* TX-1 register configuration */
 358        writel(0x03, edp->tx1 + TXn_TRANSCEIVER_BIAS_EN);
 359        writel(0x0f, edp->tx1 + TXn_CLKBUF_ENABLE);
 360        writel(0x03, edp->tx1 + TXn_RESET_TSYNC_EN);
 361        writel(0x01, edp->tx1 + TXn_TRAN_DRVR_EMP_EN);
 362        writel(0x04, edp->tx1 + TXn_TX_BAND);
 363
 364        ret = qcom_edp_set_vco_div(edp);
 365        if (ret)
 366                return ret;
 367
 368        writel(0x01, edp->edp + DP_PHY_CFG);
 369        writel(0x05, edp->edp + DP_PHY_CFG);
 370        writel(0x01, edp->edp + DP_PHY_CFG);
 371        writel(0x09, edp->edp + DP_PHY_CFG);
 372
 373        writel(0x20, edp->pll + QSERDES_V4_COM_RESETSM_CNTRL);
 374
 375        timeout = readl_poll_timeout(edp->pll + QSERDES_V4_COM_C_READY_STATUS,
 376                                     val, val & BIT(0), 500, 10000);
 377        if (timeout)
 378                return timeout;
 379
 380        writel(0x19, edp->edp + DP_PHY_CFG);
 381        writel(0x1f, edp->tx0 + TXn_HIGHZ_DRVR_EN);
 382        writel(0x04, edp->tx0 + TXn_HIGHZ_DRVR_EN);
 383        writel(0x00, edp->tx0 + TXn_TX_POL_INV);
 384        writel(0x1f, edp->tx1 + TXn_HIGHZ_DRVR_EN);
 385        writel(0x04, edp->tx1 + TXn_HIGHZ_DRVR_EN);
 386        writel(0x00, edp->tx1 + TXn_TX_POL_INV);
 387        writel(0x10, edp->tx0 + TXn_TX_DRV_LVL_OFFSET);
 388        writel(0x10, edp->tx1 + TXn_TX_DRV_LVL_OFFSET);
 389        writel(0x11, edp->tx0 + TXn_RES_CODE_LANE_OFFSET_TX0);
 390        writel(0x11, edp->tx0 + TXn_RES_CODE_LANE_OFFSET_TX1);
 391        writel(0x11, edp->tx1 + TXn_RES_CODE_LANE_OFFSET_TX0);
 392        writel(0x11, edp->tx1 + TXn_RES_CODE_LANE_OFFSET_TX1);
 393
 394        writel(0x10, edp->tx0 + TXn_TX_EMP_POST1_LVL);
 395        writel(0x10, edp->tx1 + TXn_TX_EMP_POST1_LVL);
 396        writel(0x1f, edp->tx0 + TXn_TX_DRV_LVL);
 397        writel(0x1f, edp->tx1 + TXn_TX_DRV_LVL);
 398
 399        writel(0x4, edp->tx0 + TXn_HIGHZ_DRVR_EN);
 400        writel(0x3, edp->tx0 + TXn_TRANSCEIVER_BIAS_EN);
 401        writel(0x4, edp->tx1 + TXn_HIGHZ_DRVR_EN);
 402        writel(0x0, edp->tx1 + TXn_TRANSCEIVER_BIAS_EN);
 403        writel(0x3, edp->edp + DP_PHY_CFG_1);
 404
 405        writel(0x18, edp->edp + DP_PHY_CFG);
 406        usleep_range(100, 1000);
 407
 408        writel(0x19, edp->edp + DP_PHY_CFG);
 409
 410        return readl_poll_timeout(edp->edp + DP_PHY_STATUS,
 411                                  val, val & BIT(1), 500, 10000);
 412}
 413
 414static int qcom_edp_phy_power_off(struct phy *phy)
 415{
 416        const struct qcom_edp *edp = phy_get_drvdata(phy);
 417
 418        writel(DP_PHY_PD_CTL_PSR_PWRDN, edp->edp + DP_PHY_PD_CTL);
 419
 420        return 0;
 421}
 422
 423static int qcom_edp_phy_exit(struct phy *phy)
 424{
 425        struct qcom_edp *edp = phy_get_drvdata(phy);
 426
 427        clk_bulk_disable_unprepare(ARRAY_SIZE(edp->clks), edp->clks);
 428        regulator_bulk_disable(ARRAY_SIZE(edp->supplies), edp->supplies);
 429
 430        return 0;
 431}
 432
 433static const struct phy_ops qcom_edp_ops = {
 434        .init           = qcom_edp_phy_init,
 435        .configure      = qcom_edp_phy_configure,
 436        .power_on       = qcom_edp_phy_power_on,
 437        .power_off      = qcom_edp_phy_power_off,
 438        .exit           = qcom_edp_phy_exit,
 439        .owner          = THIS_MODULE,
 440};
 441
 442/*
 443 * Embedded Display Port PLL driver block diagram for branch clocks
 444 *
 445 *              +------------------------------+
 446 *              |        EDP_VCO_CLK           |
 447 *              |                              |
 448 *              |    +-------------------+     |
 449 *              |    |  (EDP PLL/VCO)    |     |
 450 *              |    +---------+---------+     |
 451 *              |              v               |
 452 *              |   +----------+-----------+   |
 453 *              |   | hsclk_divsel_clk_src |   |
 454 *              |   +----------+-----------+   |
 455 *              +------------------------------+
 456 *                              |
 457 *          +---------<---------v------------>----------+
 458 *          |                                           |
 459 * +--------v----------------+                          |
 460 * |   edp_phy_pll_link_clk  |                          |
 461 * |     link_clk            |                          |
 462 * +--------+----------------+                          |
 463 *          |                                           |
 464 *          |                                           |
 465 *          v                                           v
 466 * Input to DISPCC block                                |
 467 * for link clk, crypto clk                             |
 468 * and interface clock                                  |
 469 *                                                      |
 470 *                                                      |
 471 *      +--------<------------+-----------------+---<---+
 472 *      |                     |                 |
 473 * +----v---------+  +--------v-----+  +--------v------+
 474 * | vco_divided  |  | vco_divided  |  | vco_divided   |
 475 * |    _clk_src  |  |    _clk_src  |  |    _clk_src   |
 476 * |              |  |              |  |               |
 477 * |divsel_six    |  |  divsel_two  |  |  divsel_four  |
 478 * +-------+------+  +-----+--------+  +--------+------+
 479 *         |                 |                  |
 480 *         v---->----------v-------------<------v
 481 *                         |
 482 *              +----------+-----------------+
 483 *              |   edp_phy_pll_vco_div_clk  |
 484 *              +---------+------------------+
 485 *                        |
 486 *                        v
 487 *              Input to DISPCC block
 488 *              for EDP pixel clock
 489 *
 490 */
 491static int qcom_edp_dp_pixel_clk_determine_rate(struct clk_hw *hw,
 492                                                struct clk_rate_request *req)
 493{
 494        switch (req->rate) {
 495        case 1620000000UL / 2:
 496        case 2700000000UL / 2:
 497        /* 5.4 and 8.1 GHz are same link rate as 2.7GHz, i.e. div 4 and div 6 */
 498                return 0;
 499
 500        default:
 501                return -EINVAL;
 502        }
 503}
 504
 505static unsigned long
 506qcom_edp_dp_pixel_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
 507{
 508        const struct qcom_edp *edp = container_of(hw, struct qcom_edp, dp_pixel_hw);
 509        const struct phy_configure_opts_dp *dp_opts = &edp->dp_opts;
 510
 511        switch (dp_opts->link_rate) {
 512        case 1620:
 513                return 1620000000UL / 2;
 514        case 2700:
 515                return 2700000000UL / 2;
 516        case 5400:
 517                return 5400000000UL / 4;
 518        case 8100:
 519                return 8100000000UL / 6;
 520        default:
 521                return 0;
 522        }
 523}
 524
 525static const struct clk_ops qcom_edp_dp_pixel_clk_ops = {
 526        .determine_rate = qcom_edp_dp_pixel_clk_determine_rate,
 527        .recalc_rate = qcom_edp_dp_pixel_clk_recalc_rate,
 528};
 529
 530static int qcom_edp_dp_link_clk_determine_rate(struct clk_hw *hw,
 531                                               struct clk_rate_request *req)
 532{
 533        switch (req->rate) {
 534        case 162000000:
 535        case 270000000:
 536        case 540000000:
 537        case 810000000:
 538                return 0;
 539
 540        default:
 541                return -EINVAL;
 542        }
 543}
 544
 545static unsigned long
 546qcom_edp_dp_link_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
 547{
 548        const struct qcom_edp *edp = container_of(hw, struct qcom_edp, dp_link_hw);
 549        const struct phy_configure_opts_dp *dp_opts = &edp->dp_opts;
 550
 551        switch (dp_opts->link_rate) {
 552        case 1620:
 553        case 2700:
 554        case 5400:
 555        case 8100:
 556                return dp_opts->link_rate * 100000;
 557
 558        default:
 559                return 0;
 560        }
 561}
 562
 563static const struct clk_ops qcom_edp_dp_link_clk_ops = {
 564        .determine_rate = qcom_edp_dp_link_clk_determine_rate,
 565        .recalc_rate = qcom_edp_dp_link_clk_recalc_rate,
 566};
 567
 568static int qcom_edp_clks_register(struct qcom_edp *edp, struct device_node *np)
 569{
 570        struct clk_hw_onecell_data *data;
 571        struct clk_init_data init = { };
 572        int ret;
 573
 574        data = devm_kzalloc(edp->dev, struct_size(data, hws, 2), GFP_KERNEL);
 575        if (!data)
 576                return -ENOMEM;
 577
 578        init.ops = &qcom_edp_dp_link_clk_ops;
 579        init.name = "edp_phy_pll_link_clk";
 580        edp->dp_link_hw.init = &init;
 581        ret = devm_clk_hw_register(edp->dev, &edp->dp_link_hw);
 582        if (ret)
 583                return ret;
 584
 585        init.ops = &qcom_edp_dp_pixel_clk_ops;
 586        init.name = "edp_phy_pll_vco_div_clk";
 587        edp->dp_pixel_hw.init = &init;
 588        ret = devm_clk_hw_register(edp->dev, &edp->dp_pixel_hw);
 589        if (ret)
 590                return ret;
 591
 592        data->hws[0] = &edp->dp_link_hw;
 593        data->hws[1] = &edp->dp_pixel_hw;
 594        data->num = 2;
 595
 596        return devm_of_clk_add_hw_provider(edp->dev, of_clk_hw_onecell_get, data);
 597}
 598
 599static int qcom_edp_phy_probe(struct platform_device *pdev)
 600{
 601        struct phy_provider *phy_provider;
 602        struct device *dev = &pdev->dev;
 603        struct qcom_edp *edp;
 604        int ret;
 605
 606        edp = devm_kzalloc(dev, sizeof(*edp), GFP_KERNEL);
 607        if (!edp)
 608                return -ENOMEM;
 609
 610        edp->dev = dev;
 611
 612        edp->edp = devm_platform_ioremap_resource(pdev, 0);
 613        if (IS_ERR(edp->edp))
 614                return PTR_ERR(edp->edp);
 615
 616        edp->tx0 = devm_platform_ioremap_resource(pdev, 1);
 617        if (IS_ERR(edp->tx0))
 618                return PTR_ERR(edp->tx0);
 619
 620        edp->tx1 = devm_platform_ioremap_resource(pdev, 2);
 621        if (IS_ERR(edp->tx1))
 622                return PTR_ERR(edp->tx1);
 623
 624        edp->pll = devm_platform_ioremap_resource(pdev, 3);
 625        if (IS_ERR(edp->pll))
 626                return PTR_ERR(edp->pll);
 627
 628        edp->clks[0].id = "aux";
 629        edp->clks[1].id = "cfg_ahb";
 630        ret = devm_clk_bulk_get(dev, ARRAY_SIZE(edp->clks), edp->clks);
 631        if (ret)
 632                return ret;
 633
 634        edp->supplies[0].supply = "vdda-phy";
 635        edp->supplies[1].supply = "vdda-pll";
 636        ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(edp->supplies), edp->supplies);
 637        if (ret)
 638                return ret;
 639
 640        ret = qcom_edp_clks_register(edp, pdev->dev.of_node);
 641        if (ret)
 642                return ret;
 643
 644        edp->phy = devm_phy_create(dev, pdev->dev.of_node, &qcom_edp_ops);
 645        if (IS_ERR(edp->phy)) {
 646                dev_err(dev, "failed to register phy\n");
 647                return PTR_ERR(edp->phy);
 648        }
 649
 650        phy_set_drvdata(edp->phy, edp);
 651
 652        phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
 653        return PTR_ERR_OR_ZERO(phy_provider);
 654}
 655
 656static const struct of_device_id qcom_edp_phy_match_table[] = {
 657        { .compatible = "qcom,sc8180x-edp-phy" },
 658        { }
 659};
 660MODULE_DEVICE_TABLE(of, qcom_edp_phy_match_table);
 661
 662static struct platform_driver qcom_edp_phy_driver = {
 663        .probe          = qcom_edp_phy_probe,
 664        .driver = {
 665                .name   = "qcom-edp-phy",
 666                .of_match_table = qcom_edp_phy_match_table,
 667        },
 668};
 669
 670module_platform_driver(qcom_edp_phy_driver);
 671
 672MODULE_AUTHOR("Bjorn Andersson <bjorn.andersson@linaro.org>");
 673MODULE_DESCRIPTION("Qualcomm eDP QMP PHY driver");
 674MODULE_LICENSE("GPL v2");
 675