Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
0002 /*
0003  *  Driver for Analog Devices Industrial Ethernet T1L PHYs
0004  *
0005  * Copyright 2020 Analog Devices Inc.
0006  */
0007 #include <linux/kernel.h>
0008 #include <linux/bitfield.h>
0009 #include <linux/delay.h>
0010 #include <linux/errno.h>
0011 #include <linux/init.h>
0012 #include <linux/module.h>
0013 #include <linux/mii.h>
0014 #include <linux/phy.h>
0015 #include <linux/property.h>
0016 
0017 #define PHY_ID_ADIN1100             0x0283bc81
0018 
0019 #define ADIN_FORCED_MODE            0x8000
0020 #define   ADIN_FORCED_MODE_EN           BIT(0)
0021 
0022 #define ADIN_CRSM_SFT_RST           0x8810
0023 #define   ADIN_CRSM_SFT_RST_EN          BIT(0)
0024 
0025 #define ADIN_CRSM_SFT_PD_CNTRL          0x8812
0026 #define   ADIN_CRSM_SFT_PD_CNTRL_EN     BIT(0)
0027 
0028 #define ADIN_AN_PHY_INST_STATUS         0x8030
0029 #define   ADIN_IS_CFG_SLV           BIT(2)
0030 #define   ADIN_IS_CFG_MST           BIT(3)
0031 
0032 #define ADIN_CRSM_STAT              0x8818
0033 #define   ADIN_CRSM_SFT_PD_RDY          BIT(1)
0034 #define   ADIN_CRSM_SYS_RDY         BIT(0)
0035 
0036 #define ADIN_MSE_VAL                0x830B
0037 
0038 #define ADIN_SQI_MAX    7
0039 
0040 struct adin_mse_sqi_range {
0041     u16 start;
0042     u16 end;
0043 };
0044 
0045 static const struct adin_mse_sqi_range adin_mse_sqi_map[] = {
0046     { 0x0A74, 0xFFFF },
0047     { 0x084E, 0x0A74 },
0048     { 0x0698, 0x084E },
0049     { 0x053D, 0x0698 },
0050     { 0x0429, 0x053D },
0051     { 0x034E, 0x0429 },
0052     { 0x02A0, 0x034E },
0053     { 0x0000, 0x02A0 },
0054 };
0055 
0056 /**
0057  * struct adin_priv - ADIN PHY driver private data
0058  * @tx_level_2v4_able:      set if the PHY supports 2.4V TX levels (10BASE-T1L)
0059  * @tx_level_2v4:       set if the PHY requests 2.4V TX levels (10BASE-T1L)
0060  * @tx_level_prop_present:  set if the TX level is specified in DT
0061  */
0062 struct adin_priv {
0063     unsigned int        tx_level_2v4_able:1;
0064     unsigned int        tx_level_2v4:1;
0065     unsigned int        tx_level_prop_present:1;
0066 };
0067 
0068 static int adin_read_status(struct phy_device *phydev)
0069 {
0070     int ret;
0071 
0072     ret = genphy_c45_read_status(phydev);
0073     if (ret)
0074         return ret;
0075 
0076     ret = phy_read_mmd(phydev, MDIO_MMD_AN, ADIN_AN_PHY_INST_STATUS);
0077     if (ret < 0)
0078         return ret;
0079 
0080     if (ret & ADIN_IS_CFG_SLV)
0081         phydev->master_slave_state = MASTER_SLAVE_STATE_SLAVE;
0082 
0083     if (ret & ADIN_IS_CFG_MST)
0084         phydev->master_slave_state = MASTER_SLAVE_STATE_MASTER;
0085 
0086     return 0;
0087 }
0088 
0089 static int adin_config_aneg(struct phy_device *phydev)
0090 {
0091     struct adin_priv *priv = phydev->priv;
0092     int ret;
0093 
0094     if (phydev->autoneg == AUTONEG_DISABLE) {
0095         ret = genphy_c45_pma_setup_forced(phydev);
0096         if (ret < 0)
0097             return ret;
0098 
0099         if (priv->tx_level_prop_present && priv->tx_level_2v4)
0100             ret = phy_set_bits_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_B10L_PMA_CTRL,
0101                            MDIO_PMA_10T1L_CTRL_2V4_EN);
0102         else
0103             ret = phy_clear_bits_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_B10L_PMA_CTRL,
0104                          MDIO_PMA_10T1L_CTRL_2V4_EN);
0105         if (ret < 0)
0106             return ret;
0107 
0108         /* Force PHY to use above configurations */
0109         return phy_set_bits_mmd(phydev, MDIO_MMD_AN, ADIN_FORCED_MODE, ADIN_FORCED_MODE_EN);
0110     }
0111 
0112     ret = phy_clear_bits_mmd(phydev, MDIO_MMD_AN, ADIN_FORCED_MODE, ADIN_FORCED_MODE_EN);
0113     if (ret < 0)
0114         return ret;
0115 
0116     /* Request increased transmit level from LP. */
0117     if (priv->tx_level_prop_present && priv->tx_level_2v4) {
0118         ret = phy_set_bits_mmd(phydev, MDIO_MMD_AN, MDIO_AN_T1_ADV_H,
0119                        MDIO_AN_T1_ADV_H_10L_TX_HI |
0120                        MDIO_AN_T1_ADV_H_10L_TX_HI_REQ);
0121         if (ret < 0)
0122             return ret;
0123     }
0124 
0125     /* Disable 2.4 Vpp transmit level. */
0126     if ((priv->tx_level_prop_present && !priv->tx_level_2v4) || !priv->tx_level_2v4_able) {
0127         ret = phy_clear_bits_mmd(phydev, MDIO_MMD_AN, MDIO_AN_T1_ADV_H,
0128                      MDIO_AN_T1_ADV_H_10L_TX_HI |
0129                      MDIO_AN_T1_ADV_H_10L_TX_HI_REQ);
0130         if (ret < 0)
0131             return ret;
0132     }
0133 
0134     return genphy_c45_config_aneg(phydev);
0135 }
0136 
0137 static int adin_set_powerdown_mode(struct phy_device *phydev, bool en)
0138 {
0139     int ret;
0140     int val;
0141 
0142     val = en ? ADIN_CRSM_SFT_PD_CNTRL_EN : 0;
0143     ret = phy_write_mmd(phydev, MDIO_MMD_VEND1,
0144                 ADIN_CRSM_SFT_PD_CNTRL, val);
0145     if (ret < 0)
0146         return ret;
0147 
0148     return phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1, ADIN_CRSM_STAT, ret,
0149                      (ret & ADIN_CRSM_SFT_PD_RDY) == val,
0150                      1000, 30000, true);
0151 }
0152 
0153 static int adin_suspend(struct phy_device *phydev)
0154 {
0155     return adin_set_powerdown_mode(phydev, true);
0156 }
0157 
0158 static int adin_resume(struct phy_device *phydev)
0159 {
0160     return adin_set_powerdown_mode(phydev, false);
0161 }
0162 
0163 static int adin_set_loopback(struct phy_device *phydev, bool enable)
0164 {
0165     if (enable)
0166         return phy_set_bits_mmd(phydev, MDIO_MMD_PCS, MDIO_PCS_10T1L_CTRL,
0167                     BMCR_LOOPBACK);
0168 
0169     /* PCS loopback (according to 10BASE-T1L spec) */
0170     return phy_clear_bits_mmd(phydev, MDIO_MMD_PCS, MDIO_PCS_10T1L_CTRL,
0171                  BMCR_LOOPBACK);
0172 }
0173 
0174 static int adin_soft_reset(struct phy_device *phydev)
0175 {
0176     int ret;
0177 
0178     ret = phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, ADIN_CRSM_SFT_RST, ADIN_CRSM_SFT_RST_EN);
0179     if (ret < 0)
0180         return ret;
0181 
0182     return phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1, ADIN_CRSM_STAT, ret,
0183                      (ret & ADIN_CRSM_SYS_RDY),
0184                      10000, 30000, true);
0185 }
0186 
0187 static int adin_get_features(struct phy_device *phydev)
0188 {
0189     struct adin_priv *priv = phydev->priv;
0190     struct device *dev = &phydev->mdio.dev;
0191     int ret;
0192     u8 val;
0193 
0194     ret = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_10T1L_STAT);
0195     if (ret < 0)
0196         return ret;
0197 
0198     /* This depends on the voltage level from the power source */
0199     priv->tx_level_2v4_able = !!(ret & MDIO_PMA_10T1L_STAT_2V4_ABLE);
0200 
0201     phydev_dbg(phydev, "PHY supports 2.4V TX level: %s\n",
0202            priv->tx_level_2v4_able ? "yes" : "no");
0203 
0204     priv->tx_level_prop_present = device_property_present(dev, "phy-10base-t1l-2.4vpp");
0205     if (priv->tx_level_prop_present) {
0206         ret = device_property_read_u8(dev, "phy-10base-t1l-2.4vpp", &val);
0207         if (ret < 0)
0208             return ret;
0209 
0210         priv->tx_level_2v4 = val;
0211         if (!priv->tx_level_2v4 && priv->tx_level_2v4_able)
0212             phydev_info(phydev,
0213                     "PHY supports 2.4V TX level, but disabled via config\n");
0214     }
0215 
0216     linkmode_set_bit_array(phy_basic_ports_array, ARRAY_SIZE(phy_basic_ports_array),
0217                    phydev->supported);
0218 
0219     return genphy_c45_pma_read_abilities(phydev);
0220 }
0221 
0222 static int adin_get_sqi(struct phy_device *phydev)
0223 {
0224     u16 mse_val;
0225     int sqi;
0226     int ret;
0227 
0228     ret = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_STAT1);
0229     if (ret < 0)
0230         return ret;
0231     else if (!(ret & MDIO_STAT1_LSTATUS))
0232         return 0;
0233 
0234     ret = phy_read_mmd(phydev, MDIO_STAT1, ADIN_MSE_VAL);
0235     if (ret < 0)
0236         return ret;
0237 
0238     mse_val = 0xFFFF & ret;
0239     for (sqi = 0; sqi < ARRAY_SIZE(adin_mse_sqi_map); sqi++) {
0240         if (mse_val >= adin_mse_sqi_map[sqi].start && mse_val <= adin_mse_sqi_map[sqi].end)
0241             return sqi;
0242     }
0243 
0244     return -EINVAL;
0245 }
0246 
0247 static int adin_get_sqi_max(struct phy_device *phydev)
0248 {
0249     return ADIN_SQI_MAX;
0250 }
0251 
0252 static int adin_probe(struct phy_device *phydev)
0253 {
0254     struct device *dev = &phydev->mdio.dev;
0255     struct adin_priv *priv;
0256 
0257     priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
0258     if (!priv)
0259         return -ENOMEM;
0260 
0261     phydev->priv = priv;
0262 
0263     return 0;
0264 }
0265 
0266 static struct phy_driver adin_driver[] = {
0267     {
0268         PHY_ID_MATCH_MODEL(PHY_ID_ADIN1100),
0269         .name           = "ADIN1100",
0270         .get_features       = adin_get_features,
0271         .soft_reset     = adin_soft_reset,
0272         .probe          = adin_probe,
0273         .config_aneg        = adin_config_aneg,
0274         .read_status        = adin_read_status,
0275         .set_loopback       = adin_set_loopback,
0276         .suspend        = adin_suspend,
0277         .resume         = adin_resume,
0278         .get_sqi        = adin_get_sqi,
0279         .get_sqi_max        = adin_get_sqi_max,
0280     },
0281 };
0282 
0283 module_phy_driver(adin_driver);
0284 
0285 static struct mdio_device_id __maybe_unused adin_tbl[] = {
0286     { PHY_ID_MATCH_MODEL(PHY_ID_ADIN1100) },
0287     { }
0288 };
0289 
0290 MODULE_DEVICE_TABLE(mdio, adin_tbl);
0291 MODULE_DESCRIPTION("Analog Devices Industrial Ethernet T1L PHY driver");
0292 MODULE_LICENSE("Dual BSD/GPL");