Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /* Copyright (c) 2021-2022 NXP. */
0003 
0004 #include <linux/module.h>
0005 #include <linux/phy.h>
0006 #include <linux/phy/phy.h>
0007 #include <linux/platform_device.h>
0008 #include <linux/workqueue.h>
0009 
0010 #define LYNX_28G_NUM_LANE           8
0011 #define LYNX_28G_NUM_PLL            2
0012 
0013 /* General registers per SerDes block */
0014 #define LYNX_28G_PCC8               0x10a0
0015 #define LYNX_28G_PCC8_SGMII         0x1
0016 #define LYNX_28G_PCC8_SGMII_DIS         0x0
0017 
0018 #define LYNX_28G_PCCC               0x10b0
0019 #define LYNX_28G_PCCC_10GBASER          0x9
0020 #define LYNX_28G_PCCC_USXGMII           0x1
0021 #define LYNX_28G_PCCC_SXGMII_DIS        0x0
0022 
0023 #define LYNX_28G_LNa_PCC_OFFSET(lane)       (4 * (LYNX_28G_NUM_LANE - (lane->id) - 1))
0024 
0025 /* Per PLL registers */
0026 #define LYNX_28G_PLLnRSTCTL(pll)        (0x400 + (pll) * 0x100 + 0x0)
0027 #define LYNX_28G_PLLnRSTCTL_DIS(rstctl)     (((rstctl) & BIT(24)) >> 24)
0028 #define LYNX_28G_PLLnRSTCTL_LOCK(rstctl)    (((rstctl) & BIT(23)) >> 23)
0029 
0030 #define LYNX_28G_PLLnCR0(pll)           (0x400 + (pll) * 0x100 + 0x4)
0031 #define LYNX_28G_PLLnCR0_REFCLK_SEL(cr0)    (((cr0) & GENMASK(20, 16)))
0032 #define LYNX_28G_PLLnCR0_REFCLK_SEL_100MHZ  0x0
0033 #define LYNX_28G_PLLnCR0_REFCLK_SEL_125MHZ  0x10000
0034 #define LYNX_28G_PLLnCR0_REFCLK_SEL_156MHZ  0x20000
0035 #define LYNX_28G_PLLnCR0_REFCLK_SEL_150MHZ  0x30000
0036 #define LYNX_28G_PLLnCR0_REFCLK_SEL_161MHZ  0x40000
0037 
0038 #define LYNX_28G_PLLnCR1(pll)           (0x400 + (pll) * 0x100 + 0x8)
0039 #define LYNX_28G_PLLnCR1_FRATE_SEL(cr1)     (((cr1) & GENMASK(28, 24)))
0040 #define LYNX_28G_PLLnCR1_FRATE_5G_10GVCO    0x0
0041 #define LYNX_28G_PLLnCR1_FRATE_5G_25GVCO    0x10000000
0042 #define LYNX_28G_PLLnCR1_FRATE_10G_20GVCO   0x6000000
0043 
0044 /* Per SerDes lane registers */
0045 /* Lane a General Control Register */
0046 #define LYNX_28G_LNaGCR0(lane)          (0x800 + (lane) * 0x100 + 0x0)
0047 #define LYNX_28G_LNaGCR0_PROTO_SEL_MSK      GENMASK(7, 3)
0048 #define LYNX_28G_LNaGCR0_PROTO_SEL_SGMII    0x8
0049 #define LYNX_28G_LNaGCR0_PROTO_SEL_XFI      0x50
0050 #define LYNX_28G_LNaGCR0_IF_WIDTH_MSK       GENMASK(2, 0)
0051 #define LYNX_28G_LNaGCR0_IF_WIDTH_10_BIT    0x0
0052 #define LYNX_28G_LNaGCR0_IF_WIDTH_20_BIT    0x2
0053 
0054 /* Lane a Tx Reset Control Register */
0055 #define LYNX_28G_LNaTRSTCTL(lane)       (0x800 + (lane) * 0x100 + 0x20)
0056 #define LYNX_28G_LNaTRSTCTL_HLT_REQ     BIT(27)
0057 #define LYNX_28G_LNaTRSTCTL_RST_DONE        BIT(30)
0058 #define LYNX_28G_LNaTRSTCTL_RST_REQ     BIT(31)
0059 
0060 /* Lane a Tx General Control Register */
0061 #define LYNX_28G_LNaTGCR0(lane)         (0x800 + (lane) * 0x100 + 0x24)
0062 #define LYNX_28G_LNaTGCR0_USE_PLLF      0x0
0063 #define LYNX_28G_LNaTGCR0_USE_PLLS      BIT(28)
0064 #define LYNX_28G_LNaTGCR0_USE_PLL_MSK       BIT(28)
0065 #define LYNX_28G_LNaTGCR0_N_RATE_FULL       0x0
0066 #define LYNX_28G_LNaTGCR0_N_RATE_HALF       0x1000000
0067 #define LYNX_28G_LNaTGCR0_N_RATE_QUARTER    0x2000000
0068 #define LYNX_28G_LNaTGCR0_N_RATE_MSK        GENMASK(26, 24)
0069 
0070 #define LYNX_28G_LNaTECR0(lane)         (0x800 + (lane) * 0x100 + 0x30)
0071 
0072 /* Lane a Rx Reset Control Register */
0073 #define LYNX_28G_LNaRRSTCTL(lane)       (0x800 + (lane) * 0x100 + 0x40)
0074 #define LYNX_28G_LNaRRSTCTL_HLT_REQ     BIT(27)
0075 #define LYNX_28G_LNaRRSTCTL_RST_DONE        BIT(30)
0076 #define LYNX_28G_LNaRRSTCTL_RST_REQ     BIT(31)
0077 #define LYNX_28G_LNaRRSTCTL_CDR_LOCK        BIT(12)
0078 
0079 /* Lane a Rx General Control Register */
0080 #define LYNX_28G_LNaRGCR0(lane)         (0x800 + (lane) * 0x100 + 0x44)
0081 #define LYNX_28G_LNaRGCR0_USE_PLLF      0x0
0082 #define LYNX_28G_LNaRGCR0_USE_PLLS      BIT(28)
0083 #define LYNX_28G_LNaRGCR0_USE_PLL_MSK       BIT(28)
0084 #define LYNX_28G_LNaRGCR0_N_RATE_MSK        GENMASK(26, 24)
0085 #define LYNX_28G_LNaRGCR0_N_RATE_FULL       0x0
0086 #define LYNX_28G_LNaRGCR0_N_RATE_HALF       0x1000000
0087 #define LYNX_28G_LNaRGCR0_N_RATE_QUARTER    0x2000000
0088 #define LYNX_28G_LNaRGCR0_N_RATE_MSK        GENMASK(26, 24)
0089 
0090 #define LYNX_28G_LNaRGCR1(lane)         (0x800 + (lane) * 0x100 + 0x48)
0091 
0092 #define LYNX_28G_LNaRECR0(lane)         (0x800 + (lane) * 0x100 + 0x50)
0093 #define LYNX_28G_LNaRECR1(lane)         (0x800 + (lane) * 0x100 + 0x54)
0094 #define LYNX_28G_LNaRECR2(lane)         (0x800 + (lane) * 0x100 + 0x58)
0095 
0096 #define LYNX_28G_LNaRSCCR0(lane)        (0x800 + (lane) * 0x100 + 0x74)
0097 
0098 #define LYNX_28G_LNaPSS(lane)           (0x1000 + (lane) * 0x4)
0099 #define LYNX_28G_LNaPSS_TYPE(pss)       (((pss) & GENMASK(30, 24)) >> 24)
0100 #define LYNX_28G_LNaPSS_TYPE_SGMII      0x4
0101 #define LYNX_28G_LNaPSS_TYPE_XFI        0x28
0102 
0103 #define LYNX_28G_SGMIIaCR1(lane)        (0x1804 + (lane) * 0x10)
0104 #define LYNX_28G_SGMIIaCR1_SGPCS_EN     BIT(11)
0105 #define LYNX_28G_SGMIIaCR1_SGPCS_DIS        0x0
0106 #define LYNX_28G_SGMIIaCR1_SGPCS_MSK        BIT(11)
0107 
0108 struct lynx_28g_priv;
0109 
0110 struct lynx_28g_pll {
0111     struct lynx_28g_priv *priv;
0112     u32 rstctl, cr0, cr1;
0113     int id;
0114     DECLARE_PHY_INTERFACE_MASK(supported);
0115 };
0116 
0117 struct lynx_28g_lane {
0118     struct lynx_28g_priv *priv;
0119     struct phy *phy;
0120     bool powered_up;
0121     bool init;
0122     unsigned int id;
0123     phy_interface_t interface;
0124 };
0125 
0126 struct lynx_28g_priv {
0127     void __iomem *base;
0128     struct device *dev;
0129     struct lynx_28g_pll pll[LYNX_28G_NUM_PLL];
0130     struct lynx_28g_lane lane[LYNX_28G_NUM_LANE];
0131 
0132     struct delayed_work cdr_check;
0133 };
0134 
0135 static void lynx_28g_rmw(struct lynx_28g_priv *priv, unsigned long off,
0136              u32 val, u32 mask)
0137 {
0138     void __iomem *reg = priv->base + off;
0139     u32 orig, tmp;
0140 
0141     orig = ioread32(reg);
0142     tmp = orig & ~mask;
0143     tmp |= val;
0144     iowrite32(tmp, reg);
0145 }
0146 
0147 #define lynx_28g_lane_rmw(lane, reg, val, mask) \
0148     lynx_28g_rmw((lane)->priv, LYNX_28G_##reg(lane->id), \
0149              LYNX_28G_##reg##_##val, LYNX_28G_##reg##_##mask)
0150 #define lynx_28g_lane_read(lane, reg)           \
0151     ioread32((lane)->priv->base + LYNX_28G_##reg((lane)->id))
0152 #define lynx_28g_pll_read(pll, reg)         \
0153     ioread32((pll)->priv->base + LYNX_28G_##reg((pll)->id))
0154 
0155 static bool lynx_28g_supports_interface(struct lynx_28g_priv *priv, int intf)
0156 {
0157     int i;
0158 
0159     for (i = 0; i < LYNX_28G_NUM_PLL; i++) {
0160         if (LYNX_28G_PLLnRSTCTL_DIS(priv->pll[i].rstctl))
0161             continue;
0162 
0163         if (test_bit(intf, priv->pll[i].supported))
0164             return true;
0165     }
0166 
0167     return false;
0168 }
0169 
0170 static struct lynx_28g_pll *lynx_28g_pll_get(struct lynx_28g_priv *priv,
0171                          phy_interface_t intf)
0172 {
0173     struct lynx_28g_pll *pll;
0174     int i;
0175 
0176     for (i = 0; i < LYNX_28G_NUM_PLL; i++) {
0177         pll = &priv->pll[i];
0178 
0179         if (LYNX_28G_PLLnRSTCTL_DIS(pll->rstctl))
0180             continue;
0181 
0182         if (test_bit(intf, pll->supported))
0183             return pll;
0184     }
0185 
0186     return NULL;
0187 }
0188 
0189 static void lynx_28g_lane_set_nrate(struct lynx_28g_lane *lane,
0190                     struct lynx_28g_pll *pll,
0191                     phy_interface_t intf)
0192 {
0193     switch (LYNX_28G_PLLnCR1_FRATE_SEL(pll->cr1)) {
0194     case LYNX_28G_PLLnCR1_FRATE_5G_10GVCO:
0195     case LYNX_28G_PLLnCR1_FRATE_5G_25GVCO:
0196         switch (intf) {
0197         case PHY_INTERFACE_MODE_SGMII:
0198         case PHY_INTERFACE_MODE_1000BASEX:
0199             lynx_28g_lane_rmw(lane, LNaTGCR0, N_RATE_QUARTER, N_RATE_MSK);
0200             lynx_28g_lane_rmw(lane, LNaRGCR0, N_RATE_QUARTER, N_RATE_MSK);
0201             break;
0202         default:
0203             break;
0204         }
0205         break;
0206     case LYNX_28G_PLLnCR1_FRATE_10G_20GVCO:
0207         switch (intf) {
0208         case PHY_INTERFACE_MODE_10GBASER:
0209         case PHY_INTERFACE_MODE_USXGMII:
0210             lynx_28g_lane_rmw(lane, LNaTGCR0, N_RATE_FULL, N_RATE_MSK);
0211             lynx_28g_lane_rmw(lane, LNaRGCR0, N_RATE_FULL, N_RATE_MSK);
0212             break;
0213         default:
0214             break;
0215         }
0216         break;
0217     default:
0218         break;
0219     }
0220 }
0221 
0222 static void lynx_28g_lane_set_pll(struct lynx_28g_lane *lane,
0223                   struct lynx_28g_pll *pll)
0224 {
0225     if (pll->id == 0) {
0226         lynx_28g_lane_rmw(lane, LNaTGCR0, USE_PLLF, USE_PLL_MSK);
0227         lynx_28g_lane_rmw(lane, LNaRGCR0, USE_PLLF, USE_PLL_MSK);
0228     } else {
0229         lynx_28g_lane_rmw(lane, LNaTGCR0, USE_PLLS, USE_PLL_MSK);
0230         lynx_28g_lane_rmw(lane, LNaRGCR0, USE_PLLS, USE_PLL_MSK);
0231     }
0232 }
0233 
0234 static void lynx_28g_cleanup_lane(struct lynx_28g_lane *lane)
0235 {
0236     u32 lane_offset = LYNX_28G_LNa_PCC_OFFSET(lane);
0237     struct lynx_28g_priv *priv = lane->priv;
0238 
0239     /* Cleanup the protocol configuration registers of the current protocol */
0240     switch (lane->interface) {
0241     case PHY_INTERFACE_MODE_10GBASER:
0242         lynx_28g_rmw(priv, LYNX_28G_PCCC,
0243                  LYNX_28G_PCCC_SXGMII_DIS << lane_offset,
0244                  GENMASK(3, 0) << lane_offset);
0245         break;
0246     case PHY_INTERFACE_MODE_SGMII:
0247     case PHY_INTERFACE_MODE_1000BASEX:
0248         lynx_28g_rmw(priv, LYNX_28G_PCC8,
0249                  LYNX_28G_PCC8_SGMII_DIS << lane_offset,
0250                  GENMASK(3, 0) << lane_offset);
0251         break;
0252     default:
0253         break;
0254     }
0255 }
0256 
0257 static void lynx_28g_lane_set_sgmii(struct lynx_28g_lane *lane)
0258 {
0259     u32 lane_offset = LYNX_28G_LNa_PCC_OFFSET(lane);
0260     struct lynx_28g_priv *priv = lane->priv;
0261     struct lynx_28g_pll *pll;
0262 
0263     lynx_28g_cleanup_lane(lane);
0264 
0265     /* Setup the lane to run in SGMII */
0266     lynx_28g_rmw(priv, LYNX_28G_PCC8,
0267              LYNX_28G_PCC8_SGMII << lane_offset,
0268              GENMASK(3, 0) << lane_offset);
0269 
0270     /* Setup the protocol select and SerDes parallel interface width */
0271     lynx_28g_lane_rmw(lane, LNaGCR0, PROTO_SEL_SGMII, PROTO_SEL_MSK);
0272     lynx_28g_lane_rmw(lane, LNaGCR0, IF_WIDTH_10_BIT, IF_WIDTH_MSK);
0273 
0274     /* Switch to the PLL that works with this interface type */
0275     pll = lynx_28g_pll_get(priv, PHY_INTERFACE_MODE_SGMII);
0276     lynx_28g_lane_set_pll(lane, pll);
0277 
0278     /* Choose the portion of clock net to be used on this lane */
0279     lynx_28g_lane_set_nrate(lane, pll, PHY_INTERFACE_MODE_SGMII);
0280 
0281     /* Enable the SGMII PCS */
0282     lynx_28g_lane_rmw(lane, SGMIIaCR1, SGPCS_EN, SGPCS_MSK);
0283 
0284     /* Configure the appropriate equalization parameters for the protocol */
0285     iowrite32(0x00808006, priv->base + LYNX_28G_LNaTECR0(lane->id));
0286     iowrite32(0x04310000, priv->base + LYNX_28G_LNaRGCR1(lane->id));
0287     iowrite32(0x9f800000, priv->base + LYNX_28G_LNaRECR0(lane->id));
0288     iowrite32(0x001f0000, priv->base + LYNX_28G_LNaRECR1(lane->id));
0289     iowrite32(0x00000000, priv->base + LYNX_28G_LNaRECR2(lane->id));
0290     iowrite32(0x00000000, priv->base + LYNX_28G_LNaRSCCR0(lane->id));
0291 }
0292 
0293 static void lynx_28g_lane_set_10gbaser(struct lynx_28g_lane *lane)
0294 {
0295     u32 lane_offset = LYNX_28G_LNa_PCC_OFFSET(lane);
0296     struct lynx_28g_priv *priv = lane->priv;
0297     struct lynx_28g_pll *pll;
0298 
0299     lynx_28g_cleanup_lane(lane);
0300 
0301     /* Enable the SXGMII lane */
0302     lynx_28g_rmw(priv, LYNX_28G_PCCC,
0303              LYNX_28G_PCCC_10GBASER << lane_offset,
0304              GENMASK(3, 0) << lane_offset);
0305 
0306     /* Setup the protocol select and SerDes parallel interface width */
0307     lynx_28g_lane_rmw(lane, LNaGCR0, PROTO_SEL_XFI, PROTO_SEL_MSK);
0308     lynx_28g_lane_rmw(lane, LNaGCR0, IF_WIDTH_20_BIT, IF_WIDTH_MSK);
0309 
0310     /* Switch to the PLL that works with this interface type */
0311     pll = lynx_28g_pll_get(priv, PHY_INTERFACE_MODE_10GBASER);
0312     lynx_28g_lane_set_pll(lane, pll);
0313 
0314     /* Choose the portion of clock net to be used on this lane */
0315     lynx_28g_lane_set_nrate(lane, pll, PHY_INTERFACE_MODE_10GBASER);
0316 
0317     /* Disable the SGMII PCS */
0318     lynx_28g_lane_rmw(lane, SGMIIaCR1, SGPCS_DIS, SGPCS_MSK);
0319 
0320     /* Configure the appropriate equalization parameters for the protocol */
0321     iowrite32(0x10808307, priv->base + LYNX_28G_LNaTECR0(lane->id));
0322     iowrite32(0x10000000, priv->base + LYNX_28G_LNaRGCR1(lane->id));
0323     iowrite32(0x00000000, priv->base + LYNX_28G_LNaRECR0(lane->id));
0324     iowrite32(0x001f0000, priv->base + LYNX_28G_LNaRECR1(lane->id));
0325     iowrite32(0x81000020, priv->base + LYNX_28G_LNaRECR2(lane->id));
0326     iowrite32(0x00002000, priv->base + LYNX_28G_LNaRSCCR0(lane->id));
0327 }
0328 
0329 static int lynx_28g_power_off(struct phy *phy)
0330 {
0331     struct lynx_28g_lane *lane = phy_get_drvdata(phy);
0332     u32 trstctl, rrstctl;
0333 
0334     if (!lane->powered_up)
0335         return 0;
0336 
0337     /* Issue a halt request */
0338     lynx_28g_lane_rmw(lane, LNaTRSTCTL, HLT_REQ, HLT_REQ);
0339     lynx_28g_lane_rmw(lane, LNaRRSTCTL, HLT_REQ, HLT_REQ);
0340 
0341     /* Wait until the halting process is complete */
0342     do {
0343         trstctl = lynx_28g_lane_read(lane, LNaTRSTCTL);
0344         rrstctl = lynx_28g_lane_read(lane, LNaRRSTCTL);
0345     } while ((trstctl & LYNX_28G_LNaTRSTCTL_HLT_REQ) ||
0346          (rrstctl & LYNX_28G_LNaRRSTCTL_HLT_REQ));
0347 
0348     lane->powered_up = false;
0349 
0350     return 0;
0351 }
0352 
0353 static int lynx_28g_power_on(struct phy *phy)
0354 {
0355     struct lynx_28g_lane *lane = phy_get_drvdata(phy);
0356     u32 trstctl, rrstctl;
0357 
0358     if (lane->powered_up)
0359         return 0;
0360 
0361     /* Issue a reset request on the lane */
0362     lynx_28g_lane_rmw(lane, LNaTRSTCTL, RST_REQ, RST_REQ);
0363     lynx_28g_lane_rmw(lane, LNaRRSTCTL, RST_REQ, RST_REQ);
0364 
0365     /* Wait until the reset sequence is completed */
0366     do {
0367         trstctl = lynx_28g_lane_read(lane, LNaTRSTCTL);
0368         rrstctl = lynx_28g_lane_read(lane, LNaRRSTCTL);
0369     } while (!(trstctl & LYNX_28G_LNaTRSTCTL_RST_DONE) ||
0370          !(rrstctl & LYNX_28G_LNaRRSTCTL_RST_DONE));
0371 
0372     lane->powered_up = true;
0373 
0374     return 0;
0375 }
0376 
0377 static int lynx_28g_set_mode(struct phy *phy, enum phy_mode mode, int submode)
0378 {
0379     struct lynx_28g_lane *lane = phy_get_drvdata(phy);
0380     struct lynx_28g_priv *priv = lane->priv;
0381     int powered_up = lane->powered_up;
0382     int err = 0;
0383 
0384     if (mode != PHY_MODE_ETHERNET)
0385         return -EOPNOTSUPP;
0386 
0387     if (lane->interface == PHY_INTERFACE_MODE_NA)
0388         return -EOPNOTSUPP;
0389 
0390     if (!lynx_28g_supports_interface(priv, submode))
0391         return -EOPNOTSUPP;
0392 
0393     /* If the lane is powered up, put the lane into the halt state while
0394      * the reconfiguration is being done.
0395      */
0396     if (powered_up)
0397         lynx_28g_power_off(phy);
0398 
0399     switch (submode) {
0400     case PHY_INTERFACE_MODE_SGMII:
0401     case PHY_INTERFACE_MODE_1000BASEX:
0402         lynx_28g_lane_set_sgmii(lane);
0403         break;
0404     case PHY_INTERFACE_MODE_10GBASER:
0405         lynx_28g_lane_set_10gbaser(lane);
0406         break;
0407     default:
0408         err = -EOPNOTSUPP;
0409         goto out;
0410     }
0411 
0412     lane->interface = submode;
0413 
0414 out:
0415     /* Power up the lane if necessary */
0416     if (powered_up)
0417         lynx_28g_power_on(phy);
0418 
0419     return err;
0420 }
0421 
0422 static int lynx_28g_validate(struct phy *phy, enum phy_mode mode, int submode,
0423                  union phy_configure_opts *opts __always_unused)
0424 {
0425     struct lynx_28g_lane *lane = phy_get_drvdata(phy);
0426     struct lynx_28g_priv *priv = lane->priv;
0427 
0428     if (mode != PHY_MODE_ETHERNET)
0429         return -EOPNOTSUPP;
0430 
0431     if (!lynx_28g_supports_interface(priv, submode))
0432         return -EOPNOTSUPP;
0433 
0434     return 0;
0435 }
0436 
0437 static int lynx_28g_init(struct phy *phy)
0438 {
0439     struct lynx_28g_lane *lane = phy_get_drvdata(phy);
0440 
0441     /* Mark the fact that the lane was init */
0442     lane->init = true;
0443 
0444     /* SerDes lanes are powered on at boot time.  Any lane that is managed
0445      * by this driver will get powered down at init time aka at dpaa2-eth
0446      * probe time.
0447      */
0448     lane->powered_up = true;
0449     lynx_28g_power_off(phy);
0450 
0451     return 0;
0452 }
0453 
0454 static const struct phy_ops lynx_28g_ops = {
0455     .init       = lynx_28g_init,
0456     .power_on   = lynx_28g_power_on,
0457     .power_off  = lynx_28g_power_off,
0458     .set_mode   = lynx_28g_set_mode,
0459     .validate   = lynx_28g_validate,
0460     .owner      = THIS_MODULE,
0461 };
0462 
0463 static void lynx_28g_pll_read_configuration(struct lynx_28g_priv *priv)
0464 {
0465     struct lynx_28g_pll *pll;
0466     int i;
0467 
0468     for (i = 0; i < LYNX_28G_NUM_PLL; i++) {
0469         pll = &priv->pll[i];
0470         pll->priv = priv;
0471         pll->id = i;
0472 
0473         pll->rstctl = lynx_28g_pll_read(pll, PLLnRSTCTL);
0474         pll->cr0 = lynx_28g_pll_read(pll, PLLnCR0);
0475         pll->cr1 = lynx_28g_pll_read(pll, PLLnCR1);
0476 
0477         if (LYNX_28G_PLLnRSTCTL_DIS(pll->rstctl))
0478             continue;
0479 
0480         switch (LYNX_28G_PLLnCR1_FRATE_SEL(pll->cr1)) {
0481         case LYNX_28G_PLLnCR1_FRATE_5G_10GVCO:
0482         case LYNX_28G_PLLnCR1_FRATE_5G_25GVCO:
0483             /* 5GHz clock net */
0484             __set_bit(PHY_INTERFACE_MODE_1000BASEX, pll->supported);
0485             __set_bit(PHY_INTERFACE_MODE_SGMII, pll->supported);
0486             break;
0487         case LYNX_28G_PLLnCR1_FRATE_10G_20GVCO:
0488             /* 10.3125GHz clock net */
0489             __set_bit(PHY_INTERFACE_MODE_10GBASER, pll->supported);
0490             break;
0491         default:
0492             /* 6GHz, 12.890625GHz, 8GHz */
0493             break;
0494         }
0495     }
0496 }
0497 
0498 #define work_to_lynx(w) container_of((w), struct lynx_28g_priv, cdr_check.work)
0499 
0500 static void lynx_28g_cdr_lock_check(struct work_struct *work)
0501 {
0502     struct lynx_28g_priv *priv = work_to_lynx(work);
0503     struct lynx_28g_lane *lane;
0504     u32 rrstctl;
0505     int i;
0506 
0507     for (i = 0; i < LYNX_28G_NUM_LANE; i++) {
0508         lane = &priv->lane[i];
0509 
0510         if (!lane->init)
0511             continue;
0512 
0513         if (!lane->powered_up)
0514             continue;
0515 
0516         rrstctl = lynx_28g_lane_read(lane, LNaRRSTCTL);
0517         if (!(rrstctl & LYNX_28G_LNaRRSTCTL_CDR_LOCK)) {
0518             lynx_28g_lane_rmw(lane, LNaRRSTCTL, RST_REQ, RST_REQ);
0519             do {
0520                 rrstctl = lynx_28g_lane_read(lane, LNaRRSTCTL);
0521             } while (!(rrstctl & LYNX_28G_LNaRRSTCTL_RST_DONE));
0522         }
0523     }
0524     queue_delayed_work(system_power_efficient_wq, &priv->cdr_check,
0525                msecs_to_jiffies(1000));
0526 }
0527 
0528 static void lynx_28g_lane_read_configuration(struct lynx_28g_lane *lane)
0529 {
0530     u32 pss, protocol;
0531 
0532     pss = lynx_28g_lane_read(lane, LNaPSS);
0533     protocol = LYNX_28G_LNaPSS_TYPE(pss);
0534     switch (protocol) {
0535     case LYNX_28G_LNaPSS_TYPE_SGMII:
0536         lane->interface = PHY_INTERFACE_MODE_SGMII;
0537         break;
0538     case LYNX_28G_LNaPSS_TYPE_XFI:
0539         lane->interface = PHY_INTERFACE_MODE_10GBASER;
0540         break;
0541     default:
0542         lane->interface = PHY_INTERFACE_MODE_NA;
0543     }
0544 }
0545 
0546 static struct phy *lynx_28g_xlate(struct device *dev,
0547                   struct of_phandle_args *args)
0548 {
0549     struct lynx_28g_priv *priv = dev_get_drvdata(dev);
0550     int idx = args->args[0];
0551 
0552     if (WARN_ON(idx >= LYNX_28G_NUM_LANE))
0553         return ERR_PTR(-EINVAL);
0554 
0555     return priv->lane[idx].phy;
0556 }
0557 
0558 static int lynx_28g_probe(struct platform_device *pdev)
0559 {
0560     struct device *dev = &pdev->dev;
0561     struct phy_provider *provider;
0562     struct lynx_28g_priv *priv;
0563     int i;
0564 
0565     priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
0566     if (!priv)
0567         return -ENOMEM;
0568     priv->dev = &pdev->dev;
0569 
0570     priv->base = devm_platform_ioremap_resource(pdev, 0);
0571     if (IS_ERR(priv->base))
0572         return PTR_ERR(priv->base);
0573 
0574     lynx_28g_pll_read_configuration(priv);
0575 
0576     for (i = 0; i < LYNX_28G_NUM_LANE; i++) {
0577         struct lynx_28g_lane *lane = &priv->lane[i];
0578         struct phy *phy;
0579 
0580         memset(lane, 0, sizeof(*lane));
0581 
0582         phy = devm_phy_create(&pdev->dev, NULL, &lynx_28g_ops);
0583         if (IS_ERR(phy))
0584             return PTR_ERR(phy);
0585 
0586         lane->priv = priv;
0587         lane->phy = phy;
0588         lane->id = i;
0589         phy_set_drvdata(phy, lane);
0590         lynx_28g_lane_read_configuration(lane);
0591     }
0592 
0593     dev_set_drvdata(dev, priv);
0594 
0595     INIT_DELAYED_WORK(&priv->cdr_check, lynx_28g_cdr_lock_check);
0596 
0597     queue_delayed_work(system_power_efficient_wq, &priv->cdr_check,
0598                msecs_to_jiffies(1000));
0599 
0600     dev_set_drvdata(&pdev->dev, priv);
0601     provider = devm_of_phy_provider_register(&pdev->dev, lynx_28g_xlate);
0602 
0603     return PTR_ERR_OR_ZERO(provider);
0604 }
0605 
0606 static const struct of_device_id lynx_28g_of_match_table[] = {
0607     { .compatible = "fsl,lynx-28g" },
0608     { },
0609 };
0610 MODULE_DEVICE_TABLE(of, lynx_28g_of_match_table);
0611 
0612 static struct platform_driver lynx_28g_driver = {
0613     .probe  = lynx_28g_probe,
0614     .driver = {
0615         .name = "lynx-28g",
0616         .of_match_table = lynx_28g_of_match_table,
0617     },
0618 };
0619 module_platform_driver(lynx_28g_driver);
0620 
0621 MODULE_AUTHOR("Ioana Ciornei <ioana.ciornei@nxp.com>");
0622 MODULE_DESCRIPTION("Lynx 28G SerDes PHY driver for Layerscape SoCs");
0623 MODULE_LICENSE("GPL v2");