0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/kernel.h>
0012 #include <linux/string.h>
0013 #include <linux/errno.h>
0014 #include <linux/unistd.h>
0015 #include <linux/interrupt.h>
0016 #include <linux/init.h>
0017 #include <linux/delay.h>
0018 #include <linux/netdevice.h>
0019 #include <linux/etherdevice.h>
0020 #include <linux/skbuff.h>
0021 #include <linux/spinlock.h>
0022 #include <linux/mm.h>
0023 #include <linux/module.h>
0024 #include <linux/mii.h>
0025 #include <linux/ethtool.h>
0026 #include <linux/phy.h>
0027
0028 #include <asm/io.h>
0029 #include <asm/irq.h>
0030 #include <linux/uaccess.h>
0031
0032
0033
0034 #define MII_LXT970_IER 17
0035
0036 #define MII_LXT970_IER_IEN 0x0002
0037
0038 #define MII_LXT970_ISR 18
0039
0040 #define MII_LXT970_IRS_MINT BIT(15)
0041
0042 #define MII_LXT970_CONFIG 19
0043
0044
0045
0046
0047
0048 #define MII_LXT971_IER 18
0049 #define MII_LXT971_IER_IEN 0x00f2
0050
0051 #define MII_LXT971_ISR 19
0052 #define MII_LXT971_ISR_MASK 0x00f0
0053
0054
0055 #define MII_LXT973_PCR 16
0056 #define PCR_FIBER_SELECT 1
0057
0058 MODULE_DESCRIPTION("Intel LXT PHY driver");
0059 MODULE_AUTHOR("Andy Fleming");
0060 MODULE_LICENSE("GPL");
0061
0062 static int lxt970_ack_interrupt(struct phy_device *phydev)
0063 {
0064 int err;
0065
0066 err = phy_read(phydev, MII_BMSR);
0067
0068 if (err < 0)
0069 return err;
0070
0071 err = phy_read(phydev, MII_LXT970_ISR);
0072
0073 if (err < 0)
0074 return err;
0075
0076 return 0;
0077 }
0078
0079 static int lxt970_config_intr(struct phy_device *phydev)
0080 {
0081 int err;
0082
0083 if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
0084 err = lxt970_ack_interrupt(phydev);
0085 if (err)
0086 return err;
0087
0088 err = phy_write(phydev, MII_LXT970_IER, MII_LXT970_IER_IEN);
0089 } else {
0090 err = phy_write(phydev, MII_LXT970_IER, 0);
0091 if (err)
0092 return err;
0093
0094 err = lxt970_ack_interrupt(phydev);
0095 }
0096
0097 return err;
0098 }
0099
0100 static irqreturn_t lxt970_handle_interrupt(struct phy_device *phydev)
0101 {
0102 int irq_status;
0103
0104
0105
0106
0107 irq_status = phy_read(phydev, MII_BMSR);
0108 if (irq_status < 0) {
0109 phy_error(phydev);
0110 return IRQ_NONE;
0111 }
0112
0113 irq_status = phy_read(phydev, MII_LXT970_ISR);
0114 if (irq_status < 0) {
0115 phy_error(phydev);
0116 return IRQ_NONE;
0117 }
0118
0119 if (!(irq_status & MII_LXT970_IRS_MINT))
0120 return IRQ_NONE;
0121
0122 phy_trigger_machine(phydev);
0123
0124 return IRQ_HANDLED;
0125 }
0126
0127 static int lxt970_config_init(struct phy_device *phydev)
0128 {
0129 return phy_write(phydev, MII_LXT970_CONFIG, 0);
0130 }
0131
0132
0133 static int lxt971_ack_interrupt(struct phy_device *phydev)
0134 {
0135 int err = phy_read(phydev, MII_LXT971_ISR);
0136
0137 if (err < 0)
0138 return err;
0139
0140 return 0;
0141 }
0142
0143 static int lxt971_config_intr(struct phy_device *phydev)
0144 {
0145 int err;
0146
0147 if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
0148 err = lxt971_ack_interrupt(phydev);
0149 if (err)
0150 return err;
0151
0152 err = phy_write(phydev, MII_LXT971_IER, MII_LXT971_IER_IEN);
0153 } else {
0154 err = phy_write(phydev, MII_LXT971_IER, 0);
0155 if (err)
0156 return err;
0157
0158 err = lxt971_ack_interrupt(phydev);
0159 }
0160
0161 return err;
0162 }
0163
0164 static irqreturn_t lxt971_handle_interrupt(struct phy_device *phydev)
0165 {
0166 int irq_status;
0167
0168 irq_status = phy_read(phydev, MII_LXT971_ISR);
0169 if (irq_status < 0) {
0170 phy_error(phydev);
0171 return IRQ_NONE;
0172 }
0173
0174 if (!(irq_status & MII_LXT971_ISR_MASK))
0175 return IRQ_NONE;
0176
0177 phy_trigger_machine(phydev);
0178
0179 return IRQ_HANDLED;
0180 }
0181
0182
0183
0184
0185
0186
0187 static int lxt973a2_update_link(struct phy_device *phydev)
0188 {
0189 int status;
0190 int control;
0191 int retry = 8;
0192
0193
0194 status = phy_read(phydev, MII_BMSR);
0195
0196 if (status < 0)
0197 return status;
0198
0199 control = phy_read(phydev, MII_BMCR);
0200 if (control < 0)
0201 return control;
0202
0203 do {
0204
0205 status = phy_read(phydev, MII_BMSR);
0206 } while (status >= 0 && retry-- && status == control);
0207
0208 if (status < 0)
0209 return status;
0210
0211 if ((status & BMSR_LSTATUS) == 0)
0212 phydev->link = 0;
0213 else
0214 phydev->link = 1;
0215
0216 return 0;
0217 }
0218
0219 static int lxt973a2_read_status(struct phy_device *phydev)
0220 {
0221 int adv;
0222 int err;
0223 int lpa;
0224
0225
0226 err = lxt973a2_update_link(phydev);
0227 if (err)
0228 return err;
0229
0230 if (AUTONEG_ENABLE == phydev->autoneg) {
0231 int retry = 1;
0232
0233 adv = phy_read(phydev, MII_ADVERTISE);
0234
0235 if (adv < 0)
0236 return adv;
0237
0238 do {
0239 lpa = phy_read(phydev, MII_LPA);
0240
0241 if (lpa < 0)
0242 return lpa;
0243
0244
0245
0246
0247 } while (lpa == adv && retry--);
0248
0249 mii_lpa_to_linkmode_lpa_t(phydev->lp_advertising, lpa);
0250
0251 lpa &= adv;
0252
0253 phydev->speed = SPEED_10;
0254 phydev->duplex = DUPLEX_HALF;
0255 phydev->pause = phydev->asym_pause = 0;
0256
0257 if (lpa & (LPA_100FULL | LPA_100HALF)) {
0258 phydev->speed = SPEED_100;
0259
0260 if (lpa & LPA_100FULL)
0261 phydev->duplex = DUPLEX_FULL;
0262 } else {
0263 if (lpa & LPA_10FULL)
0264 phydev->duplex = DUPLEX_FULL;
0265 }
0266
0267 phy_resolve_aneg_pause(phydev);
0268 } else {
0269 err = genphy_read_status_fixed(phydev);
0270 if (err < 0)
0271 return err;
0272
0273 phydev->pause = phydev->asym_pause = 0;
0274 linkmode_zero(phydev->lp_advertising);
0275 }
0276
0277 return 0;
0278 }
0279
0280 static int lxt973_probe(struct phy_device *phydev)
0281 {
0282 int val = phy_read(phydev, MII_LXT973_PCR);
0283
0284 if (val & PCR_FIBER_SELECT) {
0285
0286
0287
0288
0289 val = phy_read(phydev, MII_BMCR);
0290 val |= (BMCR_SPEED100 | BMCR_FULLDPLX);
0291 val &= ~BMCR_ANENABLE;
0292 phy_write(phydev, MII_BMCR, val);
0293
0294 phydev->priv = lxt973_probe;
0295 phydev->port = PORT_FIBRE;
0296 } else {
0297 phydev->priv = NULL;
0298 }
0299 return 0;
0300 }
0301
0302 static int lxt973_config_aneg(struct phy_device *phydev)
0303 {
0304
0305 return phydev->priv ? 0 : genphy_config_aneg(phydev);
0306 }
0307
0308 static struct phy_driver lxt97x_driver[] = {
0309 {
0310 .phy_id = 0x78100000,
0311 .name = "LXT970",
0312 .phy_id_mask = 0xfffffff0,
0313
0314 .config_init = lxt970_config_init,
0315 .config_intr = lxt970_config_intr,
0316 .handle_interrupt = lxt970_handle_interrupt,
0317 }, {
0318 .phy_id = 0x001378e0,
0319 .name = "LXT971",
0320 .phy_id_mask = 0xfffffff0,
0321
0322 .config_intr = lxt971_config_intr,
0323 .handle_interrupt = lxt971_handle_interrupt,
0324 .suspend = genphy_suspend,
0325 .resume = genphy_resume,
0326 }, {
0327 .phy_id = 0x00137a10,
0328 .name = "LXT973-A2",
0329 .phy_id_mask = 0xffffffff,
0330
0331 .flags = 0,
0332 .probe = lxt973_probe,
0333 .config_aneg = lxt973_config_aneg,
0334 .read_status = lxt973a2_read_status,
0335 .suspend = genphy_suspend,
0336 .resume = genphy_resume,
0337 }, {
0338 .phy_id = 0x00137a10,
0339 .name = "LXT973",
0340 .phy_id_mask = 0xfffffff0,
0341
0342 .flags = 0,
0343 .probe = lxt973_probe,
0344 .config_aneg = lxt973_config_aneg,
0345 .suspend = genphy_suspend,
0346 .resume = genphy_resume,
0347 } };
0348
0349 module_phy_driver(lxt97x_driver);
0350
0351 static struct mdio_device_id __maybe_unused lxt_tbl[] = {
0352 { 0x78100000, 0xfffffff0 },
0353 { 0x001378e0, 0xfffffff0 },
0354 { 0x00137a10, 0xfffffff0 },
0355 { }
0356 };
0357
0358 MODULE_DEVICE_TABLE(mdio, lxt_tbl);