0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #include <linux/clk.h>
0016 #include <linux/kernel.h>
0017 #include <linux/module.h>
0018 #include <linux/mii.h>
0019 #include <linux/ethtool.h>
0020 #include <linux/of.h>
0021 #include <linux/phy.h>
0022 #include <linux/netdevice.h>
0023 #include <linux/smscphy.h>
0024
0025
0026
0027 #define PHY_EDPD_CONFIG 16
0028 #define PHY_EDPD_CONFIG_EXT_CROSSOVER_ 0x0001
0029
0030
0031 #define SPECIAL_CTRL_STS 27
0032 #define SPECIAL_CTRL_STS_OVRRD_AMDIX_ 0x8000
0033 #define SPECIAL_CTRL_STS_AMDIX_ENABLE_ 0x4000
0034 #define SPECIAL_CTRL_STS_AMDIX_STATE_ 0x2000
0035
0036 struct smsc_hw_stat {
0037 const char *string;
0038 u8 reg;
0039 u8 bits;
0040 };
0041
0042 static struct smsc_hw_stat smsc_hw_stats[] = {
0043 { "phy_symbol_errors", 26, 16},
0044 };
0045
0046 struct smsc_phy_priv {
0047 u16 intmask;
0048 bool energy_enable;
0049 struct clk *refclk;
0050 };
0051
0052 static int smsc_phy_ack_interrupt(struct phy_device *phydev)
0053 {
0054 int rc = phy_read(phydev, MII_LAN83C185_ISF);
0055
0056 return rc < 0 ? rc : 0;
0057 }
0058
0059 static int smsc_phy_config_intr(struct phy_device *phydev)
0060 {
0061 struct smsc_phy_priv *priv = phydev->priv;
0062 int rc;
0063
0064 if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
0065 rc = smsc_phy_ack_interrupt(phydev);
0066 if (rc)
0067 return rc;
0068
0069 priv->intmask = MII_LAN83C185_ISF_INT4 | MII_LAN83C185_ISF_INT6;
0070 if (priv->energy_enable)
0071 priv->intmask |= MII_LAN83C185_ISF_INT7;
0072
0073 rc = phy_write(phydev, MII_LAN83C185_IM, priv->intmask);
0074 } else {
0075 priv->intmask = 0;
0076
0077 rc = phy_write(phydev, MII_LAN83C185_IM, 0);
0078 if (rc)
0079 return rc;
0080
0081 rc = smsc_phy_ack_interrupt(phydev);
0082 }
0083
0084 return rc < 0 ? rc : 0;
0085 }
0086
0087 static irqreturn_t smsc_phy_handle_interrupt(struct phy_device *phydev)
0088 {
0089 struct smsc_phy_priv *priv = phydev->priv;
0090 int irq_status;
0091
0092 irq_status = phy_read(phydev, MII_LAN83C185_ISF);
0093 if (irq_status < 0) {
0094 if (irq_status != -ENODEV)
0095 phy_error(phydev);
0096
0097 return IRQ_NONE;
0098 }
0099
0100 if (!(irq_status & priv->intmask))
0101 return IRQ_NONE;
0102
0103 phy_trigger_machine(phydev);
0104
0105 return IRQ_HANDLED;
0106 }
0107
0108 static int smsc_phy_config_init(struct phy_device *phydev)
0109 {
0110 struct smsc_phy_priv *priv = phydev->priv;
0111 int rc;
0112
0113 if (!priv->energy_enable || phydev->irq != PHY_POLL)
0114 return 0;
0115
0116 rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS);
0117
0118 if (rc < 0)
0119 return rc;
0120
0121
0122 rc = phy_write(phydev, MII_LAN83C185_CTRL_STATUS,
0123 rc | MII_LAN83C185_EDPWRDOWN);
0124 return rc;
0125 }
0126
0127 static int smsc_phy_reset(struct phy_device *phydev)
0128 {
0129 int rc = phy_read(phydev, MII_LAN83C185_SPECIAL_MODES);
0130 if (rc < 0)
0131 return rc;
0132
0133
0134
0135
0136 if ((rc & MII_LAN83C185_MODE_MASK) == MII_LAN83C185_MODE_POWERDOWN) {
0137
0138 rc |= MII_LAN83C185_MODE_ALL;
0139 phy_write(phydev, MII_LAN83C185_SPECIAL_MODES, rc);
0140 }
0141
0142
0143 return genphy_soft_reset(phydev);
0144 }
0145
0146 static int lan87xx_config_aneg(struct phy_device *phydev)
0147 {
0148 int rc;
0149 int val;
0150
0151 switch (phydev->mdix_ctrl) {
0152 case ETH_TP_MDI:
0153 val = SPECIAL_CTRL_STS_OVRRD_AMDIX_;
0154 break;
0155 case ETH_TP_MDI_X:
0156 val = SPECIAL_CTRL_STS_OVRRD_AMDIX_ |
0157 SPECIAL_CTRL_STS_AMDIX_STATE_;
0158 break;
0159 case ETH_TP_MDI_AUTO:
0160 val = SPECIAL_CTRL_STS_AMDIX_ENABLE_;
0161 break;
0162 default:
0163 return genphy_config_aneg(phydev);
0164 }
0165
0166 rc = phy_read(phydev, SPECIAL_CTRL_STS);
0167 if (rc < 0)
0168 return rc;
0169
0170 rc &= ~(SPECIAL_CTRL_STS_OVRRD_AMDIX_ |
0171 SPECIAL_CTRL_STS_AMDIX_ENABLE_ |
0172 SPECIAL_CTRL_STS_AMDIX_STATE_);
0173 rc |= val;
0174 phy_write(phydev, SPECIAL_CTRL_STS, rc);
0175
0176 phydev->mdix = phydev->mdix_ctrl;
0177 return genphy_config_aneg(phydev);
0178 }
0179
0180 static int lan95xx_config_aneg_ext(struct phy_device *phydev)
0181 {
0182 int rc;
0183
0184 if (phydev->phy_id != 0x0007c0f0)
0185 return lan87xx_config_aneg(phydev);
0186
0187
0188 rc = phy_read(phydev, PHY_EDPD_CONFIG);
0189 if (rc < 0)
0190 return rc;
0191
0192 rc |= PHY_EDPD_CONFIG_EXT_CROSSOVER_;
0193 phy_write(phydev, PHY_EDPD_CONFIG, rc);
0194 return lan87xx_config_aneg(phydev);
0195 }
0196
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208 static int lan87xx_read_status(struct phy_device *phydev)
0209 {
0210 struct smsc_phy_priv *priv = phydev->priv;
0211
0212 int err = genphy_read_status(phydev);
0213
0214 if (!phydev->link && priv->energy_enable && phydev->irq == PHY_POLL) {
0215
0216 int rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS);
0217 if (rc < 0)
0218 return rc;
0219
0220 rc = phy_write(phydev, MII_LAN83C185_CTRL_STATUS,
0221 rc & ~MII_LAN83C185_EDPWRDOWN);
0222 if (rc < 0)
0223 return rc;
0224
0225
0226
0227
0228 read_poll_timeout(phy_read, rc,
0229 rc & MII_LAN83C185_ENERGYON || rc < 0,
0230 10000, 640000, true, phydev,
0231 MII_LAN83C185_CTRL_STATUS);
0232 if (rc < 0)
0233 return rc;
0234
0235
0236 rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS);
0237 if (rc < 0)
0238 return rc;
0239
0240 rc = phy_write(phydev, MII_LAN83C185_CTRL_STATUS,
0241 rc | MII_LAN83C185_EDPWRDOWN);
0242 if (rc < 0)
0243 return rc;
0244 }
0245
0246 return err;
0247 }
0248
0249 static int smsc_get_sset_count(struct phy_device *phydev)
0250 {
0251 return ARRAY_SIZE(smsc_hw_stats);
0252 }
0253
0254 static void smsc_get_strings(struct phy_device *phydev, u8 *data)
0255 {
0256 int i;
0257
0258 for (i = 0; i < ARRAY_SIZE(smsc_hw_stats); i++) {
0259 strncpy(data + i * ETH_GSTRING_LEN,
0260 smsc_hw_stats[i].string, ETH_GSTRING_LEN);
0261 }
0262 }
0263
0264 static u64 smsc_get_stat(struct phy_device *phydev, int i)
0265 {
0266 struct smsc_hw_stat stat = smsc_hw_stats[i];
0267 int val;
0268 u64 ret;
0269
0270 val = phy_read(phydev, stat.reg);
0271 if (val < 0)
0272 ret = U64_MAX;
0273 else
0274 ret = val;
0275
0276 return ret;
0277 }
0278
0279 static void smsc_get_stats(struct phy_device *phydev,
0280 struct ethtool_stats *stats, u64 *data)
0281 {
0282 int i;
0283
0284 for (i = 0; i < ARRAY_SIZE(smsc_hw_stats); i++)
0285 data[i] = smsc_get_stat(phydev, i);
0286 }
0287
0288 static void smsc_phy_remove(struct phy_device *phydev)
0289 {
0290 struct smsc_phy_priv *priv = phydev->priv;
0291
0292 clk_disable_unprepare(priv->refclk);
0293 clk_put(priv->refclk);
0294 }
0295
0296 static int smsc_phy_probe(struct phy_device *phydev)
0297 {
0298 struct device *dev = &phydev->mdio.dev;
0299 struct device_node *of_node = dev->of_node;
0300 struct smsc_phy_priv *priv;
0301 int ret;
0302
0303 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
0304 if (!priv)
0305 return -ENOMEM;
0306
0307 priv->energy_enable = true;
0308
0309 if (of_property_read_bool(of_node, "smsc,disable-energy-detect"))
0310 priv->energy_enable = false;
0311
0312 phydev->priv = priv;
0313
0314
0315 priv->refclk = clk_get_optional(dev, NULL);
0316 if (IS_ERR(priv->refclk))
0317 return dev_err_probe(dev, PTR_ERR(priv->refclk),
0318 "Failed to request clock\n");
0319
0320 ret = clk_prepare_enable(priv->refclk);
0321 if (ret)
0322 return ret;
0323
0324 ret = clk_set_rate(priv->refclk, 50 * 1000 * 1000);
0325 if (ret) {
0326 clk_disable_unprepare(priv->refclk);
0327 return ret;
0328 }
0329
0330 return 0;
0331 }
0332
0333 static struct phy_driver smsc_phy_driver[] = {
0334 {
0335 .phy_id = 0x0007c0a0,
0336 .phy_id_mask = 0xfffffff0,
0337 .name = "SMSC LAN83C185",
0338
0339
0340
0341 .probe = smsc_phy_probe,
0342
0343
0344 .config_init = smsc_phy_config_init,
0345 .soft_reset = smsc_phy_reset,
0346
0347
0348 .config_intr = smsc_phy_config_intr,
0349 .handle_interrupt = smsc_phy_handle_interrupt,
0350
0351 .suspend = genphy_suspend,
0352 .resume = genphy_resume,
0353 }, {
0354 .phy_id = 0x0007c0b0,
0355 .phy_id_mask = 0xfffffff0,
0356 .name = "SMSC LAN8187",
0357
0358
0359
0360 .probe = smsc_phy_probe,
0361
0362
0363 .config_init = smsc_phy_config_init,
0364 .soft_reset = smsc_phy_reset,
0365
0366
0367 .config_intr = smsc_phy_config_intr,
0368 .handle_interrupt = smsc_phy_handle_interrupt,
0369
0370
0371 .get_sset_count = smsc_get_sset_count,
0372 .get_strings = smsc_get_strings,
0373 .get_stats = smsc_get_stats,
0374
0375 .suspend = genphy_suspend,
0376 .resume = genphy_resume,
0377 }, {
0378
0379
0380
0381 .phy_id = 0x0007c0c0,
0382 .phy_id_mask = 0xfffffff0,
0383 .name = "SMSC LAN8700",
0384
0385
0386
0387 .probe = smsc_phy_probe,
0388
0389
0390 .read_status = lan87xx_read_status,
0391 .config_init = smsc_phy_config_init,
0392 .soft_reset = smsc_phy_reset,
0393 .config_aneg = lan87xx_config_aneg,
0394
0395
0396 .config_intr = smsc_phy_config_intr,
0397 .handle_interrupt = smsc_phy_handle_interrupt,
0398
0399
0400 .get_sset_count = smsc_get_sset_count,
0401 .get_strings = smsc_get_strings,
0402 .get_stats = smsc_get_stats,
0403
0404 .suspend = genphy_suspend,
0405 .resume = genphy_resume,
0406 }, {
0407 .phy_id = 0x0007c0d0,
0408 .phy_id_mask = 0xfffffff0,
0409 .name = "SMSC LAN911x Internal PHY",
0410
0411
0412
0413 .probe = smsc_phy_probe,
0414
0415
0416 .config_intr = smsc_phy_config_intr,
0417 .handle_interrupt = smsc_phy_handle_interrupt,
0418
0419 .suspend = genphy_suspend,
0420 .resume = genphy_resume,
0421 }, {
0422
0423
0424
0425 .phy_id = 0x0007c0f0,
0426 .phy_id_mask = 0xfffffff0,
0427 .name = "SMSC LAN8710/LAN8720",
0428
0429
0430
0431 .probe = smsc_phy_probe,
0432 .remove = smsc_phy_remove,
0433
0434
0435 .read_status = lan87xx_read_status,
0436 .config_init = smsc_phy_config_init,
0437 .soft_reset = smsc_phy_reset,
0438 .config_aneg = lan95xx_config_aneg_ext,
0439
0440
0441 .config_intr = smsc_phy_config_intr,
0442 .handle_interrupt = smsc_phy_handle_interrupt,
0443
0444
0445 .get_sset_count = smsc_get_sset_count,
0446 .get_strings = smsc_get_strings,
0447 .get_stats = smsc_get_stats,
0448
0449 .suspend = genphy_suspend,
0450 .resume = genphy_resume,
0451 }, {
0452 .phy_id = 0x0007c110,
0453 .phy_id_mask = 0xfffffff0,
0454 .name = "SMSC LAN8740",
0455
0456
0457 .flags = PHY_RST_AFTER_CLK_EN,
0458
0459 .probe = smsc_phy_probe,
0460
0461
0462 .read_status = lan87xx_read_status,
0463 .config_init = smsc_phy_config_init,
0464 .soft_reset = smsc_phy_reset,
0465
0466
0467 .config_intr = smsc_phy_config_intr,
0468 .handle_interrupt = smsc_phy_handle_interrupt,
0469
0470
0471 .get_sset_count = smsc_get_sset_count,
0472 .get_strings = smsc_get_strings,
0473 .get_stats = smsc_get_stats,
0474
0475 .suspend = genphy_suspend,
0476 .resume = genphy_resume,
0477 }, {
0478 .phy_id = 0x0007c130,
0479
0480
0481
0482
0483 .phy_id_mask = 0xfffffff2,
0484 .name = "Microchip LAN8742",
0485
0486
0487 .flags = PHY_RST_AFTER_CLK_EN,
0488
0489 .probe = smsc_phy_probe,
0490
0491
0492 .read_status = lan87xx_read_status,
0493 .config_init = smsc_phy_config_init,
0494 .soft_reset = smsc_phy_reset,
0495
0496
0497 .config_intr = smsc_phy_config_intr,
0498 .handle_interrupt = smsc_phy_handle_interrupt,
0499
0500
0501 .get_sset_count = smsc_get_sset_count,
0502 .get_strings = smsc_get_strings,
0503 .get_stats = smsc_get_stats,
0504
0505 .suspend = genphy_suspend,
0506 .resume = genphy_resume,
0507 } };
0508
0509 module_phy_driver(smsc_phy_driver);
0510
0511 MODULE_DESCRIPTION("SMSC PHY driver");
0512 MODULE_AUTHOR("Herbert Valerio Riedel");
0513 MODULE_LICENSE("GPL");
0514
0515 static struct mdio_device_id __maybe_unused smsc_tbl[] = {
0516 { 0x0007c0a0, 0xfffffff0 },
0517 { 0x0007c0b0, 0xfffffff0 },
0518 { 0x0007c0c0, 0xfffffff0 },
0519 { 0x0007c0d0, 0xfffffff0 },
0520 { 0x0007c0f0, 0xfffffff0 },
0521 { 0x0007c110, 0xfffffff0 },
0522 { 0x0007c130, 0xfffffff2 },
0523 { }
0524 };
0525
0526 MODULE_DEVICE_TABLE(mdio, smsc_tbl);