Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /* Broadcom BCM54140 Quad SGMII/QSGMII Copper/Fiber Gigabit PHY
0003  *
0004  * Copyright (c) 2020 Michael Walle <michael@walle.cc>
0005  */
0006 
0007 #include <linux/bitfield.h>
0008 #include <linux/brcmphy.h>
0009 #include <linux/hwmon.h>
0010 #include <linux/module.h>
0011 #include <linux/phy.h>
0012 
0013 #include "bcm-phy-lib.h"
0014 
0015 /* RDB per-port registers
0016  */
0017 #define BCM54140_RDB_ISR        0x00a   /* interrupt status */
0018 #define BCM54140_RDB_IMR        0x00b   /* interrupt mask */
0019 #define  BCM54140_RDB_INT_LINK      BIT(1)  /* link status changed */
0020 #define  BCM54140_RDB_INT_SPEED     BIT(2)  /* link speed change */
0021 #define  BCM54140_RDB_INT_DUPLEX    BIT(3)  /* duplex mode changed */
0022 #define BCM54140_RDB_SPARE1     0x012   /* spare control 1 */
0023 #define  BCM54140_RDB_SPARE1_LSLM   BIT(2)  /* link speed LED mode */
0024 #define BCM54140_RDB_SPARE2     0x014   /* spare control 2 */
0025 #define  BCM54140_RDB_SPARE2_WS_RTRY_DIS BIT(8) /* wirespeed retry disable */
0026 #define  BCM54140_RDB_SPARE2_WS_RTRY_LIMIT GENMASK(4, 2) /* retry limit */
0027 #define BCM54140_RDB_SPARE3     0x015   /* spare control 3 */
0028 #define  BCM54140_RDB_SPARE3_BIT0   BIT(0)
0029 #define BCM54140_RDB_LED_CTRL       0x019   /* LED control */
0030 #define  BCM54140_RDB_LED_CTRL_ACTLINK0 BIT(4)
0031 #define  BCM54140_RDB_LED_CTRL_ACTLINK1 BIT(8)
0032 #define BCM54140_RDB_C_APWR     0x01a   /* auto power down control */
0033 #define  BCM54140_RDB_C_APWR_SINGLE_PULSE   BIT(8)  /* single pulse */
0034 #define  BCM54140_RDB_C_APWR_APD_MODE_DIS   0 /* ADP disable */
0035 #define  BCM54140_RDB_C_APWR_APD_MODE_EN    1 /* ADP enable */
0036 #define  BCM54140_RDB_C_APWR_APD_MODE_DIS2  2 /* ADP disable */
0037 #define  BCM54140_RDB_C_APWR_APD_MODE_EN_ANEG   3 /* ADP enable w/ aneg */
0038 #define  BCM54140_RDB_C_APWR_APD_MODE_MASK  GENMASK(6, 5)
0039 #define  BCM54140_RDB_C_APWR_SLP_TIM_MASK BIT(4)/* sleep timer */
0040 #define  BCM54140_RDB_C_APWR_SLP_TIM_2_7 0  /* 2.7s */
0041 #define  BCM54140_RDB_C_APWR_SLP_TIM_5_4 1  /* 5.4s */
0042 #define BCM54140_RDB_C_PWR      0x02a   /* copper power control */
0043 #define  BCM54140_RDB_C_PWR_ISOLATE BIT(5)  /* super isolate mode */
0044 #define BCM54140_RDB_C_MISC_CTRL    0x02f   /* misc copper control */
0045 #define  BCM54140_RDB_C_MISC_CTRL_WS_EN BIT(4)  /* wirespeed enable */
0046 
0047 /* RDB global registers
0048  */
0049 #define BCM54140_RDB_TOP_IMR        0x82d   /* interrupt mask */
0050 #define  BCM54140_RDB_TOP_IMR_PORT0 BIT(4)
0051 #define  BCM54140_RDB_TOP_IMR_PORT1 BIT(5)
0052 #define  BCM54140_RDB_TOP_IMR_PORT2 BIT(6)
0053 #define  BCM54140_RDB_TOP_IMR_PORT3 BIT(7)
0054 #define BCM54140_RDB_MON_CTRL       0x831   /* monitor control */
0055 #define  BCM54140_RDB_MON_CTRL_V_MODE   BIT(3)  /* voltage mode */
0056 #define  BCM54140_RDB_MON_CTRL_SEL_MASK GENMASK(2, 1)
0057 #define  BCM54140_RDB_MON_CTRL_SEL_TEMP 0   /* meassure temperature */
0058 #define  BCM54140_RDB_MON_CTRL_SEL_1V0  1   /* meassure AVDDL 1.0V */
0059 #define  BCM54140_RDB_MON_CTRL_SEL_3V3  2   /* meassure AVDDH 3.3V */
0060 #define  BCM54140_RDB_MON_CTRL_SEL_RR   3   /* meassure all round-robin */
0061 #define  BCM54140_RDB_MON_CTRL_PWR_DOWN BIT(0)  /* power-down monitor */
0062 #define BCM54140_RDB_MON_TEMP_VAL   0x832   /* temperature value */
0063 #define BCM54140_RDB_MON_TEMP_MAX   0x833   /* temperature high thresh */
0064 #define BCM54140_RDB_MON_TEMP_MIN   0x834   /* temperature low thresh */
0065 #define  BCM54140_RDB_MON_TEMP_DATA_MASK GENMASK(9, 0)
0066 #define BCM54140_RDB_MON_1V0_VAL    0x835   /* AVDDL 1.0V value */
0067 #define BCM54140_RDB_MON_1V0_MAX    0x836   /* AVDDL 1.0V high thresh */
0068 #define BCM54140_RDB_MON_1V0_MIN    0x837   /* AVDDL 1.0V low thresh */
0069 #define  BCM54140_RDB_MON_1V0_DATA_MASK GENMASK(10, 0)
0070 #define BCM54140_RDB_MON_3V3_VAL    0x838   /* AVDDH 3.3V value */
0071 #define BCM54140_RDB_MON_3V3_MAX    0x839   /* AVDDH 3.3V high thresh */
0072 #define BCM54140_RDB_MON_3V3_MIN    0x83a   /* AVDDH 3.3V low thresh */
0073 #define  BCM54140_RDB_MON_3V3_DATA_MASK GENMASK(11, 0)
0074 #define BCM54140_RDB_MON_ISR        0x83b   /* interrupt status */
0075 #define  BCM54140_RDB_MON_ISR_3V3   BIT(2)  /* AVDDH 3.3V alarm */
0076 #define  BCM54140_RDB_MON_ISR_1V0   BIT(1)  /* AVDDL 1.0V alarm */
0077 #define  BCM54140_RDB_MON_ISR_TEMP  BIT(0)  /* temperature alarm */
0078 
0079 /* According to the datasheet the formula is:
0080  *   T = 413.35 - (0.49055 * bits[9:0])
0081  */
0082 #define BCM54140_HWMON_TO_TEMP(v) (413350L - (v) * 491)
0083 #define BCM54140_HWMON_FROM_TEMP(v) DIV_ROUND_CLOSEST_ULL(413350L - (v), 491)
0084 
0085 /* According to the datasheet the formula is:
0086  *   U = bits[11:0] / 1024 * 220 / 0.2
0087  *
0088  * Normalized:
0089  *   U = bits[11:0] / 4096 * 2514
0090  */
0091 #define BCM54140_HWMON_TO_IN_1V0(v) ((v) * 2514 >> 11)
0092 #define BCM54140_HWMON_FROM_IN_1V0(v) DIV_ROUND_CLOSEST_ULL(((v) << 11), 2514)
0093 
0094 /* According to the datasheet the formula is:
0095  *   U = bits[10:0] / 1024 * 880 / 0.7
0096  *
0097  * Normalized:
0098  *   U = bits[10:0] / 2048 * 4400
0099  */
0100 #define BCM54140_HWMON_TO_IN_3V3(v) ((v) * 4400 >> 12)
0101 #define BCM54140_HWMON_FROM_IN_3V3(v) DIV_ROUND_CLOSEST_ULL(((v) << 12), 4400)
0102 
0103 #define BCM54140_HWMON_TO_IN(ch, v) ((ch) ? BCM54140_HWMON_TO_IN_3V3(v) \
0104                       : BCM54140_HWMON_TO_IN_1V0(v))
0105 #define BCM54140_HWMON_FROM_IN(ch, v) ((ch) ? BCM54140_HWMON_FROM_IN_3V3(v) \
0106                         : BCM54140_HWMON_FROM_IN_1V0(v))
0107 #define BCM54140_HWMON_IN_MASK(ch) ((ch) ? BCM54140_RDB_MON_3V3_DATA_MASK \
0108                      : BCM54140_RDB_MON_1V0_DATA_MASK)
0109 #define BCM54140_HWMON_IN_VAL_REG(ch) ((ch) ? BCM54140_RDB_MON_3V3_VAL \
0110                         : BCM54140_RDB_MON_1V0_VAL)
0111 #define BCM54140_HWMON_IN_MIN_REG(ch) ((ch) ? BCM54140_RDB_MON_3V3_MIN \
0112                         : BCM54140_RDB_MON_1V0_MIN)
0113 #define BCM54140_HWMON_IN_MAX_REG(ch) ((ch) ? BCM54140_RDB_MON_3V3_MAX \
0114                         : BCM54140_RDB_MON_1V0_MAX)
0115 #define BCM54140_HWMON_IN_ALARM_BIT(ch) ((ch) ? BCM54140_RDB_MON_ISR_3V3 \
0116                           : BCM54140_RDB_MON_ISR_1V0)
0117 
0118 /* This PHY has two different PHY IDs depening on its MODE_SEL pin. This
0119  * pin choses between 4x SGMII and QSGMII mode:
0120  *   AE02_5009 4x SGMII
0121  *   AE02_5019 QSGMII
0122  */
0123 #define BCM54140_PHY_ID_MASK    0xffffffe8
0124 
0125 #define BCM54140_PHY_ID_REV(phy_id) ((phy_id) & 0x7)
0126 #define BCM54140_REV_B0         1
0127 
0128 #define BCM54140_DEFAULT_DOWNSHIFT 5
0129 #define BCM54140_MAX_DOWNSHIFT 9
0130 
0131 struct bcm54140_priv {
0132     int port;
0133     int base_addr;
0134 #if IS_ENABLED(CONFIG_HWMON)
0135     /* protect the alarm bits */
0136     struct mutex alarm_lock;
0137     u16 alarm;
0138 #endif
0139 };
0140 
0141 #if IS_ENABLED(CONFIG_HWMON)
0142 static umode_t bcm54140_hwmon_is_visible(const void *data,
0143                      enum hwmon_sensor_types type,
0144                      u32 attr, int channel)
0145 {
0146     switch (type) {
0147     case hwmon_in:
0148         switch (attr) {
0149         case hwmon_in_min:
0150         case hwmon_in_max:
0151             return 0644;
0152         case hwmon_in_label:
0153         case hwmon_in_input:
0154         case hwmon_in_alarm:
0155             return 0444;
0156         default:
0157             return 0;
0158         }
0159     case hwmon_temp:
0160         switch (attr) {
0161         case hwmon_temp_min:
0162         case hwmon_temp_max:
0163             return 0644;
0164         case hwmon_temp_input:
0165         case hwmon_temp_alarm:
0166             return 0444;
0167         default:
0168             return 0;
0169         }
0170     default:
0171         return 0;
0172     }
0173 }
0174 
0175 static int bcm54140_hwmon_read_alarm(struct device *dev, unsigned int bit,
0176                      long *val)
0177 {
0178     struct phy_device *phydev = dev_get_drvdata(dev);
0179     struct bcm54140_priv *priv = phydev->priv;
0180     int tmp, ret = 0;
0181 
0182     mutex_lock(&priv->alarm_lock);
0183 
0184     /* latch any alarm bits */
0185     tmp = bcm_phy_read_rdb(phydev, BCM54140_RDB_MON_ISR);
0186     if (tmp < 0) {
0187         ret = tmp;
0188         goto out;
0189     }
0190     priv->alarm |= tmp;
0191 
0192     *val = !!(priv->alarm & bit);
0193     priv->alarm &= ~bit;
0194 
0195 out:
0196     mutex_unlock(&priv->alarm_lock);
0197     return ret;
0198 }
0199 
0200 static int bcm54140_hwmon_read_temp(struct device *dev, u32 attr, long *val)
0201 {
0202     struct phy_device *phydev = dev_get_drvdata(dev);
0203     u16 reg;
0204     int tmp;
0205 
0206     switch (attr) {
0207     case hwmon_temp_input:
0208         reg = BCM54140_RDB_MON_TEMP_VAL;
0209         break;
0210     case hwmon_temp_min:
0211         reg = BCM54140_RDB_MON_TEMP_MIN;
0212         break;
0213     case hwmon_temp_max:
0214         reg = BCM54140_RDB_MON_TEMP_MAX;
0215         break;
0216     case hwmon_temp_alarm:
0217         return bcm54140_hwmon_read_alarm(dev,
0218                          BCM54140_RDB_MON_ISR_TEMP,
0219                          val);
0220     default:
0221         return -EOPNOTSUPP;
0222     }
0223 
0224     tmp = bcm_phy_read_rdb(phydev, reg);
0225     if (tmp < 0)
0226         return tmp;
0227 
0228     *val = BCM54140_HWMON_TO_TEMP(tmp & BCM54140_RDB_MON_TEMP_DATA_MASK);
0229 
0230     return 0;
0231 }
0232 
0233 static int bcm54140_hwmon_read_in(struct device *dev, u32 attr,
0234                   int channel, long *val)
0235 {
0236     struct phy_device *phydev = dev_get_drvdata(dev);
0237     u16 bit, reg;
0238     int tmp;
0239 
0240     switch (attr) {
0241     case hwmon_in_input:
0242         reg = BCM54140_HWMON_IN_VAL_REG(channel);
0243         break;
0244     case hwmon_in_min:
0245         reg = BCM54140_HWMON_IN_MIN_REG(channel);
0246         break;
0247     case hwmon_in_max:
0248         reg = BCM54140_HWMON_IN_MAX_REG(channel);
0249         break;
0250     case hwmon_in_alarm:
0251         bit = BCM54140_HWMON_IN_ALARM_BIT(channel);
0252         return bcm54140_hwmon_read_alarm(dev, bit, val);
0253     default:
0254         return -EOPNOTSUPP;
0255     }
0256 
0257     tmp = bcm_phy_read_rdb(phydev, reg);
0258     if (tmp < 0)
0259         return tmp;
0260 
0261     tmp &= BCM54140_HWMON_IN_MASK(channel);
0262     *val = BCM54140_HWMON_TO_IN(channel, tmp);
0263 
0264     return 0;
0265 }
0266 
0267 static int bcm54140_hwmon_read(struct device *dev,
0268                    enum hwmon_sensor_types type, u32 attr,
0269                    int channel, long *val)
0270 {
0271     switch (type) {
0272     case hwmon_temp:
0273         return bcm54140_hwmon_read_temp(dev, attr, val);
0274     case hwmon_in:
0275         return bcm54140_hwmon_read_in(dev, attr, channel, val);
0276     default:
0277         return -EOPNOTSUPP;
0278     }
0279 }
0280 
0281 static const char *const bcm54140_hwmon_in_labels[] = {
0282     "AVDDL",
0283     "AVDDH",
0284 };
0285 
0286 static int bcm54140_hwmon_read_string(struct device *dev,
0287                       enum hwmon_sensor_types type, u32 attr,
0288                       int channel, const char **str)
0289 {
0290     switch (type) {
0291     case hwmon_in:
0292         switch (attr) {
0293         case hwmon_in_label:
0294             *str = bcm54140_hwmon_in_labels[channel];
0295             return 0;
0296         default:
0297             return -EOPNOTSUPP;
0298         }
0299     default:
0300         return -EOPNOTSUPP;
0301     }
0302 }
0303 
0304 static int bcm54140_hwmon_write_temp(struct device *dev, u32 attr,
0305                      int channel, long val)
0306 {
0307     struct phy_device *phydev = dev_get_drvdata(dev);
0308     u16 mask = BCM54140_RDB_MON_TEMP_DATA_MASK;
0309     u16 reg;
0310 
0311     val = clamp_val(val, BCM54140_HWMON_TO_TEMP(mask),
0312             BCM54140_HWMON_TO_TEMP(0));
0313 
0314     switch (attr) {
0315     case hwmon_temp_min:
0316         reg = BCM54140_RDB_MON_TEMP_MIN;
0317         break;
0318     case hwmon_temp_max:
0319         reg = BCM54140_RDB_MON_TEMP_MAX;
0320         break;
0321     default:
0322         return -EOPNOTSUPP;
0323     }
0324 
0325     return bcm_phy_modify_rdb(phydev, reg, mask,
0326                   BCM54140_HWMON_FROM_TEMP(val));
0327 }
0328 
0329 static int bcm54140_hwmon_write_in(struct device *dev, u32 attr,
0330                    int channel, long val)
0331 {
0332     struct phy_device *phydev = dev_get_drvdata(dev);
0333     u16 mask = BCM54140_HWMON_IN_MASK(channel);
0334     u16 reg;
0335 
0336     val = clamp_val(val, 0, BCM54140_HWMON_TO_IN(channel, mask));
0337 
0338     switch (attr) {
0339     case hwmon_in_min:
0340         reg = BCM54140_HWMON_IN_MIN_REG(channel);
0341         break;
0342     case hwmon_in_max:
0343         reg = BCM54140_HWMON_IN_MAX_REG(channel);
0344         break;
0345     default:
0346         return -EOPNOTSUPP;
0347     }
0348 
0349     return bcm_phy_modify_rdb(phydev, reg, mask,
0350                   BCM54140_HWMON_FROM_IN(channel, val));
0351 }
0352 
0353 static int bcm54140_hwmon_write(struct device *dev,
0354                 enum hwmon_sensor_types type, u32 attr,
0355                 int channel, long val)
0356 {
0357     switch (type) {
0358     case hwmon_temp:
0359         return bcm54140_hwmon_write_temp(dev, attr, channel, val);
0360     case hwmon_in:
0361         return bcm54140_hwmon_write_in(dev, attr, channel, val);
0362     default:
0363         return -EOPNOTSUPP;
0364     }
0365 }
0366 
0367 static const struct hwmon_channel_info *bcm54140_hwmon_info[] = {
0368     HWMON_CHANNEL_INFO(temp,
0369                HWMON_T_INPUT | HWMON_T_MIN | HWMON_T_MAX |
0370                HWMON_T_ALARM),
0371     HWMON_CHANNEL_INFO(in,
0372                HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX |
0373                HWMON_I_ALARM | HWMON_I_LABEL,
0374                HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX |
0375                HWMON_I_ALARM | HWMON_I_LABEL),
0376     NULL
0377 };
0378 
0379 static const struct hwmon_ops bcm54140_hwmon_ops = {
0380     .is_visible = bcm54140_hwmon_is_visible,
0381     .read = bcm54140_hwmon_read,
0382     .read_string = bcm54140_hwmon_read_string,
0383     .write = bcm54140_hwmon_write,
0384 };
0385 
0386 static const struct hwmon_chip_info bcm54140_chip_info = {
0387     .ops = &bcm54140_hwmon_ops,
0388     .info = bcm54140_hwmon_info,
0389 };
0390 
0391 static int bcm54140_enable_monitoring(struct phy_device *phydev)
0392 {
0393     u16 mask, set;
0394 
0395     /* 3.3V voltage mode */
0396     set = BCM54140_RDB_MON_CTRL_V_MODE;
0397 
0398     /* select round-robin */
0399     mask = BCM54140_RDB_MON_CTRL_SEL_MASK;
0400     set |= FIELD_PREP(BCM54140_RDB_MON_CTRL_SEL_MASK,
0401               BCM54140_RDB_MON_CTRL_SEL_RR);
0402 
0403     /* remove power-down bit */
0404     mask |= BCM54140_RDB_MON_CTRL_PWR_DOWN;
0405 
0406     return bcm_phy_modify_rdb(phydev, BCM54140_RDB_MON_CTRL, mask, set);
0407 }
0408 
0409 static int bcm54140_probe_once(struct phy_device *phydev)
0410 {
0411     struct device *hwmon;
0412     int ret;
0413 
0414     /* enable hardware monitoring */
0415     ret = bcm54140_enable_monitoring(phydev);
0416     if (ret)
0417         return ret;
0418 
0419     hwmon = devm_hwmon_device_register_with_info(&phydev->mdio.dev,
0420                              "BCM54140", phydev,
0421                              &bcm54140_chip_info,
0422                              NULL);
0423     return PTR_ERR_OR_ZERO(hwmon);
0424 }
0425 #endif
0426 
0427 static int bcm54140_base_read_rdb(struct phy_device *phydev, u16 rdb)
0428 {
0429     int ret;
0430 
0431     phy_lock_mdio_bus(phydev);
0432     ret = __phy_package_write(phydev, MII_BCM54XX_RDB_ADDR, rdb);
0433     if (ret < 0)
0434         goto out;
0435 
0436     ret = __phy_package_read(phydev, MII_BCM54XX_RDB_DATA);
0437 
0438 out:
0439     phy_unlock_mdio_bus(phydev);
0440     return ret;
0441 }
0442 
0443 static int bcm54140_base_write_rdb(struct phy_device *phydev,
0444                    u16 rdb, u16 val)
0445 {
0446     int ret;
0447 
0448     phy_lock_mdio_bus(phydev);
0449     ret = __phy_package_write(phydev, MII_BCM54XX_RDB_ADDR, rdb);
0450     if (ret < 0)
0451         goto out;
0452 
0453     ret = __phy_package_write(phydev, MII_BCM54XX_RDB_DATA, val);
0454 
0455 out:
0456     phy_unlock_mdio_bus(phydev);
0457     return ret;
0458 }
0459 
0460 /* Under some circumstances a core PLL may not lock, this will then prevent
0461  * a successful link establishment. Restart the PLL after the voltages are
0462  * stable to workaround this issue.
0463  */
0464 static int bcm54140_b0_workaround(struct phy_device *phydev)
0465 {
0466     int spare3;
0467     int ret;
0468 
0469     spare3 = bcm_phy_read_rdb(phydev, BCM54140_RDB_SPARE3);
0470     if (spare3 < 0)
0471         return spare3;
0472 
0473     spare3 &= ~BCM54140_RDB_SPARE3_BIT0;
0474 
0475     ret = bcm_phy_write_rdb(phydev, BCM54140_RDB_SPARE3, spare3);
0476     if (ret)
0477         return ret;
0478 
0479     ret = phy_modify(phydev, MII_BMCR, 0, BMCR_PDOWN);
0480     if (ret)
0481         return ret;
0482 
0483     ret = phy_modify(phydev, MII_BMCR, BMCR_PDOWN, 0);
0484     if (ret)
0485         return ret;
0486 
0487     spare3 |= BCM54140_RDB_SPARE3_BIT0;
0488 
0489     return bcm_phy_write_rdb(phydev, BCM54140_RDB_SPARE3, spare3);
0490 }
0491 
0492 /* The BCM54140 is a quad PHY where only the first port has access to the
0493  * global register. Thus we need to find out its PHY address.
0494  *
0495  */
0496 static int bcm54140_get_base_addr_and_port(struct phy_device *phydev)
0497 {
0498     struct bcm54140_priv *priv = phydev->priv;
0499     struct mii_bus *bus = phydev->mdio.bus;
0500     int addr, min_addr, max_addr;
0501     int step = 1;
0502     u32 phy_id;
0503     int tmp;
0504 
0505     min_addr = phydev->mdio.addr;
0506     max_addr = phydev->mdio.addr;
0507     addr = phydev->mdio.addr;
0508 
0509     /* We scan forward and backwards and look for PHYs which have the
0510      * same phy_id like we do. Step 1 will scan forward, step 2
0511      * backwards. Once we are finished, we have a min_addr and
0512      * max_addr which resembles the range of PHY addresses of the same
0513      * type of PHY. There is one caveat; there may be many PHYs of
0514      * the same type, but we know that each PHY takes exactly 4
0515      * consecutive addresses. Therefore we can deduce our offset
0516      * to the base address of this quad PHY.
0517      */
0518 
0519     while (1) {
0520         if (step == 3) {
0521             break;
0522         } else if (step == 1) {
0523             max_addr = addr;
0524             addr++;
0525         } else {
0526             min_addr = addr;
0527             addr--;
0528         }
0529 
0530         if (addr < 0 || addr >= PHY_MAX_ADDR) {
0531             addr = phydev->mdio.addr;
0532             step++;
0533             continue;
0534         }
0535 
0536         /* read the PHY id */
0537         tmp = mdiobus_read(bus, addr, MII_PHYSID1);
0538         if (tmp < 0)
0539             return tmp;
0540         phy_id = tmp << 16;
0541         tmp = mdiobus_read(bus, addr, MII_PHYSID2);
0542         if (tmp < 0)
0543             return tmp;
0544         phy_id |= tmp;
0545 
0546         /* see if it is still the same PHY */
0547         if ((phy_id & phydev->drv->phy_id_mask) !=
0548             (phydev->drv->phy_id & phydev->drv->phy_id_mask)) {
0549             addr = phydev->mdio.addr;
0550             step++;
0551         }
0552     }
0553 
0554     /* The range we get should be a multiple of four. Please note that both
0555      * the min_addr and max_addr are inclusive. So we have to add one if we
0556      * subtract them.
0557      */
0558     if ((max_addr - min_addr + 1) % 4) {
0559         dev_err(&phydev->mdio.dev,
0560             "Detected Quad PHY IDs %d..%d doesn't make sense.\n",
0561             min_addr, max_addr);
0562         return -EINVAL;
0563     }
0564 
0565     priv->port = (phydev->mdio.addr - min_addr) % 4;
0566     priv->base_addr = phydev->mdio.addr - priv->port;
0567 
0568     return 0;
0569 }
0570 
0571 static int bcm54140_probe(struct phy_device *phydev)
0572 {
0573     struct bcm54140_priv *priv;
0574     int ret;
0575 
0576     priv = devm_kzalloc(&phydev->mdio.dev, sizeof(*priv), GFP_KERNEL);
0577     if (!priv)
0578         return -ENOMEM;
0579 
0580     phydev->priv = priv;
0581 
0582     ret = bcm54140_get_base_addr_and_port(phydev);
0583     if (ret)
0584         return ret;
0585 
0586     devm_phy_package_join(&phydev->mdio.dev, phydev, priv->base_addr, 0);
0587 
0588 #if IS_ENABLED(CONFIG_HWMON)
0589     mutex_init(&priv->alarm_lock);
0590 
0591     if (phy_package_init_once(phydev)) {
0592         ret = bcm54140_probe_once(phydev);
0593         if (ret)
0594             return ret;
0595     }
0596 #endif
0597 
0598     phydev_dbg(phydev, "probed (port %d, base PHY address %d)\n",
0599            priv->port, priv->base_addr);
0600 
0601     return 0;
0602 }
0603 
0604 static int bcm54140_config_init(struct phy_device *phydev)
0605 {
0606     u16 reg = 0xffff;
0607     int ret;
0608 
0609     /* Apply hardware errata */
0610     if (BCM54140_PHY_ID_REV(phydev->phy_id) == BCM54140_REV_B0) {
0611         ret = bcm54140_b0_workaround(phydev);
0612         if (ret)
0613             return ret;
0614     }
0615 
0616     /* Unmask events we are interested in. */
0617     reg &= ~(BCM54140_RDB_INT_DUPLEX |
0618          BCM54140_RDB_INT_SPEED |
0619          BCM54140_RDB_INT_LINK);
0620     ret = bcm_phy_write_rdb(phydev, BCM54140_RDB_IMR, reg);
0621     if (ret)
0622         return ret;
0623 
0624     /* LED1=LINKSPD[1], LED2=LINKSPD[2], LED3=LINK/ACTIVITY */
0625     ret = bcm_phy_modify_rdb(phydev, BCM54140_RDB_SPARE1,
0626                  0, BCM54140_RDB_SPARE1_LSLM);
0627     if (ret)
0628         return ret;
0629 
0630     ret = bcm_phy_modify_rdb(phydev, BCM54140_RDB_LED_CTRL,
0631                  0, BCM54140_RDB_LED_CTRL_ACTLINK0);
0632     if (ret)
0633         return ret;
0634 
0635     /* disable super isolate mode */
0636     return bcm_phy_modify_rdb(phydev, BCM54140_RDB_C_PWR,
0637                   BCM54140_RDB_C_PWR_ISOLATE, 0);
0638 }
0639 
0640 static irqreturn_t bcm54140_handle_interrupt(struct phy_device *phydev)
0641 {
0642     int irq_status, irq_mask;
0643 
0644     irq_status = bcm_phy_read_rdb(phydev, BCM54140_RDB_ISR);
0645     if (irq_status < 0) {
0646         phy_error(phydev);
0647         return IRQ_NONE;
0648     }
0649 
0650     irq_mask = bcm_phy_read_rdb(phydev, BCM54140_RDB_IMR);
0651     if (irq_mask < 0) {
0652         phy_error(phydev);
0653         return IRQ_NONE;
0654     }
0655     irq_mask = ~irq_mask;
0656 
0657     if (!(irq_status & irq_mask))
0658         return IRQ_NONE;
0659 
0660     phy_trigger_machine(phydev);
0661 
0662     return IRQ_HANDLED;
0663 }
0664 
0665 static int bcm54140_ack_intr(struct phy_device *phydev)
0666 {
0667     int reg;
0668 
0669     /* clear pending interrupts */
0670     reg = bcm_phy_read_rdb(phydev, BCM54140_RDB_ISR);
0671     if (reg < 0)
0672         return reg;
0673 
0674     return 0;
0675 }
0676 
0677 static int bcm54140_config_intr(struct phy_device *phydev)
0678 {
0679     struct bcm54140_priv *priv = phydev->priv;
0680     static const u16 port_to_imr_bit[] = {
0681         BCM54140_RDB_TOP_IMR_PORT0, BCM54140_RDB_TOP_IMR_PORT1,
0682         BCM54140_RDB_TOP_IMR_PORT2, BCM54140_RDB_TOP_IMR_PORT3,
0683     };
0684     int reg, err;
0685 
0686     if (priv->port >= ARRAY_SIZE(port_to_imr_bit))
0687         return -EINVAL;
0688 
0689     reg = bcm54140_base_read_rdb(phydev, BCM54140_RDB_TOP_IMR);
0690     if (reg < 0)
0691         return reg;
0692 
0693     if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
0694         err = bcm54140_ack_intr(phydev);
0695         if (err)
0696             return err;
0697 
0698         reg &= ~port_to_imr_bit[priv->port];
0699         err = bcm54140_base_write_rdb(phydev, BCM54140_RDB_TOP_IMR, reg);
0700     } else {
0701         reg |= port_to_imr_bit[priv->port];
0702         err = bcm54140_base_write_rdb(phydev, BCM54140_RDB_TOP_IMR, reg);
0703         if (err)
0704             return err;
0705 
0706         err = bcm54140_ack_intr(phydev);
0707     }
0708 
0709     return err;
0710 }
0711 
0712 static int bcm54140_get_downshift(struct phy_device *phydev, u8 *data)
0713 {
0714     int val;
0715 
0716     val = bcm_phy_read_rdb(phydev, BCM54140_RDB_C_MISC_CTRL);
0717     if (val < 0)
0718         return val;
0719 
0720     if (!(val & BCM54140_RDB_C_MISC_CTRL_WS_EN)) {
0721         *data = DOWNSHIFT_DEV_DISABLE;
0722         return 0;
0723     }
0724 
0725     val = bcm_phy_read_rdb(phydev, BCM54140_RDB_SPARE2);
0726     if (val < 0)
0727         return val;
0728 
0729     if (val & BCM54140_RDB_SPARE2_WS_RTRY_DIS)
0730         *data = 1;
0731     else
0732         *data = FIELD_GET(BCM54140_RDB_SPARE2_WS_RTRY_LIMIT, val) + 2;
0733 
0734     return 0;
0735 }
0736 
0737 static int bcm54140_set_downshift(struct phy_device *phydev, u8 cnt)
0738 {
0739     u16 mask, set;
0740     int ret;
0741 
0742     if (cnt > BCM54140_MAX_DOWNSHIFT && cnt != DOWNSHIFT_DEV_DEFAULT_COUNT)
0743         return -EINVAL;
0744 
0745     if (!cnt)
0746         return bcm_phy_modify_rdb(phydev, BCM54140_RDB_C_MISC_CTRL,
0747                       BCM54140_RDB_C_MISC_CTRL_WS_EN, 0);
0748 
0749     if (cnt == DOWNSHIFT_DEV_DEFAULT_COUNT)
0750         cnt = BCM54140_DEFAULT_DOWNSHIFT;
0751 
0752     if (cnt == 1) {
0753         mask = 0;
0754         set = BCM54140_RDB_SPARE2_WS_RTRY_DIS;
0755     } else {
0756         mask = BCM54140_RDB_SPARE2_WS_RTRY_DIS;
0757         mask |= BCM54140_RDB_SPARE2_WS_RTRY_LIMIT;
0758         set = FIELD_PREP(BCM54140_RDB_SPARE2_WS_RTRY_LIMIT, cnt - 2);
0759     }
0760     ret = bcm_phy_modify_rdb(phydev, BCM54140_RDB_SPARE2,
0761                  mask, set);
0762     if (ret)
0763         return ret;
0764 
0765     return bcm_phy_modify_rdb(phydev, BCM54140_RDB_C_MISC_CTRL,
0766                   0, BCM54140_RDB_C_MISC_CTRL_WS_EN);
0767 }
0768 
0769 static int bcm54140_get_edpd(struct phy_device *phydev, u16 *tx_interval)
0770 {
0771     int val;
0772 
0773     val = bcm_phy_read_rdb(phydev, BCM54140_RDB_C_APWR);
0774     if (val < 0)
0775         return val;
0776 
0777     switch (FIELD_GET(BCM54140_RDB_C_APWR_APD_MODE_MASK, val)) {
0778     case BCM54140_RDB_C_APWR_APD_MODE_DIS:
0779     case BCM54140_RDB_C_APWR_APD_MODE_DIS2:
0780         *tx_interval = ETHTOOL_PHY_EDPD_DISABLE;
0781         break;
0782     case BCM54140_RDB_C_APWR_APD_MODE_EN:
0783     case BCM54140_RDB_C_APWR_APD_MODE_EN_ANEG:
0784         switch (FIELD_GET(BCM54140_RDB_C_APWR_SLP_TIM_MASK, val)) {
0785         case BCM54140_RDB_C_APWR_SLP_TIM_2_7:
0786             *tx_interval = 2700;
0787             break;
0788         case BCM54140_RDB_C_APWR_SLP_TIM_5_4:
0789             *tx_interval = 5400;
0790             break;
0791         }
0792     }
0793 
0794     return 0;
0795 }
0796 
0797 static int bcm54140_set_edpd(struct phy_device *phydev, u16 tx_interval)
0798 {
0799     u16 mask, set;
0800 
0801     mask = BCM54140_RDB_C_APWR_APD_MODE_MASK;
0802     if (tx_interval == ETHTOOL_PHY_EDPD_DISABLE)
0803         set = FIELD_PREP(BCM54140_RDB_C_APWR_APD_MODE_MASK,
0804                  BCM54140_RDB_C_APWR_APD_MODE_DIS);
0805     else
0806         set = FIELD_PREP(BCM54140_RDB_C_APWR_APD_MODE_MASK,
0807                  BCM54140_RDB_C_APWR_APD_MODE_EN_ANEG);
0808 
0809     /* enable single pulse mode */
0810     set |= BCM54140_RDB_C_APWR_SINGLE_PULSE;
0811 
0812     /* set sleep timer */
0813     mask |= BCM54140_RDB_C_APWR_SLP_TIM_MASK;
0814     switch (tx_interval) {
0815     case ETHTOOL_PHY_EDPD_DFLT_TX_MSECS:
0816     case ETHTOOL_PHY_EDPD_DISABLE:
0817     case 2700:
0818         set |= BCM54140_RDB_C_APWR_SLP_TIM_2_7;
0819         break;
0820     case 5400:
0821         set |= BCM54140_RDB_C_APWR_SLP_TIM_5_4;
0822         break;
0823     default:
0824         return -EINVAL;
0825     }
0826 
0827     return bcm_phy_modify_rdb(phydev, BCM54140_RDB_C_APWR, mask, set);
0828 }
0829 
0830 static int bcm54140_get_tunable(struct phy_device *phydev,
0831                 struct ethtool_tunable *tuna, void *data)
0832 {
0833     switch (tuna->id) {
0834     case ETHTOOL_PHY_DOWNSHIFT:
0835         return bcm54140_get_downshift(phydev, data);
0836     case ETHTOOL_PHY_EDPD:
0837         return bcm54140_get_edpd(phydev, data);
0838     default:
0839         return -EOPNOTSUPP;
0840     }
0841 }
0842 
0843 static int bcm54140_set_tunable(struct phy_device *phydev,
0844                 struct ethtool_tunable *tuna, const void *data)
0845 {
0846     switch (tuna->id) {
0847     case ETHTOOL_PHY_DOWNSHIFT:
0848         return bcm54140_set_downshift(phydev, *(const u8 *)data);
0849     case ETHTOOL_PHY_EDPD:
0850         return bcm54140_set_edpd(phydev, *(const u16 *)data);
0851     default:
0852         return -EOPNOTSUPP;
0853     }
0854 }
0855 
0856 static struct phy_driver bcm54140_drivers[] = {
0857     {
0858         .phy_id         = PHY_ID_BCM54140,
0859         .phy_id_mask    = BCM54140_PHY_ID_MASK,
0860         .name           = "Broadcom BCM54140",
0861         .flags      = PHY_POLL_CABLE_TEST,
0862         .features       = PHY_GBIT_FEATURES,
0863         .config_init    = bcm54140_config_init,
0864         .handle_interrupt = bcm54140_handle_interrupt,
0865         .config_intr    = bcm54140_config_intr,
0866         .probe      = bcm54140_probe,
0867         .suspend    = genphy_suspend,
0868         .resume     = genphy_resume,
0869         .soft_reset = genphy_soft_reset,
0870         .get_tunable    = bcm54140_get_tunable,
0871         .set_tunable    = bcm54140_set_tunable,
0872         .cable_test_start = bcm_phy_cable_test_start_rdb,
0873         .cable_test_get_status = bcm_phy_cable_test_get_status_rdb,
0874     },
0875 };
0876 module_phy_driver(bcm54140_drivers);
0877 
0878 static struct mdio_device_id __maybe_unused bcm54140_tbl[] = {
0879     { PHY_ID_BCM54140, BCM54140_PHY_ID_MASK },
0880     { }
0881 };
0882 
0883 MODULE_AUTHOR("Michael Walle");
0884 MODULE_DESCRIPTION("Broadcom BCM54140 PHY driver");
0885 MODULE_DEVICE_TABLE(mdio, bcm54140_tbl);
0886 MODULE_LICENSE("GPL");