linux/drivers/phy/cadence/phy-cadence-dp.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Cadence MHDP DisplayPort SD0801 PHY driver.
   4 *
   5 * Copyright 2018 Cadence Design Systems, Inc.
   6 *
   7 */
   8
   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_address.h>
  17#include <linux/of_device.h>
  18#include <linux/phy/phy.h>
  19#include <linux/platform_device.h>
  20
  21#define DEFAULT_NUM_LANES       2
  22#define MAX_NUM_LANES           4
  23#define DEFAULT_MAX_BIT_RATE    8100 /* in Mbps */
  24
  25#define POLL_TIMEOUT_US         2000
  26#define LANE_MASK               0x7
  27
  28/*
  29 * register offsets from DPTX PHY register block base (i.e MHDP
  30 * register base + 0x30a00)
  31 */
  32#define PHY_AUX_CONFIG                  0x00
  33#define PHY_AUX_CTRL                    0x04
  34#define PHY_RESET                       0x20
  35#define PHY_PMA_XCVR_PLLCLK_EN          0x24
  36#define PHY_PMA_XCVR_PLLCLK_EN_ACK      0x28
  37#define PHY_PMA_XCVR_POWER_STATE_REQ    0x2c
  38#define PHY_POWER_STATE_LN_0    0x0000
  39#define PHY_POWER_STATE_LN_1    0x0008
  40#define PHY_POWER_STATE_LN_2    0x0010
  41#define PHY_POWER_STATE_LN_3    0x0018
  42#define PHY_PMA_XCVR_POWER_STATE_ACK    0x30
  43#define PHY_PMA_CMN_READY               0x34
  44#define PHY_PMA_XCVR_TX_VMARGIN         0x38
  45#define PHY_PMA_XCVR_TX_DEEMPH          0x3c
  46
  47/*
  48 * register offsets from SD0801 PHY register block base (i.e MHDP
  49 * register base + 0x500000)
  50 */
  51#define CMN_SSM_BANDGAP_TMR             0x00084
  52#define CMN_SSM_BIAS_TMR                0x00088
  53#define CMN_PLLSM0_PLLPRE_TMR           0x000a8
  54#define CMN_PLLSM0_PLLLOCK_TMR          0x000b0
  55#define CMN_PLLSM1_PLLPRE_TMR           0x000c8
  56#define CMN_PLLSM1_PLLLOCK_TMR          0x000d0
  57#define CMN_BGCAL_INIT_TMR              0x00190
  58#define CMN_BGCAL_ITER_TMR              0x00194
  59#define CMN_IBCAL_INIT_TMR              0x001d0
  60#define CMN_PLL0_VCOCAL_INIT_TMR        0x00210
  61#define CMN_PLL0_VCOCAL_ITER_TMR        0x00214
  62#define CMN_PLL0_VCOCAL_REFTIM_START    0x00218
  63#define CMN_PLL0_VCOCAL_PLLCNT_START    0x00220
  64#define CMN_PLL0_INTDIV_M0              0x00240
  65#define CMN_PLL0_FRACDIVL_M0            0x00244
  66#define CMN_PLL0_FRACDIVH_M0            0x00248
  67#define CMN_PLL0_HIGH_THR_M0            0x0024c
  68#define CMN_PLL0_DSM_DIAG_M0            0x00250
  69#define CMN_PLL0_LOCK_PLLCNT_START      0x00278
  70#define CMN_PLL1_VCOCAL_INIT_TMR        0x00310
  71#define CMN_PLL1_VCOCAL_ITER_TMR        0x00314
  72#define CMN_PLL1_DSM_DIAG_M0            0x00350
  73#define CMN_TXPUCAL_INIT_TMR            0x00410
  74#define CMN_TXPUCAL_ITER_TMR            0x00414
  75#define CMN_TXPDCAL_INIT_TMR            0x00430
  76#define CMN_TXPDCAL_ITER_TMR            0x00434
  77#define CMN_RXCAL_INIT_TMR              0x00450
  78#define CMN_RXCAL_ITER_TMR              0x00454
  79#define CMN_SD_CAL_INIT_TMR             0x00490
  80#define CMN_SD_CAL_ITER_TMR             0x00494
  81#define CMN_SD_CAL_REFTIM_START         0x00498
  82#define CMN_SD_CAL_PLLCNT_START         0x004a0
  83#define CMN_PDIAG_PLL0_CTRL_M0          0x00680
  84#define CMN_PDIAG_PLL0_CLK_SEL_M0       0x00684
  85#define CMN_PDIAG_PLL0_CP_PADJ_M0       0x00690
  86#define CMN_PDIAG_PLL0_CP_IADJ_M0       0x00694
  87#define CMN_PDIAG_PLL0_FILT_PADJ_M0     0x00698
  88#define CMN_PDIAG_PLL0_CP_PADJ_M1       0x006d0
  89#define CMN_PDIAG_PLL0_CP_IADJ_M1       0x006d4
  90#define CMN_PDIAG_PLL1_CLK_SEL_M0       0x00704
  91#define XCVR_DIAG_PLLDRC_CTRL           0x10394
  92#define XCVR_DIAG_HSCLK_SEL             0x10398
  93#define XCVR_DIAG_HSCLK_DIV             0x1039c
  94#define TX_PSC_A0                       0x10400
  95#define TX_PSC_A1                       0x10404
  96#define TX_PSC_A2                       0x10408
  97#define TX_PSC_A3                       0x1040c
  98#define RX_PSC_A0                       0x20000
  99#define RX_PSC_A1                       0x20004
 100#define RX_PSC_A2                       0x20008
 101#define RX_PSC_A3                       0x2000c
 102#define PHY_PLL_CFG                     0x30038
 103
 104struct cdns_dp_phy {
 105        void __iomem *base;     /* DPTX registers base */
 106        void __iomem *sd_base; /* SD0801 registers base */
 107        u32 num_lanes; /* Number of lanes to use */
 108        u32 max_bit_rate; /* Maximum link bit rate to use (in Mbps) */
 109        struct device *dev;
 110};
 111
 112static int cdns_dp_phy_init(struct phy *phy);
 113static void cdns_dp_phy_run(struct cdns_dp_phy *cdns_phy);
 114static void cdns_dp_phy_wait_pma_cmn_ready(struct cdns_dp_phy *cdns_phy);
 115static void cdns_dp_phy_pma_cfg(struct cdns_dp_phy *cdns_phy);
 116static void cdns_dp_phy_pma_cmn_cfg_25mhz(struct cdns_dp_phy *cdns_phy);
 117static void cdns_dp_phy_pma_lane_cfg(struct cdns_dp_phy *cdns_phy,
 118                                         unsigned int lane);
 119static void cdns_dp_phy_pma_cmn_vco_cfg_25mhz(struct cdns_dp_phy *cdns_phy);
 120static void cdns_dp_phy_pma_cmn_rate(struct cdns_dp_phy *cdns_phy);
 121static void cdns_dp_phy_write_field(struct cdns_dp_phy *cdns_phy,
 122                                        unsigned int offset,
 123                                        unsigned char start_bit,
 124                                        unsigned char num_bits,
 125                                        unsigned int val);
 126
 127static const struct phy_ops cdns_dp_phy_ops = {
 128        .init           = cdns_dp_phy_init,
 129        .owner          = THIS_MODULE,
 130};
 131
 132static int cdns_dp_phy_init(struct phy *phy)
 133{
 134        unsigned char lane_bits;
 135
 136        struct cdns_dp_phy *cdns_phy = phy_get_drvdata(phy);
 137
 138        writel(0x0003, cdns_phy->base + PHY_AUX_CTRL); /* enable AUX */
 139
 140        /* PHY PMA registers configuration function */
 141        cdns_dp_phy_pma_cfg(cdns_phy);
 142
 143        /*
 144         * Set lines power state to A0
 145         * Set lines pll clk enable to 0
 146         */
 147
 148        cdns_dp_phy_write_field(cdns_phy, PHY_PMA_XCVR_POWER_STATE_REQ,
 149                                PHY_POWER_STATE_LN_0, 6, 0x0000);
 150
 151        if (cdns_phy->num_lanes >= 2) {
 152                cdns_dp_phy_write_field(cdns_phy,
 153                                        PHY_PMA_XCVR_POWER_STATE_REQ,
 154                                        PHY_POWER_STATE_LN_1, 6, 0x0000);
 155
 156                if (cdns_phy->num_lanes == 4) {
 157                        cdns_dp_phy_write_field(cdns_phy,
 158                                                PHY_PMA_XCVR_POWER_STATE_REQ,
 159                                                PHY_POWER_STATE_LN_2, 6, 0);
 160                        cdns_dp_phy_write_field(cdns_phy,
 161                                                PHY_PMA_XCVR_POWER_STATE_REQ,
 162                                                PHY_POWER_STATE_LN_3, 6, 0);
 163                }
 164        }
 165
 166        cdns_dp_phy_write_field(cdns_phy, PHY_PMA_XCVR_PLLCLK_EN,
 167                                0, 1, 0x0000);
 168
 169        if (cdns_phy->num_lanes >= 2) {
 170                cdns_dp_phy_write_field(cdns_phy, PHY_PMA_XCVR_PLLCLK_EN,
 171                                        1, 1, 0x0000);
 172                if (cdns_phy->num_lanes == 4) {
 173                        cdns_dp_phy_write_field(cdns_phy,
 174                                                PHY_PMA_XCVR_PLLCLK_EN,
 175                                                2, 1, 0x0000);
 176                        cdns_dp_phy_write_field(cdns_phy,
 177                                                PHY_PMA_XCVR_PLLCLK_EN,
 178                                                3, 1, 0x0000);
 179                }
 180        }
 181
 182        /*
 183         * release phy_l0*_reset_n and pma_tx_elec_idle_ln_* based on
 184         * used lanes
 185         */
 186        lane_bits = (1 << cdns_phy->num_lanes) - 1;
 187        writel(((0xF & ~lane_bits) << 4) | (0xF & lane_bits),
 188                   cdns_phy->base + PHY_RESET);
 189
 190        /* release pma_xcvr_pllclk_en_ln_*, only for the master lane */
 191        writel(0x0001, cdns_phy->base + PHY_PMA_XCVR_PLLCLK_EN);
 192
 193        /* PHY PMA registers configuration functions */
 194        cdns_dp_phy_pma_cmn_vco_cfg_25mhz(cdns_phy);
 195        cdns_dp_phy_pma_cmn_rate(cdns_phy);
 196
 197        /* take out of reset */
 198        cdns_dp_phy_write_field(cdns_phy, PHY_RESET, 8, 1, 1);
 199        cdns_dp_phy_wait_pma_cmn_ready(cdns_phy);
 200        cdns_dp_phy_run(cdns_phy);
 201
 202        return 0;
 203}
 204
 205static void cdns_dp_phy_wait_pma_cmn_ready(struct cdns_dp_phy *cdns_phy)
 206{
 207        unsigned int reg;
 208        int ret;
 209
 210        ret = readl_poll_timeout(cdns_phy->base + PHY_PMA_CMN_READY, reg,
 211                                 reg & 1, 0, 500);
 212        if (ret == -ETIMEDOUT)
 213                dev_err(cdns_phy->dev,
 214                        "timeout waiting for PMA common ready\n");
 215}
 216
 217static void cdns_dp_phy_pma_cfg(struct cdns_dp_phy *cdns_phy)
 218{
 219        unsigned int i;
 220
 221        /* PMA common configuration */
 222        cdns_dp_phy_pma_cmn_cfg_25mhz(cdns_phy);
 223
 224        /* PMA lane configuration to deal with multi-link operation */
 225        for (i = 0; i < cdns_phy->num_lanes; i++)
 226                cdns_dp_phy_pma_lane_cfg(cdns_phy, i);
 227}
 228
 229static void cdns_dp_phy_pma_cmn_cfg_25mhz(struct cdns_dp_phy *cdns_phy)
 230{
 231        /* refclock registers - assumes 25 MHz refclock */
 232        writel(0x0019, cdns_phy->sd_base + CMN_SSM_BIAS_TMR);
 233        writel(0x0032, cdns_phy->sd_base + CMN_PLLSM0_PLLPRE_TMR);
 234        writel(0x00D1, cdns_phy->sd_base + CMN_PLLSM0_PLLLOCK_TMR);
 235        writel(0x0032, cdns_phy->sd_base + CMN_PLLSM1_PLLPRE_TMR);
 236        writel(0x00D1, cdns_phy->sd_base + CMN_PLLSM1_PLLLOCK_TMR);
 237        writel(0x007D, cdns_phy->sd_base + CMN_BGCAL_INIT_TMR);
 238        writel(0x007D, cdns_phy->sd_base + CMN_BGCAL_ITER_TMR);
 239        writel(0x0019, cdns_phy->sd_base + CMN_IBCAL_INIT_TMR);
 240        writel(0x001E, cdns_phy->sd_base + CMN_TXPUCAL_INIT_TMR);
 241        writel(0x0006, cdns_phy->sd_base + CMN_TXPUCAL_ITER_TMR);
 242        writel(0x001E, cdns_phy->sd_base + CMN_TXPDCAL_INIT_TMR);
 243        writel(0x0006, cdns_phy->sd_base + CMN_TXPDCAL_ITER_TMR);
 244        writel(0x02EE, cdns_phy->sd_base + CMN_RXCAL_INIT_TMR);
 245        writel(0x0006, cdns_phy->sd_base + CMN_RXCAL_ITER_TMR);
 246        writel(0x0002, cdns_phy->sd_base + CMN_SD_CAL_INIT_TMR);
 247        writel(0x0002, cdns_phy->sd_base + CMN_SD_CAL_ITER_TMR);
 248        writel(0x000E, cdns_phy->sd_base + CMN_SD_CAL_REFTIM_START);
 249        writel(0x012B, cdns_phy->sd_base + CMN_SD_CAL_PLLCNT_START);
 250        /* PLL registers */
 251        writel(0x0409, cdns_phy->sd_base + CMN_PDIAG_PLL0_CP_PADJ_M0);
 252        writel(0x1001, cdns_phy->sd_base + CMN_PDIAG_PLL0_CP_IADJ_M0);
 253        writel(0x0F08, cdns_phy->sd_base + CMN_PDIAG_PLL0_FILT_PADJ_M0);
 254        writel(0x0004, cdns_phy->sd_base + CMN_PLL0_DSM_DIAG_M0);
 255        writel(0x00FA, cdns_phy->sd_base + CMN_PLL0_VCOCAL_INIT_TMR);
 256        writel(0x0004, cdns_phy->sd_base + CMN_PLL0_VCOCAL_ITER_TMR);
 257        writel(0x00FA, cdns_phy->sd_base + CMN_PLL1_VCOCAL_INIT_TMR);
 258        writel(0x0004, cdns_phy->sd_base + CMN_PLL1_VCOCAL_ITER_TMR);
 259        writel(0x0318, cdns_phy->sd_base + CMN_PLL0_VCOCAL_REFTIM_START);
 260}
 261
 262static void cdns_dp_phy_pma_cmn_vco_cfg_25mhz(struct cdns_dp_phy *cdns_phy)
 263{
 264        /* Assumes 25 MHz refclock */
 265        switch (cdns_phy->max_bit_rate) {
 266                /* Setting VCO for 10.8GHz */
 267        case 2700:
 268        case 5400:
 269                writel(0x01B0, cdns_phy->sd_base + CMN_PLL0_INTDIV_M0);
 270                writel(0x0000, cdns_phy->sd_base + CMN_PLL0_FRACDIVL_M0);
 271                writel(0x0002, cdns_phy->sd_base + CMN_PLL0_FRACDIVH_M0);
 272                writel(0x0120, cdns_phy->sd_base + CMN_PLL0_HIGH_THR_M0);
 273                break;
 274                /* Setting VCO for 9.72GHz */
 275        case 2430:
 276        case 3240:
 277                writel(0x0184, cdns_phy->sd_base + CMN_PLL0_INTDIV_M0);
 278                writel(0xCCCD, cdns_phy->sd_base + CMN_PLL0_FRACDIVL_M0);
 279                writel(0x0002, cdns_phy->sd_base + CMN_PLL0_FRACDIVH_M0);
 280                writel(0x0104, cdns_phy->sd_base + CMN_PLL0_HIGH_THR_M0);
 281                break;
 282                /* Setting VCO for 8.64GHz */
 283        case 2160:
 284        case 4320:
 285                writel(0x0159, cdns_phy->sd_base + CMN_PLL0_INTDIV_M0);
 286                writel(0x999A, cdns_phy->sd_base + CMN_PLL0_FRACDIVL_M0);
 287                writel(0x0002, cdns_phy->sd_base + CMN_PLL0_FRACDIVH_M0);
 288                writel(0x00E7, cdns_phy->sd_base + CMN_PLL0_HIGH_THR_M0);
 289                break;
 290                /* Setting VCO for 8.1GHz */
 291        case 8100:
 292                writel(0x0144, cdns_phy->sd_base + CMN_PLL0_INTDIV_M0);
 293                writel(0x0000, cdns_phy->sd_base + CMN_PLL0_FRACDIVL_M0);
 294                writel(0x0002, cdns_phy->sd_base + CMN_PLL0_FRACDIVH_M0);
 295                writel(0x00D8, cdns_phy->sd_base + CMN_PLL0_HIGH_THR_M0);
 296                break;
 297        }
 298
 299        writel(0x0002, cdns_phy->sd_base + CMN_PDIAG_PLL0_CTRL_M0);
 300        writel(0x0318, cdns_phy->sd_base + CMN_PLL0_VCOCAL_PLLCNT_START);
 301}
 302
 303static void cdns_dp_phy_pma_cmn_rate(struct cdns_dp_phy *cdns_phy)
 304{
 305        unsigned int clk_sel_val = 0;
 306        unsigned int hsclk_div_val = 0;
 307        unsigned int i;
 308
 309        /* 16'h0000 for single DP link configuration */
 310        writel(0x0000, cdns_phy->sd_base + PHY_PLL_CFG);
 311
 312        switch (cdns_phy->max_bit_rate) {
 313        case 1620:
 314                clk_sel_val = 0x0f01;
 315                hsclk_div_val = 2;
 316                break;
 317        case 2160:
 318        case 2430:
 319        case 2700:
 320                clk_sel_val = 0x0701;
 321                 hsclk_div_val = 1;
 322                break;
 323        case 3240:
 324                clk_sel_val = 0x0b00;
 325                hsclk_div_val = 2;
 326                break;
 327        case 4320:
 328        case 5400:
 329                clk_sel_val = 0x0301;
 330                hsclk_div_val = 0;
 331                break;
 332        case 8100:
 333                clk_sel_val = 0x0200;
 334                hsclk_div_val = 0;
 335                break;
 336        }
 337
 338        writel(clk_sel_val, cdns_phy->sd_base + CMN_PDIAG_PLL0_CLK_SEL_M0);
 339
 340        /* PMA lane configuration to deal with multi-link operation */
 341        for (i = 0; i < cdns_phy->num_lanes; i++) {
 342                writel(hsclk_div_val,
 343                       cdns_phy->sd_base + (XCVR_DIAG_HSCLK_DIV | (i<<11)));
 344        }
 345}
 346
 347static void cdns_dp_phy_pma_lane_cfg(struct cdns_dp_phy *cdns_phy,
 348                                     unsigned int lane)
 349{
 350        unsigned int lane_bits = (lane & LANE_MASK) << 11;
 351
 352        /* Writing Tx/Rx Power State Controllers registers */
 353        writel(0x00FB, cdns_phy->sd_base + (TX_PSC_A0 | lane_bits));
 354        writel(0x04AA, cdns_phy->sd_base + (TX_PSC_A2 | lane_bits));
 355        writel(0x04AA, cdns_phy->sd_base + (TX_PSC_A3 | lane_bits));
 356        writel(0x0000, cdns_phy->sd_base + (RX_PSC_A0 | lane_bits));
 357        writel(0x0000, cdns_phy->sd_base + (RX_PSC_A2 | lane_bits));
 358        writel(0x0000, cdns_phy->sd_base + (RX_PSC_A3 | lane_bits));
 359
 360        writel(0x0001, cdns_phy->sd_base + (XCVR_DIAG_PLLDRC_CTRL | lane_bits));
 361        writel(0x0000, cdns_phy->sd_base + (XCVR_DIAG_HSCLK_SEL | lane_bits));
 362}
 363
 364static void cdns_dp_phy_run(struct cdns_dp_phy *cdns_phy)
 365{
 366        unsigned int read_val;
 367        u32 write_val1 = 0;
 368        u32 write_val2 = 0;
 369        u32 mask = 0;
 370        int ret;
 371
 372        /*
 373         * waiting for ACK of pma_xcvr_pllclk_en_ln_*, only for the
 374         * master lane
 375         */
 376        ret = readl_poll_timeout(cdns_phy->base + PHY_PMA_XCVR_PLLCLK_EN_ACK,
 377                                 read_val, read_val & 1, 0, POLL_TIMEOUT_US);
 378        if (ret == -ETIMEDOUT)
 379                dev_err(cdns_phy->dev,
 380                        "timeout waiting for link PLL clock enable ack\n");
 381
 382        ndelay(100);
 383
 384        switch (cdns_phy->num_lanes) {
 385
 386        case 1: /* lane 0 */
 387                write_val1 = 0x00000004;
 388                write_val2 = 0x00000001;
 389                mask = 0x0000003f;
 390                break;
 391        case 2: /* lane 0-1 */
 392                write_val1 = 0x00000404;
 393                write_val2 = 0x00000101;
 394                mask = 0x00003f3f;
 395                break;
 396        case 4: /* lane 0-3 */
 397                write_val1 = 0x04040404;
 398                write_val2 = 0x01010101;
 399                mask = 0x3f3f3f3f;
 400                break;
 401        }
 402
 403        writel(write_val1, cdns_phy->base + PHY_PMA_XCVR_POWER_STATE_REQ);
 404
 405        ret = readl_poll_timeout(cdns_phy->base + PHY_PMA_XCVR_POWER_STATE_ACK,
 406                                 read_val, (read_val & mask) == write_val1, 0,
 407                                 POLL_TIMEOUT_US);
 408        if (ret == -ETIMEDOUT)
 409                dev_err(cdns_phy->dev,
 410                        "timeout waiting for link power state ack\n");
 411
 412        writel(0, cdns_phy->base + PHY_PMA_XCVR_POWER_STATE_REQ);
 413        ndelay(100);
 414
 415        writel(write_val2, cdns_phy->base + PHY_PMA_XCVR_POWER_STATE_REQ);
 416
 417        ret = readl_poll_timeout(cdns_phy->base + PHY_PMA_XCVR_POWER_STATE_ACK,
 418                                 read_val, (read_val & mask) == write_val2, 0,
 419                                 POLL_TIMEOUT_US);
 420        if (ret == -ETIMEDOUT)
 421                dev_err(cdns_phy->dev,
 422                        "timeout waiting for link power state ack\n");
 423
 424        writel(0, cdns_phy->base + PHY_PMA_XCVR_POWER_STATE_REQ);
 425        ndelay(100);
 426}
 427
 428static void cdns_dp_phy_write_field(struct cdns_dp_phy *cdns_phy,
 429                                    unsigned int offset,
 430                                    unsigned char start_bit,
 431                                    unsigned char num_bits,
 432                                    unsigned int val)
 433{
 434        unsigned int read_val;
 435
 436        read_val = readl(cdns_phy->base + offset);
 437        writel(((val << start_bit) | (read_val & ~(((1 << num_bits) - 1) <<
 438                start_bit))), cdns_phy->base + offset);
 439}
 440
 441static int cdns_dp_phy_probe(struct platform_device *pdev)
 442{
 443        struct resource *regs;
 444        struct cdns_dp_phy *cdns_phy;
 445        struct device *dev = &pdev->dev;
 446        struct phy_provider *phy_provider;
 447        struct phy *phy;
 448        int err;
 449
 450        cdns_phy = devm_kzalloc(dev, sizeof(*cdns_phy), GFP_KERNEL);
 451        if (!cdns_phy)
 452                return -ENOMEM;
 453
 454        cdns_phy->dev = &pdev->dev;
 455
 456        phy = devm_phy_create(dev, NULL, &cdns_dp_phy_ops);
 457        if (IS_ERR(phy)) {
 458                dev_err(dev, "failed to create DisplayPort PHY\n");
 459                return PTR_ERR(phy);
 460        }
 461
 462        regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 463        cdns_phy->base = devm_ioremap_resource(&pdev->dev, regs);
 464        if (IS_ERR(cdns_phy->base))
 465                return PTR_ERR(cdns_phy->base);
 466
 467        regs = platform_get_resource(pdev, IORESOURCE_MEM, 1);
 468        cdns_phy->sd_base = devm_ioremap_resource(&pdev->dev, regs);
 469        if (IS_ERR(cdns_phy->sd_base))
 470                return PTR_ERR(cdns_phy->sd_base);
 471
 472        err = device_property_read_u32(dev, "num_lanes",
 473                                       &(cdns_phy->num_lanes));
 474        if (err)
 475                cdns_phy->num_lanes = DEFAULT_NUM_LANES;
 476
 477        switch (cdns_phy->num_lanes) {
 478        case 1:
 479        case 2:
 480        case 4:
 481                /* valid number of lanes */
 482                break;
 483        default:
 484                dev_err(dev, "unsupported number of lanes: %d\n",
 485                        cdns_phy->num_lanes);
 486                return -EINVAL;
 487        }
 488
 489        err = device_property_read_u32(dev, "max_bit_rate",
 490                   &(cdns_phy->max_bit_rate));
 491        if (err)
 492                cdns_phy->max_bit_rate = DEFAULT_MAX_BIT_RATE;
 493
 494        switch (cdns_phy->max_bit_rate) {
 495        case 2160:
 496        case 2430:
 497        case 2700:
 498        case 3240:
 499        case 4320:
 500        case 5400:
 501        case 8100:
 502                /* valid bit rate */
 503                break;
 504        default:
 505                dev_err(dev, "unsupported max bit rate: %dMbps\n",
 506                        cdns_phy->max_bit_rate);
 507                return -EINVAL;
 508        }
 509
 510        phy_set_drvdata(phy, cdns_phy);
 511
 512        phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
 513
 514        dev_info(dev, "%d lanes, max bit rate %d.%03d Gbps\n",
 515                 cdns_phy->num_lanes,
 516                 cdns_phy->max_bit_rate / 1000,
 517                 cdns_phy->max_bit_rate % 1000);
 518
 519        return PTR_ERR_OR_ZERO(phy_provider);
 520}
 521
 522static const struct of_device_id cdns_dp_phy_of_match[] = {
 523        {
 524                .compatible = "cdns,dp-phy"
 525        },
 526        {}
 527};
 528MODULE_DEVICE_TABLE(of, cdns_dp_phy_of_match);
 529
 530static struct platform_driver cdns_dp_phy_driver = {
 531        .probe  = cdns_dp_phy_probe,
 532        .driver = {
 533                .name   = "cdns-dp-phy",
 534                .of_match_table = cdns_dp_phy_of_match,
 535        }
 536};
 537module_platform_driver(cdns_dp_phy_driver);
 538
 539MODULE_AUTHOR("Cadence Design Systems, Inc.");
 540MODULE_DESCRIPTION("Cadence MHDP PHY driver");
 541MODULE_LICENSE("GPL v2");
 542