0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #include <linux/kernel.h>
0014 #include <linux/string.h>
0015 #include <linux/ctype.h>
0016 #include <linux/errno.h>
0017 #include <linux/unistd.h>
0018 #include <linux/hwmon.h>
0019 #include <linux/interrupt.h>
0020 #include <linux/init.h>
0021 #include <linux/delay.h>
0022 #include <linux/netdevice.h>
0023 #include <linux/etherdevice.h>
0024 #include <linux/skbuff.h>
0025 #include <linux/spinlock.h>
0026 #include <linux/mm.h>
0027 #include <linux/module.h>
0028 #include <linux/mii.h>
0029 #include <linux/ethtool.h>
0030 #include <linux/ethtool_netlink.h>
0031 #include <linux/phy.h>
0032 #include <linux/marvell_phy.h>
0033 #include <linux/bitfield.h>
0034 #include <linux/of.h>
0035 #include <linux/sfp.h>
0036
0037 #include <linux/io.h>
0038 #include <asm/irq.h>
0039 #include <linux/uaccess.h>
0040
0041 #define MII_MARVELL_PHY_PAGE 22
0042 #define MII_MARVELL_COPPER_PAGE 0x00
0043 #define MII_MARVELL_FIBER_PAGE 0x01
0044 #define MII_MARVELL_MSCR_PAGE 0x02
0045 #define MII_MARVELL_LED_PAGE 0x03
0046 #define MII_MARVELL_VCT5_PAGE 0x05
0047 #define MII_MARVELL_MISC_TEST_PAGE 0x06
0048 #define MII_MARVELL_VCT7_PAGE 0x07
0049 #define MII_MARVELL_WOL_PAGE 0x11
0050 #define MII_MARVELL_MODE_PAGE 0x12
0051
0052 #define MII_M1011_IEVENT 0x13
0053 #define MII_M1011_IEVENT_CLEAR 0x0000
0054
0055 #define MII_M1011_IMASK 0x12
0056 #define MII_M1011_IMASK_INIT 0x6400
0057 #define MII_M1011_IMASK_CLEAR 0x0000
0058
0059 #define MII_M1011_PHY_SCR 0x10
0060 #define MII_M1011_PHY_SCR_DOWNSHIFT_EN BIT(11)
0061 #define MII_M1011_PHY_SCR_DOWNSHIFT_MASK GENMASK(14, 12)
0062 #define MII_M1011_PHY_SCR_DOWNSHIFT_MAX 8
0063 #define MII_M1011_PHY_SCR_MDI (0x0 << 5)
0064 #define MII_M1011_PHY_SCR_MDI_X (0x1 << 5)
0065 #define MII_M1011_PHY_SCR_AUTO_CROSS (0x3 << 5)
0066
0067 #define MII_M1011_PHY_SSR 0x11
0068 #define MII_M1011_PHY_SSR_DOWNSHIFT BIT(5)
0069
0070 #define MII_M1111_PHY_LED_CONTROL 0x18
0071 #define MII_M1111_PHY_LED_DIRECT 0x4100
0072 #define MII_M1111_PHY_LED_COMBINE 0x411c
0073 #define MII_M1111_PHY_EXT_CR 0x14
0074 #define MII_M1111_PHY_EXT_CR_DOWNSHIFT_MASK GENMASK(11, 9)
0075 #define MII_M1111_PHY_EXT_CR_DOWNSHIFT_MAX 8
0076 #define MII_M1111_PHY_EXT_CR_DOWNSHIFT_EN BIT(8)
0077 #define MII_M1111_RGMII_RX_DELAY BIT(7)
0078 #define MII_M1111_RGMII_TX_DELAY BIT(1)
0079 #define MII_M1111_PHY_EXT_SR 0x1b
0080
0081 #define MII_M1111_HWCFG_MODE_MASK 0xf
0082 #define MII_M1111_HWCFG_MODE_FIBER_RGMII 0x3
0083 #define MII_M1111_HWCFG_MODE_SGMII_NO_CLK 0x4
0084 #define MII_M1111_HWCFG_MODE_RTBI 0x7
0085 #define MII_M1111_HWCFG_MODE_COPPER_1000X_AN 0x8
0086 #define MII_M1111_HWCFG_MODE_COPPER_RTBI 0x9
0087 #define MII_M1111_HWCFG_MODE_COPPER_RGMII 0xb
0088 #define MII_M1111_HWCFG_MODE_COPPER_1000X_NOAN 0xc
0089 #define MII_M1111_HWCFG_SERIAL_AN_BYPASS BIT(12)
0090 #define MII_M1111_HWCFG_FIBER_COPPER_RES BIT(13)
0091 #define MII_M1111_HWCFG_FIBER_COPPER_AUTO BIT(15)
0092
0093 #define MII_88E1121_PHY_MSCR_REG 21
0094 #define MII_88E1121_PHY_MSCR_RX_DELAY BIT(5)
0095 #define MII_88E1121_PHY_MSCR_TX_DELAY BIT(4)
0096 #define MII_88E1121_PHY_MSCR_DELAY_MASK (BIT(5) | BIT(4))
0097
0098 #define MII_88E1121_MISC_TEST 0x1a
0099 #define MII_88E1510_MISC_TEST_TEMP_THRESHOLD_MASK 0x1f00
0100 #define MII_88E1510_MISC_TEST_TEMP_THRESHOLD_SHIFT 8
0101 #define MII_88E1510_MISC_TEST_TEMP_IRQ_EN BIT(7)
0102 #define MII_88E1510_MISC_TEST_TEMP_IRQ BIT(6)
0103 #define MII_88E1121_MISC_TEST_TEMP_SENSOR_EN BIT(5)
0104 #define MII_88E1121_MISC_TEST_TEMP_MASK 0x1f
0105
0106 #define MII_88E1510_TEMP_SENSOR 0x1b
0107 #define MII_88E1510_TEMP_SENSOR_MASK 0xff
0108
0109 #define MII_88E1540_COPPER_CTRL3 0x1a
0110 #define MII_88E1540_COPPER_CTRL3_LINK_DOWN_DELAY_MASK GENMASK(11, 10)
0111 #define MII_88E1540_COPPER_CTRL3_LINK_DOWN_DELAY_00MS 0
0112 #define MII_88E1540_COPPER_CTRL3_LINK_DOWN_DELAY_10MS 1
0113 #define MII_88E1540_COPPER_CTRL3_LINK_DOWN_DELAY_20MS 2
0114 #define MII_88E1540_COPPER_CTRL3_LINK_DOWN_DELAY_40MS 3
0115 #define MII_88E1540_COPPER_CTRL3_FAST_LINK_DOWN BIT(9)
0116
0117 #define MII_88E6390_MISC_TEST 0x1b
0118 #define MII_88E6390_MISC_TEST_TEMP_SENSOR_ENABLE_SAMPLE_1S (0x0 << 14)
0119 #define MII_88E6390_MISC_TEST_TEMP_SENSOR_ENABLE (0x1 << 14)
0120 #define MII_88E6390_MISC_TEST_TEMP_SENSOR_ENABLE_ONESHOT (0x2 << 14)
0121 #define MII_88E6390_MISC_TEST_TEMP_SENSOR_DISABLE (0x3 << 14)
0122 #define MII_88E6390_MISC_TEST_TEMP_SENSOR_MASK (0x3 << 14)
0123 #define MII_88E6393_MISC_TEST_SAMPLES_2048 (0x0 << 11)
0124 #define MII_88E6393_MISC_TEST_SAMPLES_4096 (0x1 << 11)
0125 #define MII_88E6393_MISC_TEST_SAMPLES_8192 (0x2 << 11)
0126 #define MII_88E6393_MISC_TEST_SAMPLES_16384 (0x3 << 11)
0127 #define MII_88E6393_MISC_TEST_SAMPLES_MASK (0x3 << 11)
0128 #define MII_88E6393_MISC_TEST_RATE_2_3MS (0x5 << 8)
0129 #define MII_88E6393_MISC_TEST_RATE_6_4MS (0x6 << 8)
0130 #define MII_88E6393_MISC_TEST_RATE_11_9MS (0x7 << 8)
0131 #define MII_88E6393_MISC_TEST_RATE_MASK (0x7 << 8)
0132
0133 #define MII_88E6390_TEMP_SENSOR 0x1c
0134 #define MII_88E6393_TEMP_SENSOR_THRESHOLD_MASK 0xff00
0135 #define MII_88E6393_TEMP_SENSOR_THRESHOLD_SHIFT 8
0136 #define MII_88E6390_TEMP_SENSOR_MASK 0xff
0137 #define MII_88E6390_TEMP_SENSOR_SAMPLES 10
0138
0139 #define MII_88E1318S_PHY_MSCR1_REG 16
0140 #define MII_88E1318S_PHY_MSCR1_PAD_ODD BIT(6)
0141
0142
0143 #define MII_88E1318S_PHY_CSIER 0x12
0144
0145 #define MII_88E1318S_PHY_CSIER_WOL_EIE BIT(7)
0146
0147
0148 #define MII_88E1318S_PHY_LED_TCR 0x12
0149 #define MII_88E1318S_PHY_LED_TCR_FORCE_INT BIT(15)
0150 #define MII_88E1318S_PHY_LED_TCR_INTn_ENABLE BIT(7)
0151 #define MII_88E1318S_PHY_LED_TCR_INT_ACTIVE_LOW BIT(11)
0152
0153
0154 #define MII_88E1318S_PHY_MAGIC_PACKET_WORD2 0x17
0155 #define MII_88E1318S_PHY_MAGIC_PACKET_WORD1 0x18
0156 #define MII_88E1318S_PHY_MAGIC_PACKET_WORD0 0x19
0157
0158 #define MII_88E1318S_PHY_WOL_CTRL 0x10
0159 #define MII_88E1318S_PHY_WOL_CTRL_CLEAR_WOL_STATUS BIT(12)
0160 #define MII_88E1318S_PHY_WOL_CTRL_LINK_UP_ENABLE BIT(13)
0161 #define MII_88E1318S_PHY_WOL_CTRL_MAGIC_PACKET_MATCH_ENABLE BIT(14)
0162
0163 #define MII_PHY_LED_CTRL 16
0164 #define MII_88E1121_PHY_LED_DEF 0x0030
0165 #define MII_88E1510_PHY_LED_DEF 0x1177
0166 #define MII_88E1510_PHY_LED0_LINK_LED1_ACTIVE 0x1040
0167
0168 #define MII_M1011_PHY_STATUS 0x11
0169 #define MII_M1011_PHY_STATUS_1000 0x8000
0170 #define MII_M1011_PHY_STATUS_100 0x4000
0171 #define MII_M1011_PHY_STATUS_SPD_MASK 0xc000
0172 #define MII_M1011_PHY_STATUS_FULLDUPLEX 0x2000
0173 #define MII_M1011_PHY_STATUS_RESOLVED 0x0800
0174 #define MII_M1011_PHY_STATUS_LINK 0x0400
0175
0176 #define MII_88E3016_PHY_SPEC_CTRL 0x10
0177 #define MII_88E3016_DISABLE_SCRAMBLER 0x0200
0178 #define MII_88E3016_AUTO_MDIX_CROSSOVER 0x0030
0179
0180 #define MII_88E1510_GEN_CTRL_REG_1 0x14
0181 #define MII_88E1510_GEN_CTRL_REG_1_MODE_MASK 0x7
0182 #define MII_88E1510_GEN_CTRL_REG_1_MODE_RGMII 0x0
0183 #define MII_88E1510_GEN_CTRL_REG_1_MODE_SGMII 0x1
0184
0185 #define MII_88E1510_GEN_CTRL_REG_1_MODE_RGMII_1000X 0x2
0186
0187 #define MII_88E1510_GEN_CTRL_REG_1_MODE_RGMII_100FX 0x3
0188
0189 #define MII_88E1510_GEN_CTRL_REG_1_MODE_RGMII_SGMII 0x4
0190 #define MII_88E1510_GEN_CTRL_REG_1_RESET 0x8000
0191
0192 #define MII_88E1510_MSCR_2 0x15
0193
0194 #define MII_VCT5_TX_RX_MDI0_COUPLING 0x10
0195 #define MII_VCT5_TX_RX_MDI1_COUPLING 0x11
0196 #define MII_VCT5_TX_RX_MDI2_COUPLING 0x12
0197 #define MII_VCT5_TX_RX_MDI3_COUPLING 0x13
0198 #define MII_VCT5_TX_RX_AMPLITUDE_MASK 0x7f00
0199 #define MII_VCT5_TX_RX_AMPLITUDE_SHIFT 8
0200 #define MII_VCT5_TX_RX_COUPLING_POSITIVE_REFLECTION BIT(15)
0201
0202 #define MII_VCT5_CTRL 0x17
0203 #define MII_VCT5_CTRL_ENABLE BIT(15)
0204 #define MII_VCT5_CTRL_COMPLETE BIT(14)
0205 #define MII_VCT5_CTRL_TX_SAME_CHANNEL (0x0 << 11)
0206 #define MII_VCT5_CTRL_TX0_CHANNEL (0x4 << 11)
0207 #define MII_VCT5_CTRL_TX1_CHANNEL (0x5 << 11)
0208 #define MII_VCT5_CTRL_TX2_CHANNEL (0x6 << 11)
0209 #define MII_VCT5_CTRL_TX3_CHANNEL (0x7 << 11)
0210 #define MII_VCT5_CTRL_SAMPLES_2 (0x0 << 8)
0211 #define MII_VCT5_CTRL_SAMPLES_4 (0x1 << 8)
0212 #define MII_VCT5_CTRL_SAMPLES_8 (0x2 << 8)
0213 #define MII_VCT5_CTRL_SAMPLES_16 (0x3 << 8)
0214 #define MII_VCT5_CTRL_SAMPLES_32 (0x4 << 8)
0215 #define MII_VCT5_CTRL_SAMPLES_64 (0x5 << 8)
0216 #define MII_VCT5_CTRL_SAMPLES_128 (0x6 << 8)
0217 #define MII_VCT5_CTRL_SAMPLES_DEFAULT (0x6 << 8)
0218 #define MII_VCT5_CTRL_SAMPLES_256 (0x7 << 8)
0219 #define MII_VCT5_CTRL_SAMPLES_SHIFT 8
0220 #define MII_VCT5_CTRL_MODE_MAXIMUM_PEEK (0x0 << 6)
0221 #define MII_VCT5_CTRL_MODE_FIRST_LAST_PEEK (0x1 << 6)
0222 #define MII_VCT5_CTRL_MODE_OFFSET (0x2 << 6)
0223 #define MII_VCT5_CTRL_SAMPLE_POINT (0x3 << 6)
0224 #define MII_VCT5_CTRL_PEEK_HYST_DEFAULT 3
0225
0226 #define MII_VCT5_SAMPLE_POINT_DISTANCE 0x18
0227 #define MII_VCT5_SAMPLE_POINT_DISTANCE_MAX 511
0228 #define MII_VCT5_TX_PULSE_CTRL 0x1c
0229 #define MII_VCT5_TX_PULSE_CTRL_DONT_WAIT_LINK_DOWN BIT(12)
0230 #define MII_VCT5_TX_PULSE_CTRL_PULSE_WIDTH_128nS (0x0 << 10)
0231 #define MII_VCT5_TX_PULSE_CTRL_PULSE_WIDTH_96nS (0x1 << 10)
0232 #define MII_VCT5_TX_PULSE_CTRL_PULSE_WIDTH_64nS (0x2 << 10)
0233 #define MII_VCT5_TX_PULSE_CTRL_PULSE_WIDTH_32nS (0x3 << 10)
0234 #define MII_VCT5_TX_PULSE_CTRL_PULSE_WIDTH_SHIFT 10
0235 #define MII_VCT5_TX_PULSE_CTRL_PULSE_AMPLITUDE_1000mV (0x0 << 8)
0236 #define MII_VCT5_TX_PULSE_CTRL_PULSE_AMPLITUDE_750mV (0x1 << 8)
0237 #define MII_VCT5_TX_PULSE_CTRL_PULSE_AMPLITUDE_500mV (0x2 << 8)
0238 #define MII_VCT5_TX_PULSE_CTRL_PULSE_AMPLITUDE_250mV (0x3 << 8)
0239 #define MII_VCT5_TX_PULSE_CTRL_PULSE_AMPLITUDE_SHIFT 8
0240 #define MII_VCT5_TX_PULSE_CTRL_MAX_AMP BIT(7)
0241 #define MII_VCT5_TX_PULSE_CTRL_GT_140m_46_86mV (0x6 << 0)
0242
0243
0244
0245
0246 #define TDR_SHORT_CABLE_LENGTH 11
0247
0248 #define MII_VCT7_PAIR_0_DISTANCE 0x10
0249 #define MII_VCT7_PAIR_1_DISTANCE 0x11
0250 #define MII_VCT7_PAIR_2_DISTANCE 0x12
0251 #define MII_VCT7_PAIR_3_DISTANCE 0x13
0252
0253 #define MII_VCT7_RESULTS 0x14
0254 #define MII_VCT7_RESULTS_PAIR3_MASK 0xf000
0255 #define MII_VCT7_RESULTS_PAIR2_MASK 0x0f00
0256 #define MII_VCT7_RESULTS_PAIR1_MASK 0x00f0
0257 #define MII_VCT7_RESULTS_PAIR0_MASK 0x000f
0258 #define MII_VCT7_RESULTS_PAIR3_SHIFT 12
0259 #define MII_VCT7_RESULTS_PAIR2_SHIFT 8
0260 #define MII_VCT7_RESULTS_PAIR1_SHIFT 4
0261 #define MII_VCT7_RESULTS_PAIR0_SHIFT 0
0262 #define MII_VCT7_RESULTS_INVALID 0
0263 #define MII_VCT7_RESULTS_OK 1
0264 #define MII_VCT7_RESULTS_OPEN 2
0265 #define MII_VCT7_RESULTS_SAME_SHORT 3
0266 #define MII_VCT7_RESULTS_CROSS_SHORT 4
0267 #define MII_VCT7_RESULTS_BUSY 9
0268
0269 #define MII_VCT7_CTRL 0x15
0270 #define MII_VCT7_CTRL_RUN_NOW BIT(15)
0271 #define MII_VCT7_CTRL_RUN_ANEG BIT(14)
0272 #define MII_VCT7_CTRL_DISABLE_CROSS BIT(13)
0273 #define MII_VCT7_CTRL_RUN_AFTER_BREAK_LINK BIT(12)
0274 #define MII_VCT7_CTRL_IN_PROGRESS BIT(11)
0275 #define MII_VCT7_CTRL_METERS BIT(10)
0276 #define MII_VCT7_CTRL_CENTIMETERS 0
0277
0278 #define LPA_PAUSE_FIBER 0x180
0279 #define LPA_PAUSE_ASYM_FIBER 0x100
0280
0281 #define NB_FIBER_STATS 1
0282
0283 MODULE_DESCRIPTION("Marvell PHY driver");
0284 MODULE_AUTHOR("Andy Fleming");
0285 MODULE_LICENSE("GPL");
0286
0287 struct marvell_hw_stat {
0288 const char *string;
0289 u8 page;
0290 u8 reg;
0291 u8 bits;
0292 };
0293
0294 static struct marvell_hw_stat marvell_hw_stats[] = {
0295 { "phy_receive_errors_copper", 0, 21, 16},
0296 { "phy_idle_errors", 0, 10, 8 },
0297 { "phy_receive_errors_fiber", 1, 21, 16},
0298 };
0299
0300 struct marvell_priv {
0301 u64 stats[ARRAY_SIZE(marvell_hw_stats)];
0302 char *hwmon_name;
0303 struct device *hwmon_dev;
0304 bool cable_test_tdr;
0305 u32 first;
0306 u32 last;
0307 u32 step;
0308 s8 pair;
0309 };
0310
0311 static int marvell_read_page(struct phy_device *phydev)
0312 {
0313 return __phy_read(phydev, MII_MARVELL_PHY_PAGE);
0314 }
0315
0316 static int marvell_write_page(struct phy_device *phydev, int page)
0317 {
0318 return __phy_write(phydev, MII_MARVELL_PHY_PAGE, page);
0319 }
0320
0321 static int marvell_set_page(struct phy_device *phydev, int page)
0322 {
0323 return phy_write(phydev, MII_MARVELL_PHY_PAGE, page);
0324 }
0325
0326 static int marvell_ack_interrupt(struct phy_device *phydev)
0327 {
0328 int err;
0329
0330
0331 err = phy_read(phydev, MII_M1011_IEVENT);
0332
0333 if (err < 0)
0334 return err;
0335
0336 return 0;
0337 }
0338
0339 static int marvell_config_intr(struct phy_device *phydev)
0340 {
0341 int err;
0342
0343 if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
0344 err = marvell_ack_interrupt(phydev);
0345 if (err)
0346 return err;
0347
0348 err = phy_write(phydev, MII_M1011_IMASK,
0349 MII_M1011_IMASK_INIT);
0350 } else {
0351 err = phy_write(phydev, MII_M1011_IMASK,
0352 MII_M1011_IMASK_CLEAR);
0353 if (err)
0354 return err;
0355
0356 err = marvell_ack_interrupt(phydev);
0357 }
0358
0359 return err;
0360 }
0361
0362 static irqreturn_t marvell_handle_interrupt(struct phy_device *phydev)
0363 {
0364 int irq_status;
0365
0366 irq_status = phy_read(phydev, MII_M1011_IEVENT);
0367 if (irq_status < 0) {
0368 phy_error(phydev);
0369 return IRQ_NONE;
0370 }
0371
0372 if (!(irq_status & MII_M1011_IMASK_INIT))
0373 return IRQ_NONE;
0374
0375 phy_trigger_machine(phydev);
0376
0377 return IRQ_HANDLED;
0378 }
0379
0380 static int marvell_set_polarity(struct phy_device *phydev, int polarity)
0381 {
0382 u16 val;
0383
0384 switch (polarity) {
0385 case ETH_TP_MDI:
0386 val = MII_M1011_PHY_SCR_MDI;
0387 break;
0388 case ETH_TP_MDI_X:
0389 val = MII_M1011_PHY_SCR_MDI_X;
0390 break;
0391 case ETH_TP_MDI_AUTO:
0392 case ETH_TP_MDI_INVALID:
0393 default:
0394 val = MII_M1011_PHY_SCR_AUTO_CROSS;
0395 break;
0396 }
0397
0398 return phy_modify_changed(phydev, MII_M1011_PHY_SCR,
0399 MII_M1011_PHY_SCR_AUTO_CROSS, val);
0400 }
0401
0402 static int marvell_config_aneg(struct phy_device *phydev)
0403 {
0404 int changed = 0;
0405 int err;
0406
0407 err = marvell_set_polarity(phydev, phydev->mdix_ctrl);
0408 if (err < 0)
0409 return err;
0410
0411 changed = err;
0412
0413 err = phy_write(phydev, MII_M1111_PHY_LED_CONTROL,
0414 MII_M1111_PHY_LED_DIRECT);
0415 if (err < 0)
0416 return err;
0417
0418 err = genphy_config_aneg(phydev);
0419 if (err < 0)
0420 return err;
0421
0422 if (phydev->autoneg != AUTONEG_ENABLE || changed) {
0423
0424
0425
0426
0427 err = genphy_soft_reset(phydev);
0428 if (err < 0)
0429 return err;
0430 }
0431
0432 return 0;
0433 }
0434
0435 static int m88e1101_config_aneg(struct phy_device *phydev)
0436 {
0437 int err;
0438
0439
0440
0441
0442
0443 err = genphy_soft_reset(phydev);
0444 if (err < 0)
0445 return err;
0446
0447 err = phy_write(phydev, 0x1d, 0x1f);
0448 if (err < 0)
0449 return err;
0450
0451 err = phy_write(phydev, 0x1e, 0x200c);
0452 if (err < 0)
0453 return err;
0454
0455 err = phy_write(phydev, 0x1d, 0x5);
0456 if (err < 0)
0457 return err;
0458
0459 err = phy_write(phydev, 0x1e, 0);
0460 if (err < 0)
0461 return err;
0462
0463 err = phy_write(phydev, 0x1e, 0x100);
0464 if (err < 0)
0465 return err;
0466
0467 return marvell_config_aneg(phydev);
0468 }
0469
0470 #if IS_ENABLED(CONFIG_OF_MDIO)
0471
0472
0473
0474
0475
0476
0477
0478
0479
0480
0481
0482
0483
0484 static int marvell_of_reg_init(struct phy_device *phydev)
0485 {
0486 const __be32 *paddr;
0487 int len, i, saved_page, current_page, ret = 0;
0488
0489 if (!phydev->mdio.dev.of_node)
0490 return 0;
0491
0492 paddr = of_get_property(phydev->mdio.dev.of_node,
0493 "marvell,reg-init", &len);
0494 if (!paddr || len < (4 * sizeof(*paddr)))
0495 return 0;
0496
0497 saved_page = phy_save_page(phydev);
0498 if (saved_page < 0)
0499 goto err;
0500 current_page = saved_page;
0501
0502 len /= sizeof(*paddr);
0503 for (i = 0; i < len - 3; i += 4) {
0504 u16 page = be32_to_cpup(paddr + i);
0505 u16 reg = be32_to_cpup(paddr + i + 1);
0506 u16 mask = be32_to_cpup(paddr + i + 2);
0507 u16 val_bits = be32_to_cpup(paddr + i + 3);
0508 int val;
0509
0510 if (page != current_page) {
0511 current_page = page;
0512 ret = marvell_write_page(phydev, page);
0513 if (ret < 0)
0514 goto err;
0515 }
0516
0517 val = 0;
0518 if (mask) {
0519 val = __phy_read(phydev, reg);
0520 if (val < 0) {
0521 ret = val;
0522 goto err;
0523 }
0524 val &= mask;
0525 }
0526 val |= val_bits;
0527
0528 ret = __phy_write(phydev, reg, val);
0529 if (ret < 0)
0530 goto err;
0531 }
0532 err:
0533 return phy_restore_page(phydev, saved_page, ret);
0534 }
0535 #else
0536 static int marvell_of_reg_init(struct phy_device *phydev)
0537 {
0538 return 0;
0539 }
0540 #endif
0541
0542 static int m88e1121_config_aneg_rgmii_delays(struct phy_device *phydev)
0543 {
0544 int mscr;
0545
0546 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
0547 mscr = MII_88E1121_PHY_MSCR_RX_DELAY |
0548 MII_88E1121_PHY_MSCR_TX_DELAY;
0549 else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID)
0550 mscr = MII_88E1121_PHY_MSCR_RX_DELAY;
0551 else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)
0552 mscr = MII_88E1121_PHY_MSCR_TX_DELAY;
0553 else
0554 mscr = 0;
0555
0556 return phy_modify_paged_changed(phydev, MII_MARVELL_MSCR_PAGE,
0557 MII_88E1121_PHY_MSCR_REG,
0558 MII_88E1121_PHY_MSCR_DELAY_MASK, mscr);
0559 }
0560
0561 static int m88e1121_config_aneg(struct phy_device *phydev)
0562 {
0563 int changed = 0;
0564 int err = 0;
0565
0566 if (phy_interface_is_rgmii(phydev)) {
0567 err = m88e1121_config_aneg_rgmii_delays(phydev);
0568 if (err < 0)
0569 return err;
0570 }
0571
0572 changed = err;
0573
0574 err = marvell_set_polarity(phydev, phydev->mdix_ctrl);
0575 if (err < 0)
0576 return err;
0577
0578 changed |= err;
0579
0580 err = genphy_config_aneg(phydev);
0581 if (err < 0)
0582 return err;
0583
0584 if (phydev->autoneg != AUTONEG_ENABLE || changed) {
0585
0586
0587
0588 err = genphy_soft_reset(phydev);
0589 if (err < 0)
0590 return err;
0591 }
0592
0593 return 0;
0594 }
0595
0596 static int m88e1318_config_aneg(struct phy_device *phydev)
0597 {
0598 int err;
0599
0600 err = phy_modify_paged(phydev, MII_MARVELL_MSCR_PAGE,
0601 MII_88E1318S_PHY_MSCR1_REG,
0602 0, MII_88E1318S_PHY_MSCR1_PAD_ODD);
0603 if (err < 0)
0604 return err;
0605
0606 return m88e1121_config_aneg(phydev);
0607 }
0608
0609
0610
0611
0612
0613
0614
0615
0616
0617 static inline u32 linkmode_adv_to_fiber_adv_t(unsigned long *advertise)
0618 {
0619 u32 result = 0;
0620
0621 if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT, advertise))
0622 result |= ADVERTISE_1000XHALF;
0623 if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, advertise))
0624 result |= ADVERTISE_1000XFULL;
0625
0626 if (linkmode_test_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, advertise) &&
0627 linkmode_test_bit(ETHTOOL_LINK_MODE_Pause_BIT, advertise))
0628 result |= ADVERTISE_1000XPSE_ASYM;
0629 else if (linkmode_test_bit(ETHTOOL_LINK_MODE_Pause_BIT, advertise))
0630 result |= ADVERTISE_1000XPAUSE;
0631
0632 return result;
0633 }
0634
0635
0636
0637
0638
0639
0640
0641
0642
0643
0644 static int marvell_config_aneg_fiber(struct phy_device *phydev)
0645 {
0646 int changed = 0;
0647 int err;
0648 u16 adv;
0649
0650 if (phydev->autoneg != AUTONEG_ENABLE)
0651 return genphy_setup_forced(phydev);
0652
0653
0654 linkmode_and(phydev->advertising, phydev->advertising,
0655 phydev->supported);
0656
0657 adv = linkmode_adv_to_fiber_adv_t(phydev->advertising);
0658
0659
0660 err = phy_modify_changed(phydev, MII_ADVERTISE,
0661 ADVERTISE_1000XHALF | ADVERTISE_1000XFULL |
0662 ADVERTISE_1000XPAUSE | ADVERTISE_1000XPSE_ASYM,
0663 adv);
0664 if (err < 0)
0665 return err;
0666 if (err > 0)
0667 changed = 1;
0668
0669 return genphy_check_and_restart_aneg(phydev, changed);
0670 }
0671
0672 static int m88e1111_config_aneg(struct phy_device *phydev)
0673 {
0674 int extsr = phy_read(phydev, MII_M1111_PHY_EXT_SR);
0675 int err;
0676
0677 if (extsr < 0)
0678 return extsr;
0679
0680
0681
0682
0683 if (phydev->interface != PHY_INTERFACE_MODE_SGMII &&
0684 (extsr & MII_M1111_HWCFG_MODE_MASK) !=
0685 MII_M1111_HWCFG_MODE_COPPER_1000X_AN)
0686 return marvell_config_aneg(phydev);
0687
0688 err = marvell_set_page(phydev, MII_MARVELL_COPPER_PAGE);
0689 if (err < 0)
0690 goto error;
0691
0692
0693 err = marvell_config_aneg(phydev);
0694 if (err < 0)
0695 goto error;
0696
0697
0698 err = marvell_set_page(phydev, MII_MARVELL_FIBER_PAGE);
0699 if (err < 0)
0700 goto error;
0701
0702 if (phydev->interface == PHY_INTERFACE_MODE_SGMII)
0703
0704
0705
0706
0707 err = genphy_check_and_restart_aneg(phydev, false);
0708 else
0709 err = marvell_config_aneg_fiber(phydev);
0710 if (err < 0)
0711 goto error;
0712
0713 return marvell_set_page(phydev, MII_MARVELL_COPPER_PAGE);
0714
0715 error:
0716 marvell_set_page(phydev, MII_MARVELL_COPPER_PAGE);
0717 return err;
0718 }
0719
0720 static int m88e1510_config_aneg(struct phy_device *phydev)
0721 {
0722 int err;
0723
0724 err = marvell_set_page(phydev, MII_MARVELL_COPPER_PAGE);
0725 if (err < 0)
0726 goto error;
0727
0728
0729 err = m88e1318_config_aneg(phydev);
0730 if (err < 0)
0731 goto error;
0732
0733
0734 if (phydev->interface == PHY_INTERFACE_MODE_SGMII)
0735 return 0;
0736
0737
0738 err = marvell_set_page(phydev, MII_MARVELL_FIBER_PAGE);
0739 if (err < 0)
0740 goto error;
0741
0742 err = marvell_config_aneg_fiber(phydev);
0743 if (err < 0)
0744 goto error;
0745
0746 return marvell_set_page(phydev, MII_MARVELL_COPPER_PAGE);
0747
0748 error:
0749 marvell_set_page(phydev, MII_MARVELL_COPPER_PAGE);
0750 return err;
0751 }
0752
0753 static void marvell_config_led(struct phy_device *phydev)
0754 {
0755 u16 def_config;
0756 int err;
0757
0758 switch (MARVELL_PHY_FAMILY_ID(phydev->phy_id)) {
0759
0760 case MARVELL_PHY_FAMILY_ID(MARVELL_PHY_ID_88E1121R):
0761 case MARVELL_PHY_FAMILY_ID(MARVELL_PHY_ID_88E1318S):
0762 def_config = MII_88E1121_PHY_LED_DEF;
0763 break;
0764
0765
0766
0767
0768
0769 case MARVELL_PHY_FAMILY_ID(MARVELL_PHY_ID_88E1510):
0770 if (phydev->dev_flags & MARVELL_PHY_LED0_LINK_LED1_ACTIVE)
0771 def_config = MII_88E1510_PHY_LED0_LINK_LED1_ACTIVE;
0772 else
0773 def_config = MII_88E1510_PHY_LED_DEF;
0774 break;
0775 default:
0776 return;
0777 }
0778
0779 err = phy_write_paged(phydev, MII_MARVELL_LED_PAGE, MII_PHY_LED_CTRL,
0780 def_config);
0781 if (err < 0)
0782 phydev_warn(phydev, "Fail to config marvell phy LED.\n");
0783 }
0784
0785 static int marvell_config_init(struct phy_device *phydev)
0786 {
0787
0788 marvell_config_led(phydev);
0789
0790
0791 return marvell_of_reg_init(phydev);
0792 }
0793
0794 static int m88e3016_config_init(struct phy_device *phydev)
0795 {
0796 int ret;
0797
0798
0799 ret = phy_modify(phydev, MII_88E3016_PHY_SPEC_CTRL,
0800 MII_88E3016_DISABLE_SCRAMBLER,
0801 MII_88E3016_AUTO_MDIX_CROSSOVER);
0802 if (ret < 0)
0803 return ret;
0804
0805 return marvell_config_init(phydev);
0806 }
0807
0808 static int m88e1111_config_init_hwcfg_mode(struct phy_device *phydev,
0809 u16 mode,
0810 int fibre_copper_auto)
0811 {
0812 if (fibre_copper_auto)
0813 mode |= MII_M1111_HWCFG_FIBER_COPPER_AUTO;
0814
0815 return phy_modify(phydev, MII_M1111_PHY_EXT_SR,
0816 MII_M1111_HWCFG_MODE_MASK |
0817 MII_M1111_HWCFG_FIBER_COPPER_AUTO |
0818 MII_M1111_HWCFG_FIBER_COPPER_RES,
0819 mode);
0820 }
0821
0822 static int m88e1111_config_init_rgmii_delays(struct phy_device *phydev)
0823 {
0824 int delay;
0825
0826 switch (phydev->interface) {
0827 case PHY_INTERFACE_MODE_RGMII_ID:
0828 delay = MII_M1111_RGMII_RX_DELAY | MII_M1111_RGMII_TX_DELAY;
0829 break;
0830 case PHY_INTERFACE_MODE_RGMII_RXID:
0831 delay = MII_M1111_RGMII_RX_DELAY;
0832 break;
0833 case PHY_INTERFACE_MODE_RGMII_TXID:
0834 delay = MII_M1111_RGMII_TX_DELAY;
0835 break;
0836 default:
0837 delay = 0;
0838 break;
0839 }
0840
0841 return phy_modify(phydev, MII_M1111_PHY_EXT_CR,
0842 MII_M1111_RGMII_RX_DELAY | MII_M1111_RGMII_TX_DELAY,
0843 delay);
0844 }
0845
0846 static int m88e1111_config_init_rgmii(struct phy_device *phydev)
0847 {
0848 int temp;
0849 int err;
0850
0851 err = m88e1111_config_init_rgmii_delays(phydev);
0852 if (err < 0)
0853 return err;
0854
0855 temp = phy_read(phydev, MII_M1111_PHY_EXT_SR);
0856 if (temp < 0)
0857 return temp;
0858
0859 temp &= ~(MII_M1111_HWCFG_MODE_MASK);
0860
0861 if (temp & MII_M1111_HWCFG_FIBER_COPPER_RES)
0862 temp |= MII_M1111_HWCFG_MODE_FIBER_RGMII;
0863 else
0864 temp |= MII_M1111_HWCFG_MODE_COPPER_RGMII;
0865
0866 return phy_write(phydev, MII_M1111_PHY_EXT_SR, temp);
0867 }
0868
0869 static int m88e1111_config_init_sgmii(struct phy_device *phydev)
0870 {
0871 int err;
0872
0873 err = m88e1111_config_init_hwcfg_mode(
0874 phydev,
0875 MII_M1111_HWCFG_MODE_SGMII_NO_CLK,
0876 MII_M1111_HWCFG_FIBER_COPPER_AUTO);
0877 if (err < 0)
0878 return err;
0879
0880
0881 return marvell_set_page(phydev, MII_MARVELL_COPPER_PAGE);
0882 }
0883
0884 static int m88e1111_config_init_rtbi(struct phy_device *phydev)
0885 {
0886 int err;
0887
0888 err = m88e1111_config_init_rgmii_delays(phydev);
0889 if (err < 0)
0890 return err;
0891
0892 err = m88e1111_config_init_hwcfg_mode(
0893 phydev,
0894 MII_M1111_HWCFG_MODE_RTBI,
0895 MII_M1111_HWCFG_FIBER_COPPER_AUTO);
0896 if (err < 0)
0897 return err;
0898
0899
0900 err = genphy_soft_reset(phydev);
0901 if (err < 0)
0902 return err;
0903
0904 return m88e1111_config_init_hwcfg_mode(
0905 phydev,
0906 MII_M1111_HWCFG_MODE_RTBI,
0907 MII_M1111_HWCFG_FIBER_COPPER_AUTO);
0908 }
0909
0910 static int m88e1111_config_init_1000basex(struct phy_device *phydev)
0911 {
0912 int extsr = phy_read(phydev, MII_M1111_PHY_EXT_SR);
0913 int err, mode;
0914
0915 if (extsr < 0)
0916 return extsr;
0917
0918
0919 mode = extsr & MII_M1111_HWCFG_MODE_MASK;
0920 if (mode == MII_M1111_HWCFG_MODE_COPPER_1000X_NOAN) {
0921 err = phy_modify(phydev, MII_M1111_PHY_EXT_SR,
0922 MII_M1111_HWCFG_MODE_MASK |
0923 MII_M1111_HWCFG_SERIAL_AN_BYPASS,
0924 MII_M1111_HWCFG_MODE_COPPER_1000X_AN |
0925 MII_M1111_HWCFG_SERIAL_AN_BYPASS);
0926 if (err < 0)
0927 return err;
0928 }
0929 return 0;
0930 }
0931
0932 static int m88e1111_config_init(struct phy_device *phydev)
0933 {
0934 int err;
0935
0936 if (phy_interface_is_rgmii(phydev)) {
0937 err = m88e1111_config_init_rgmii(phydev);
0938 if (err < 0)
0939 return err;
0940 }
0941
0942 if (phydev->interface == PHY_INTERFACE_MODE_SGMII) {
0943 err = m88e1111_config_init_sgmii(phydev);
0944 if (err < 0)
0945 return err;
0946 }
0947
0948 if (phydev->interface == PHY_INTERFACE_MODE_RTBI) {
0949 err = m88e1111_config_init_rtbi(phydev);
0950 if (err < 0)
0951 return err;
0952 }
0953
0954 if (phydev->interface == PHY_INTERFACE_MODE_1000BASEX) {
0955 err = m88e1111_config_init_1000basex(phydev);
0956 if (err < 0)
0957 return err;
0958 }
0959
0960 err = marvell_of_reg_init(phydev);
0961 if (err < 0)
0962 return err;
0963
0964 err = genphy_soft_reset(phydev);
0965 if (err < 0)
0966 return err;
0967
0968 if (phydev->interface == PHY_INTERFACE_MODE_SGMII) {
0969
0970
0971
0972
0973
0974 err = genphy_read_abilities(phydev);
0975 linkmode_or(phydev->advertising, phydev->advertising,
0976 phydev->supported);
0977 }
0978 return err;
0979 }
0980
0981 static int m88e1111_get_downshift(struct phy_device *phydev, u8 *data)
0982 {
0983 int val, cnt, enable;
0984
0985 val = phy_read(phydev, MII_M1111_PHY_EXT_CR);
0986 if (val < 0)
0987 return val;
0988
0989 enable = FIELD_GET(MII_M1111_PHY_EXT_CR_DOWNSHIFT_EN, val);
0990 cnt = FIELD_GET(MII_M1111_PHY_EXT_CR_DOWNSHIFT_MASK, val) + 1;
0991
0992 *data = enable ? cnt : DOWNSHIFT_DEV_DISABLE;
0993
0994 return 0;
0995 }
0996
0997 static int m88e1111_set_downshift(struct phy_device *phydev, u8 cnt)
0998 {
0999 int val, err;
1000
1001 if (cnt > MII_M1111_PHY_EXT_CR_DOWNSHIFT_MAX)
1002 return -E2BIG;
1003
1004 if (!cnt) {
1005 err = phy_clear_bits(phydev, MII_M1111_PHY_EXT_CR,
1006 MII_M1111_PHY_EXT_CR_DOWNSHIFT_EN);
1007 } else {
1008 val = MII_M1111_PHY_EXT_CR_DOWNSHIFT_EN;
1009 val |= FIELD_PREP(MII_M1111_PHY_EXT_CR_DOWNSHIFT_MASK, cnt - 1);
1010
1011 err = phy_modify(phydev, MII_M1111_PHY_EXT_CR,
1012 MII_M1111_PHY_EXT_CR_DOWNSHIFT_EN |
1013 MII_M1111_PHY_EXT_CR_DOWNSHIFT_MASK,
1014 val);
1015 }
1016
1017 if (err < 0)
1018 return err;
1019
1020 return genphy_soft_reset(phydev);
1021 }
1022
1023 static int m88e1111_get_tunable(struct phy_device *phydev,
1024 struct ethtool_tunable *tuna, void *data)
1025 {
1026 switch (tuna->id) {
1027 case ETHTOOL_PHY_DOWNSHIFT:
1028 return m88e1111_get_downshift(phydev, data);
1029 default:
1030 return -EOPNOTSUPP;
1031 }
1032 }
1033
1034 static int m88e1111_set_tunable(struct phy_device *phydev,
1035 struct ethtool_tunable *tuna, const void *data)
1036 {
1037 switch (tuna->id) {
1038 case ETHTOOL_PHY_DOWNSHIFT:
1039 return m88e1111_set_downshift(phydev, *(const u8 *)data);
1040 default:
1041 return -EOPNOTSUPP;
1042 }
1043 }
1044
1045 static int m88e1011_get_downshift(struct phy_device *phydev, u8 *data)
1046 {
1047 int val, cnt, enable;
1048
1049 val = phy_read(phydev, MII_M1011_PHY_SCR);
1050 if (val < 0)
1051 return val;
1052
1053 enable = FIELD_GET(MII_M1011_PHY_SCR_DOWNSHIFT_EN, val);
1054 cnt = FIELD_GET(MII_M1011_PHY_SCR_DOWNSHIFT_MASK, val) + 1;
1055
1056 *data = enable ? cnt : DOWNSHIFT_DEV_DISABLE;
1057
1058 return 0;
1059 }
1060
1061 static int m88e1011_set_downshift(struct phy_device *phydev, u8 cnt)
1062 {
1063 int val, err;
1064
1065 if (cnt > MII_M1011_PHY_SCR_DOWNSHIFT_MAX)
1066 return -E2BIG;
1067
1068 if (!cnt) {
1069 err = phy_clear_bits(phydev, MII_M1011_PHY_SCR,
1070 MII_M1011_PHY_SCR_DOWNSHIFT_EN);
1071 } else {
1072 val = MII_M1011_PHY_SCR_DOWNSHIFT_EN;
1073 val |= FIELD_PREP(MII_M1011_PHY_SCR_DOWNSHIFT_MASK, cnt - 1);
1074
1075 err = phy_modify(phydev, MII_M1011_PHY_SCR,
1076 MII_M1011_PHY_SCR_DOWNSHIFT_EN |
1077 MII_M1011_PHY_SCR_DOWNSHIFT_MASK,
1078 val);
1079 }
1080
1081 if (err < 0)
1082 return err;
1083
1084 return genphy_soft_reset(phydev);
1085 }
1086
1087 static int m88e1011_get_tunable(struct phy_device *phydev,
1088 struct ethtool_tunable *tuna, void *data)
1089 {
1090 switch (tuna->id) {
1091 case ETHTOOL_PHY_DOWNSHIFT:
1092 return m88e1011_get_downshift(phydev, data);
1093 default:
1094 return -EOPNOTSUPP;
1095 }
1096 }
1097
1098 static int m88e1011_set_tunable(struct phy_device *phydev,
1099 struct ethtool_tunable *tuna, const void *data)
1100 {
1101 switch (tuna->id) {
1102 case ETHTOOL_PHY_DOWNSHIFT:
1103 return m88e1011_set_downshift(phydev, *(const u8 *)data);
1104 default:
1105 return -EOPNOTSUPP;
1106 }
1107 }
1108
1109 static int m88e1112_config_init(struct phy_device *phydev)
1110 {
1111 int err;
1112
1113 err = m88e1011_set_downshift(phydev, 3);
1114 if (err < 0)
1115 return err;
1116
1117 return m88e1111_config_init(phydev);
1118 }
1119
1120 static int m88e1111gbe_config_init(struct phy_device *phydev)
1121 {
1122 int err;
1123
1124 err = m88e1111_set_downshift(phydev, 3);
1125 if (err < 0)
1126 return err;
1127
1128 return m88e1111_config_init(phydev);
1129 }
1130
1131 static int marvell_1011gbe_config_init(struct phy_device *phydev)
1132 {
1133 int err;
1134
1135 err = m88e1011_set_downshift(phydev, 3);
1136 if (err < 0)
1137 return err;
1138
1139 return marvell_config_init(phydev);
1140 }
1141 static int m88e1116r_config_init(struct phy_device *phydev)
1142 {
1143 int err;
1144
1145 err = genphy_soft_reset(phydev);
1146 if (err < 0)
1147 return err;
1148
1149 msleep(500);
1150
1151 err = marvell_set_page(phydev, MII_MARVELL_COPPER_PAGE);
1152 if (err < 0)
1153 return err;
1154
1155 err = marvell_set_polarity(phydev, phydev->mdix_ctrl);
1156 if (err < 0)
1157 return err;
1158
1159 err = m88e1011_set_downshift(phydev, 8);
1160 if (err < 0)
1161 return err;
1162
1163 if (phy_interface_is_rgmii(phydev)) {
1164 err = m88e1121_config_aneg_rgmii_delays(phydev);
1165 if (err < 0)
1166 return err;
1167 }
1168
1169 err = genphy_soft_reset(phydev);
1170 if (err < 0)
1171 return err;
1172
1173 return marvell_config_init(phydev);
1174 }
1175
1176 static int m88e1318_config_init(struct phy_device *phydev)
1177 {
1178 if (phy_interrupt_is_valid(phydev)) {
1179 int err = phy_modify_paged(
1180 phydev, MII_MARVELL_LED_PAGE,
1181 MII_88E1318S_PHY_LED_TCR,
1182 MII_88E1318S_PHY_LED_TCR_FORCE_INT,
1183 MII_88E1318S_PHY_LED_TCR_INTn_ENABLE |
1184 MII_88E1318S_PHY_LED_TCR_INT_ACTIVE_LOW);
1185 if (err < 0)
1186 return err;
1187 }
1188
1189 return marvell_config_init(phydev);
1190 }
1191
1192 static int m88e1510_config_init(struct phy_device *phydev)
1193 {
1194 static const struct {
1195 u16 reg17, reg16;
1196 } errata_vals[] = {
1197 { 0x214b, 0x2144 },
1198 { 0x0c28, 0x2146 },
1199 { 0xb233, 0x214d },
1200 { 0xcc0c, 0x2159 },
1201 };
1202 int err;
1203 int i;
1204
1205
1206
1207
1208
1209
1210 err = marvell_set_page(phydev, 0x00FF);
1211 if (err < 0)
1212 return err;
1213
1214 for (i = 0; i < ARRAY_SIZE(errata_vals); ++i) {
1215 err = phy_write(phydev, 17, errata_vals[i].reg17);
1216 if (err)
1217 return err;
1218 err = phy_write(phydev, 16, errata_vals[i].reg16);
1219 if (err)
1220 return err;
1221 }
1222
1223 err = marvell_set_page(phydev, 0x00FB);
1224 if (err < 0)
1225 return err;
1226 err = phy_write(phydev, 07, 0xC00D);
1227 if (err < 0)
1228 return err;
1229 err = marvell_set_page(phydev, MII_MARVELL_COPPER_PAGE);
1230 if (err < 0)
1231 return err;
1232
1233
1234 if (phydev->interface == PHY_INTERFACE_MODE_SGMII) {
1235
1236 err = marvell_set_page(phydev, 18);
1237 if (err < 0)
1238 return err;
1239
1240
1241 err = phy_modify(phydev, MII_88E1510_GEN_CTRL_REG_1,
1242 MII_88E1510_GEN_CTRL_REG_1_MODE_MASK,
1243 MII_88E1510_GEN_CTRL_REG_1_MODE_SGMII);
1244 if (err < 0)
1245 return err;
1246
1247
1248 err = phy_set_bits(phydev, MII_88E1510_GEN_CTRL_REG_1,
1249 MII_88E1510_GEN_CTRL_REG_1_RESET);
1250 if (err < 0)
1251 return err;
1252
1253
1254 err = marvell_set_page(phydev, MII_MARVELL_COPPER_PAGE);
1255 if (err < 0)
1256 return err;
1257 }
1258 err = m88e1011_set_downshift(phydev, 3);
1259 if (err < 0)
1260 return err;
1261
1262 return m88e1318_config_init(phydev);
1263 }
1264
1265 static int m88e1118_config_aneg(struct phy_device *phydev)
1266 {
1267 int err;
1268
1269 err = marvell_set_polarity(phydev, phydev->mdix_ctrl);
1270 if (err < 0)
1271 return err;
1272
1273 err = genphy_config_aneg(phydev);
1274 if (err < 0)
1275 return err;
1276
1277 return genphy_soft_reset(phydev);
1278 }
1279
1280 static int m88e1118_config_init(struct phy_device *phydev)
1281 {
1282 u16 leds;
1283 int err;
1284
1285
1286 err = phy_write_paged(phydev, MII_MARVELL_MSCR_PAGE,
1287 MII_88E1121_PHY_MSCR_REG, 0x1070);
1288 if (err < 0)
1289 return err;
1290
1291 if (phy_interface_is_rgmii(phydev)) {
1292 err = m88e1121_config_aneg_rgmii_delays(phydev);
1293 if (err < 0)
1294 return err;
1295 }
1296
1297
1298 if (phydev->dev_flags & MARVELL_PHY_M1118_DNS323_LEDS)
1299 leds = 0x1100;
1300 else
1301 leds = 0x021e;
1302
1303 err = phy_write_paged(phydev, MII_MARVELL_LED_PAGE, 0x10, leds);
1304 if (err < 0)
1305 return err;
1306
1307 err = marvell_of_reg_init(phydev);
1308 if (err < 0)
1309 return err;
1310
1311
1312 err = marvell_set_page(phydev, MII_MARVELL_COPPER_PAGE);
1313 if (err < 0)
1314 return err;
1315
1316 return genphy_soft_reset(phydev);
1317 }
1318
1319 static int m88e1149_config_init(struct phy_device *phydev)
1320 {
1321 int err;
1322
1323
1324 err = marvell_set_page(phydev, MII_MARVELL_MSCR_PAGE);
1325 if (err < 0)
1326 return err;
1327
1328
1329 err = phy_write(phydev, 0x15, 0x1048);
1330 if (err < 0)
1331 return err;
1332
1333 err = marvell_of_reg_init(phydev);
1334 if (err < 0)
1335 return err;
1336
1337
1338 err = marvell_set_page(phydev, MII_MARVELL_COPPER_PAGE);
1339 if (err < 0)
1340 return err;
1341
1342 return genphy_soft_reset(phydev);
1343 }
1344
1345 static int m88e1145_config_init_rgmii(struct phy_device *phydev)
1346 {
1347 int err;
1348
1349 err = m88e1111_config_init_rgmii_delays(phydev);
1350 if (err < 0)
1351 return err;
1352
1353 if (phydev->dev_flags & MARVELL_PHY_M1145_FLAGS_RESISTANCE) {
1354 err = phy_write(phydev, 0x1d, 0x0012);
1355 if (err < 0)
1356 return err;
1357
1358 err = phy_modify(phydev, 0x1e, 0x0fc0,
1359 2 << 9 |
1360 2 << 6);
1361 if (err < 0)
1362 return err;
1363
1364 err = phy_write(phydev, 0x1d, 0x3);
1365 if (err < 0)
1366 return err;
1367
1368 err = phy_write(phydev, 0x1e, 0x8000);
1369 }
1370 return err;
1371 }
1372
1373 static int m88e1145_config_init_sgmii(struct phy_device *phydev)
1374 {
1375 return m88e1111_config_init_hwcfg_mode(
1376 phydev, MII_M1111_HWCFG_MODE_SGMII_NO_CLK,
1377 MII_M1111_HWCFG_FIBER_COPPER_AUTO);
1378 }
1379
1380 static int m88e1145_config_init(struct phy_device *phydev)
1381 {
1382 int err;
1383
1384
1385 err = phy_write(phydev, 0x1d, 0x001b);
1386 if (err < 0)
1387 return err;
1388
1389 err = phy_write(phydev, 0x1e, 0x418f);
1390 if (err < 0)
1391 return err;
1392
1393 err = phy_write(phydev, 0x1d, 0x0016);
1394 if (err < 0)
1395 return err;
1396
1397 err = phy_write(phydev, 0x1e, 0xa2da);
1398 if (err < 0)
1399 return err;
1400
1401 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) {
1402 err = m88e1145_config_init_rgmii(phydev);
1403 if (err < 0)
1404 return err;
1405 }
1406
1407 if (phydev->interface == PHY_INTERFACE_MODE_SGMII) {
1408 err = m88e1145_config_init_sgmii(phydev);
1409 if (err < 0)
1410 return err;
1411 }
1412 err = m88e1111_set_downshift(phydev, 3);
1413 if (err < 0)
1414 return err;
1415
1416 err = marvell_of_reg_init(phydev);
1417 if (err < 0)
1418 return err;
1419
1420 return 0;
1421 }
1422
1423 static int m88e1540_get_fld(struct phy_device *phydev, u8 *msecs)
1424 {
1425 int val;
1426
1427 val = phy_read(phydev, MII_88E1540_COPPER_CTRL3);
1428 if (val < 0)
1429 return val;
1430
1431 if (!(val & MII_88E1540_COPPER_CTRL3_FAST_LINK_DOWN)) {
1432 *msecs = ETHTOOL_PHY_FAST_LINK_DOWN_OFF;
1433 return 0;
1434 }
1435
1436 val = FIELD_GET(MII_88E1540_COPPER_CTRL3_LINK_DOWN_DELAY_MASK, val);
1437
1438 switch (val) {
1439 case MII_88E1540_COPPER_CTRL3_LINK_DOWN_DELAY_00MS:
1440 *msecs = 0;
1441 break;
1442 case MII_88E1540_COPPER_CTRL3_LINK_DOWN_DELAY_10MS:
1443 *msecs = 10;
1444 break;
1445 case MII_88E1540_COPPER_CTRL3_LINK_DOWN_DELAY_20MS:
1446 *msecs = 20;
1447 break;
1448 case MII_88E1540_COPPER_CTRL3_LINK_DOWN_DELAY_40MS:
1449 *msecs = 40;
1450 break;
1451 default:
1452 return -EINVAL;
1453 }
1454
1455 return 0;
1456 }
1457
1458 static int m88e1540_set_fld(struct phy_device *phydev, const u8 *msecs)
1459 {
1460 struct ethtool_eee eee;
1461 int val, ret;
1462
1463 if (*msecs == ETHTOOL_PHY_FAST_LINK_DOWN_OFF)
1464 return phy_clear_bits(phydev, MII_88E1540_COPPER_CTRL3,
1465 MII_88E1540_COPPER_CTRL3_FAST_LINK_DOWN);
1466
1467
1468
1469
1470 ret = phy_ethtool_get_eee(phydev, &eee);
1471 if (!ret && eee.eee_enabled) {
1472 phydev_warn(phydev, "Fast Link Down detection requires EEE to be disabled!\n");
1473 return -EBUSY;
1474 }
1475
1476 if (*msecs <= 5)
1477 val = MII_88E1540_COPPER_CTRL3_LINK_DOWN_DELAY_00MS;
1478 else if (*msecs <= 15)
1479 val = MII_88E1540_COPPER_CTRL3_LINK_DOWN_DELAY_10MS;
1480 else if (*msecs <= 30)
1481 val = MII_88E1540_COPPER_CTRL3_LINK_DOWN_DELAY_20MS;
1482 else
1483 val = MII_88E1540_COPPER_CTRL3_LINK_DOWN_DELAY_40MS;
1484
1485 val = FIELD_PREP(MII_88E1540_COPPER_CTRL3_LINK_DOWN_DELAY_MASK, val);
1486
1487 ret = phy_modify(phydev, MII_88E1540_COPPER_CTRL3,
1488 MII_88E1540_COPPER_CTRL3_LINK_DOWN_DELAY_MASK, val);
1489 if (ret)
1490 return ret;
1491
1492 return phy_set_bits(phydev, MII_88E1540_COPPER_CTRL3,
1493 MII_88E1540_COPPER_CTRL3_FAST_LINK_DOWN);
1494 }
1495
1496 static int m88e1540_get_tunable(struct phy_device *phydev,
1497 struct ethtool_tunable *tuna, void *data)
1498 {
1499 switch (tuna->id) {
1500 case ETHTOOL_PHY_FAST_LINK_DOWN:
1501 return m88e1540_get_fld(phydev, data);
1502 case ETHTOOL_PHY_DOWNSHIFT:
1503 return m88e1011_get_downshift(phydev, data);
1504 default:
1505 return -EOPNOTSUPP;
1506 }
1507 }
1508
1509 static int m88e1540_set_tunable(struct phy_device *phydev,
1510 struct ethtool_tunable *tuna, const void *data)
1511 {
1512 switch (tuna->id) {
1513 case ETHTOOL_PHY_FAST_LINK_DOWN:
1514 return m88e1540_set_fld(phydev, data);
1515 case ETHTOOL_PHY_DOWNSHIFT:
1516 return m88e1011_set_downshift(phydev, *(const u8 *)data);
1517 default:
1518 return -EOPNOTSUPP;
1519 }
1520 }
1521
1522
1523
1524
1525
1526 static int m88e6390_errata(struct phy_device *phydev)
1527 {
1528 int err;
1529
1530 err = phy_write(phydev, MII_BMCR,
1531 BMCR_ANENABLE | BMCR_SPEED1000 | BMCR_FULLDPLX);
1532 if (err)
1533 return err;
1534
1535 usleep_range(300, 400);
1536
1537 err = phy_write_paged(phydev, 0xf8, 0x08, 0x36);
1538 if (err)
1539 return err;
1540
1541 return genphy_soft_reset(phydev);
1542 }
1543
1544 static int m88e6390_config_aneg(struct phy_device *phydev)
1545 {
1546 int err;
1547
1548 err = m88e6390_errata(phydev);
1549 if (err)
1550 return err;
1551
1552 return m88e1510_config_aneg(phydev);
1553 }
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564 static void fiber_lpa_mod_linkmode_lpa_t(unsigned long *advertising, u32 lpa)
1565 {
1566 linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT,
1567 advertising, lpa & LPA_1000XHALF);
1568
1569 linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
1570 advertising, lpa & LPA_1000XFULL);
1571 }
1572
1573 static int marvell_read_status_page_an(struct phy_device *phydev,
1574 int fiber, int status)
1575 {
1576 int lpa;
1577 int err;
1578
1579 if (!(status & MII_M1011_PHY_STATUS_RESOLVED)) {
1580 phydev->link = 0;
1581 return 0;
1582 }
1583
1584 if (status & MII_M1011_PHY_STATUS_FULLDUPLEX)
1585 phydev->duplex = DUPLEX_FULL;
1586 else
1587 phydev->duplex = DUPLEX_HALF;
1588
1589 switch (status & MII_M1011_PHY_STATUS_SPD_MASK) {
1590 case MII_M1011_PHY_STATUS_1000:
1591 phydev->speed = SPEED_1000;
1592 break;
1593
1594 case MII_M1011_PHY_STATUS_100:
1595 phydev->speed = SPEED_100;
1596 break;
1597
1598 default:
1599 phydev->speed = SPEED_10;
1600 break;
1601 }
1602
1603 if (!fiber) {
1604 err = genphy_read_lpa(phydev);
1605 if (err < 0)
1606 return err;
1607
1608 phy_resolve_aneg_pause(phydev);
1609 } else {
1610 lpa = phy_read(phydev, MII_LPA);
1611 if (lpa < 0)
1612 return lpa;
1613
1614
1615 fiber_lpa_mod_linkmode_lpa_t(phydev->lp_advertising, lpa);
1616
1617 if (phydev->duplex == DUPLEX_FULL) {
1618 if (!(lpa & LPA_PAUSE_FIBER)) {
1619 phydev->pause = 0;
1620 phydev->asym_pause = 0;
1621 } else if ((lpa & LPA_PAUSE_ASYM_FIBER)) {
1622 phydev->pause = 1;
1623 phydev->asym_pause = 1;
1624 } else {
1625 phydev->pause = 1;
1626 phydev->asym_pause = 0;
1627 }
1628 }
1629 }
1630
1631 return 0;
1632 }
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642 static int marvell_read_status_page(struct phy_device *phydev, int page)
1643 {
1644 int status;
1645 int fiber;
1646 int err;
1647
1648 status = phy_read(phydev, MII_M1011_PHY_STATUS);
1649 if (status < 0)
1650 return status;
1651
1652
1653
1654
1655 if (page == MII_MARVELL_FIBER_PAGE) {
1656 phydev->link = !!(status & MII_M1011_PHY_STATUS_LINK);
1657 } else {
1658 err = genphy_update_link(phydev);
1659 if (err)
1660 return err;
1661 }
1662
1663 if (page == MII_MARVELL_FIBER_PAGE)
1664 fiber = 1;
1665 else
1666 fiber = 0;
1667
1668 linkmode_zero(phydev->lp_advertising);
1669 phydev->pause = 0;
1670 phydev->asym_pause = 0;
1671 phydev->speed = SPEED_UNKNOWN;
1672 phydev->duplex = DUPLEX_UNKNOWN;
1673 phydev->port = fiber ? PORT_FIBRE : PORT_TP;
1674
1675 if (phydev->autoneg == AUTONEG_ENABLE)
1676 err = marvell_read_status_page_an(phydev, fiber, status);
1677 else
1678 err = genphy_read_status_fixed(phydev);
1679
1680 return err;
1681 }
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692 static int marvell_read_status(struct phy_device *phydev)
1693 {
1694 int err;
1695
1696
1697 if (linkmode_test_bit(ETHTOOL_LINK_MODE_FIBRE_BIT,
1698 phydev->supported) &&
1699 phydev->interface != PHY_INTERFACE_MODE_SGMII) {
1700 err = marvell_set_page(phydev, MII_MARVELL_FIBER_PAGE);
1701 if (err < 0)
1702 goto error;
1703
1704 err = marvell_read_status_page(phydev, MII_MARVELL_FIBER_PAGE);
1705 if (err < 0)
1706 goto error;
1707
1708
1709
1710
1711
1712
1713
1714
1715 if (phydev->link)
1716 return 0;
1717
1718
1719 err = marvell_set_page(phydev, MII_MARVELL_COPPER_PAGE);
1720 if (err < 0)
1721 goto error;
1722 }
1723
1724 return marvell_read_status_page(phydev, MII_MARVELL_COPPER_PAGE);
1725
1726 error:
1727 marvell_set_page(phydev, MII_MARVELL_COPPER_PAGE);
1728 return err;
1729 }
1730
1731
1732
1733
1734
1735
1736 static int marvell_suspend(struct phy_device *phydev)
1737 {
1738 int err;
1739
1740
1741 if (linkmode_test_bit(ETHTOOL_LINK_MODE_FIBRE_BIT,
1742 phydev->supported)) {
1743 err = marvell_set_page(phydev, MII_MARVELL_FIBER_PAGE);
1744 if (err < 0)
1745 goto error;
1746
1747
1748 err = genphy_suspend(phydev);
1749 if (err < 0)
1750 goto error;
1751
1752
1753 err = marvell_set_page(phydev, MII_MARVELL_COPPER_PAGE);
1754 if (err < 0)
1755 goto error;
1756 }
1757
1758
1759 return genphy_suspend(phydev);
1760
1761 error:
1762 marvell_set_page(phydev, MII_MARVELL_COPPER_PAGE);
1763 return err;
1764 }
1765
1766
1767
1768
1769
1770
1771 static int marvell_resume(struct phy_device *phydev)
1772 {
1773 int err;
1774
1775
1776 if (linkmode_test_bit(ETHTOOL_LINK_MODE_FIBRE_BIT,
1777 phydev->supported)) {
1778 err = marvell_set_page(phydev, MII_MARVELL_FIBER_PAGE);
1779 if (err < 0)
1780 goto error;
1781
1782
1783 err = genphy_resume(phydev);
1784 if (err < 0)
1785 goto error;
1786
1787
1788 err = marvell_set_page(phydev, MII_MARVELL_COPPER_PAGE);
1789 if (err < 0)
1790 goto error;
1791 }
1792
1793
1794 return genphy_resume(phydev);
1795
1796 error:
1797 marvell_set_page(phydev, MII_MARVELL_COPPER_PAGE);
1798 return err;
1799 }
1800
1801 static int marvell_aneg_done(struct phy_device *phydev)
1802 {
1803 int retval = phy_read(phydev, MII_M1011_PHY_STATUS);
1804
1805 return (retval < 0) ? retval : (retval & MII_M1011_PHY_STATUS_RESOLVED);
1806 }
1807
1808 static void m88e1318_get_wol(struct phy_device *phydev,
1809 struct ethtool_wolinfo *wol)
1810 {
1811 int ret;
1812
1813 wol->supported = WAKE_MAGIC | WAKE_PHY;
1814 wol->wolopts = 0;
1815
1816 ret = phy_read_paged(phydev, MII_MARVELL_WOL_PAGE,
1817 MII_88E1318S_PHY_WOL_CTRL);
1818 if (ret < 0)
1819 return;
1820
1821 if (ret & MII_88E1318S_PHY_WOL_CTRL_MAGIC_PACKET_MATCH_ENABLE)
1822 wol->wolopts |= WAKE_MAGIC;
1823
1824 if (ret & MII_88E1318S_PHY_WOL_CTRL_LINK_UP_ENABLE)
1825 wol->wolopts |= WAKE_PHY;
1826 }
1827
1828 static int m88e1318_set_wol(struct phy_device *phydev,
1829 struct ethtool_wolinfo *wol)
1830 {
1831 int err = 0, oldpage;
1832
1833 oldpage = phy_save_page(phydev);
1834 if (oldpage < 0)
1835 goto error;
1836
1837 if (wol->wolopts & (WAKE_MAGIC | WAKE_PHY)) {
1838
1839 err = marvell_write_page(phydev, MII_MARVELL_COPPER_PAGE);
1840 if (err < 0)
1841 goto error;
1842
1843
1844
1845
1846
1847
1848
1849 if (!phy_interrupt_is_valid(phydev))
1850 __phy_read(phydev, MII_M1011_IEVENT);
1851
1852
1853 err = __phy_set_bits(phydev, MII_88E1318S_PHY_CSIER,
1854 MII_88E1318S_PHY_CSIER_WOL_EIE);
1855 if (err < 0)
1856 goto error;
1857
1858 err = marvell_write_page(phydev, MII_MARVELL_LED_PAGE);
1859 if (err < 0)
1860 goto error;
1861
1862
1863 err = __phy_modify(phydev, MII_88E1318S_PHY_LED_TCR,
1864 MII_88E1318S_PHY_LED_TCR_FORCE_INT,
1865 MII_88E1318S_PHY_LED_TCR_INTn_ENABLE |
1866 MII_88E1318S_PHY_LED_TCR_INT_ACTIVE_LOW);
1867 if (err < 0)
1868 goto error;
1869 }
1870
1871 if (wol->wolopts & WAKE_MAGIC) {
1872 err = marvell_write_page(phydev, MII_MARVELL_WOL_PAGE);
1873 if (err < 0)
1874 goto error;
1875
1876
1877 err = __phy_write(phydev, MII_88E1318S_PHY_MAGIC_PACKET_WORD2,
1878 ((phydev->attached_dev->dev_addr[5] << 8) |
1879 phydev->attached_dev->dev_addr[4]));
1880 if (err < 0)
1881 goto error;
1882 err = __phy_write(phydev, MII_88E1318S_PHY_MAGIC_PACKET_WORD1,
1883 ((phydev->attached_dev->dev_addr[3] << 8) |
1884 phydev->attached_dev->dev_addr[2]));
1885 if (err < 0)
1886 goto error;
1887 err = __phy_write(phydev, MII_88E1318S_PHY_MAGIC_PACKET_WORD0,
1888 ((phydev->attached_dev->dev_addr[1] << 8) |
1889 phydev->attached_dev->dev_addr[0]));
1890 if (err < 0)
1891 goto error;
1892
1893
1894 err = __phy_set_bits(phydev, MII_88E1318S_PHY_WOL_CTRL,
1895 MII_88E1318S_PHY_WOL_CTRL_CLEAR_WOL_STATUS |
1896 MII_88E1318S_PHY_WOL_CTRL_MAGIC_PACKET_MATCH_ENABLE);
1897 if (err < 0)
1898 goto error;
1899 } else {
1900 err = marvell_write_page(phydev, MII_MARVELL_WOL_PAGE);
1901 if (err < 0)
1902 goto error;
1903
1904
1905 err = __phy_modify(phydev, MII_88E1318S_PHY_WOL_CTRL,
1906 MII_88E1318S_PHY_WOL_CTRL_MAGIC_PACKET_MATCH_ENABLE,
1907 MII_88E1318S_PHY_WOL_CTRL_CLEAR_WOL_STATUS);
1908 if (err < 0)
1909 goto error;
1910 }
1911
1912 if (wol->wolopts & WAKE_PHY) {
1913 err = marvell_write_page(phydev, MII_MARVELL_WOL_PAGE);
1914 if (err < 0)
1915 goto error;
1916
1917
1918 err = __phy_modify(phydev, MII_88E1318S_PHY_WOL_CTRL, 0,
1919 MII_88E1318S_PHY_WOL_CTRL_CLEAR_WOL_STATUS |
1920 MII_88E1318S_PHY_WOL_CTRL_LINK_UP_ENABLE);
1921 if (err < 0)
1922 goto error;
1923 } else {
1924 err = marvell_write_page(phydev, MII_MARVELL_WOL_PAGE);
1925 if (err < 0)
1926 goto error;
1927
1928
1929 err = __phy_modify(phydev, MII_88E1318S_PHY_WOL_CTRL,
1930 MII_88E1318S_PHY_WOL_CTRL_LINK_UP_ENABLE,
1931 MII_88E1318S_PHY_WOL_CTRL_CLEAR_WOL_STATUS);
1932 if (err < 0)
1933 goto error;
1934 }
1935
1936 error:
1937 return phy_restore_page(phydev, oldpage, err);
1938 }
1939
1940 static int marvell_get_sset_count(struct phy_device *phydev)
1941 {
1942 if (linkmode_test_bit(ETHTOOL_LINK_MODE_FIBRE_BIT,
1943 phydev->supported))
1944 return ARRAY_SIZE(marvell_hw_stats);
1945 else
1946 return ARRAY_SIZE(marvell_hw_stats) - NB_FIBER_STATS;
1947 }
1948
1949 static void marvell_get_strings(struct phy_device *phydev, u8 *data)
1950 {
1951 int count = marvell_get_sset_count(phydev);
1952 int i;
1953
1954 for (i = 0; i < count; i++) {
1955 strlcpy(data + i * ETH_GSTRING_LEN,
1956 marvell_hw_stats[i].string, ETH_GSTRING_LEN);
1957 }
1958 }
1959
1960 static u64 marvell_get_stat(struct phy_device *phydev, int i)
1961 {
1962 struct marvell_hw_stat stat = marvell_hw_stats[i];
1963 struct marvell_priv *priv = phydev->priv;
1964 int val;
1965 u64 ret;
1966
1967 val = phy_read_paged(phydev, stat.page, stat.reg);
1968 if (val < 0) {
1969 ret = U64_MAX;
1970 } else {
1971 val = val & ((1 << stat.bits) - 1);
1972 priv->stats[i] += val;
1973 ret = priv->stats[i];
1974 }
1975
1976 return ret;
1977 }
1978
1979 static void marvell_get_stats(struct phy_device *phydev,
1980 struct ethtool_stats *stats, u64 *data)
1981 {
1982 int count = marvell_get_sset_count(phydev);
1983 int i;
1984
1985 for (i = 0; i < count; i++)
1986 data[i] = marvell_get_stat(phydev, i);
1987 }
1988
1989 static int m88e1510_loopback(struct phy_device *phydev, bool enable)
1990 {
1991 int err;
1992
1993 if (enable) {
1994 u16 bmcr_ctl, mscr2_ctl = 0;
1995
1996 bmcr_ctl = mii_bmcr_encode_fixed(phydev->speed, phydev->duplex);
1997
1998 err = phy_write(phydev, MII_BMCR, bmcr_ctl);
1999 if (err < 0)
2000 return err;
2001
2002 if (phydev->speed == SPEED_1000)
2003 mscr2_ctl = BMCR_SPEED1000;
2004 else if (phydev->speed == SPEED_100)
2005 mscr2_ctl = BMCR_SPEED100;
2006
2007 err = phy_modify_paged(phydev, MII_MARVELL_MSCR_PAGE,
2008 MII_88E1510_MSCR_2, BMCR_SPEED1000 |
2009 BMCR_SPEED100, mscr2_ctl);
2010 if (err < 0)
2011 return err;
2012
2013
2014 err = genphy_soft_reset(phydev);
2015 if (err < 0)
2016 return err;
2017
2018
2019
2020
2021 if (phydev->speed == SPEED_1000)
2022 msleep(1000);
2023
2024 return phy_modify(phydev, MII_BMCR, BMCR_LOOPBACK,
2025 BMCR_LOOPBACK);
2026 } else {
2027 err = phy_modify(phydev, MII_BMCR, BMCR_LOOPBACK, 0);
2028 if (err < 0)
2029 return err;
2030
2031 return phy_config_aneg(phydev);
2032 }
2033 }
2034
2035 static int marvell_vct5_wait_complete(struct phy_device *phydev)
2036 {
2037 int i;
2038 int val;
2039
2040 for (i = 0; i < 32; i++) {
2041 val = __phy_read(phydev, MII_VCT5_CTRL);
2042 if (val < 0)
2043 return val;
2044
2045 if (val & MII_VCT5_CTRL_COMPLETE)
2046 return 0;
2047 }
2048
2049 phydev_err(phydev, "Timeout while waiting for cable test to finish\n");
2050 return -ETIMEDOUT;
2051 }
2052
2053 static int marvell_vct5_amplitude(struct phy_device *phydev, int pair)
2054 {
2055 int amplitude;
2056 int val;
2057 int reg;
2058
2059 reg = MII_VCT5_TX_RX_MDI0_COUPLING + pair;
2060 val = __phy_read(phydev, reg);
2061
2062 if (val < 0)
2063 return 0;
2064
2065 amplitude = (val & MII_VCT5_TX_RX_AMPLITUDE_MASK) >>
2066 MII_VCT5_TX_RX_AMPLITUDE_SHIFT;
2067
2068 if (!(val & MII_VCT5_TX_RX_COUPLING_POSITIVE_REFLECTION))
2069 amplitude = -amplitude;
2070
2071 return 1000 * amplitude / 128;
2072 }
2073
2074 static u32 marvell_vct5_distance2cm(int distance)
2075 {
2076 return distance * 805 / 10;
2077 }
2078
2079 static u32 marvell_vct5_cm2distance(int cm)
2080 {
2081 return cm * 10 / 805;
2082 }
2083
2084 static int marvell_vct5_amplitude_distance(struct phy_device *phydev,
2085 int distance, int pair)
2086 {
2087 u16 reg;
2088 int err;
2089 int mV;
2090 int i;
2091
2092 err = __phy_write(phydev, MII_VCT5_SAMPLE_POINT_DISTANCE,
2093 distance);
2094 if (err)
2095 return err;
2096
2097 reg = MII_VCT5_CTRL_ENABLE |
2098 MII_VCT5_CTRL_TX_SAME_CHANNEL |
2099 MII_VCT5_CTRL_SAMPLES_DEFAULT |
2100 MII_VCT5_CTRL_SAMPLE_POINT |
2101 MII_VCT5_CTRL_PEEK_HYST_DEFAULT;
2102 err = __phy_write(phydev, MII_VCT5_CTRL, reg);
2103 if (err)
2104 return err;
2105
2106 err = marvell_vct5_wait_complete(phydev);
2107 if (err)
2108 return err;
2109
2110 for (i = 0; i < 4; i++) {
2111 if (pair != PHY_PAIR_ALL && i != pair)
2112 continue;
2113
2114 mV = marvell_vct5_amplitude(phydev, i);
2115 ethnl_cable_test_amplitude(phydev, i, mV);
2116 }
2117
2118 return 0;
2119 }
2120
2121 static int marvell_vct5_amplitude_graph(struct phy_device *phydev)
2122 {
2123 struct marvell_priv *priv = phydev->priv;
2124 int distance;
2125 u16 width;
2126 int page;
2127 int err;
2128 u16 reg;
2129
2130 if (priv->first <= TDR_SHORT_CABLE_LENGTH)
2131 width = MII_VCT5_TX_PULSE_CTRL_PULSE_WIDTH_32nS;
2132 else
2133 width = MII_VCT5_TX_PULSE_CTRL_PULSE_WIDTH_128nS;
2134
2135 reg = MII_VCT5_TX_PULSE_CTRL_GT_140m_46_86mV |
2136 MII_VCT5_TX_PULSE_CTRL_DONT_WAIT_LINK_DOWN |
2137 MII_VCT5_TX_PULSE_CTRL_MAX_AMP | width;
2138
2139 err = phy_write_paged(phydev, MII_MARVELL_VCT5_PAGE,
2140 MII_VCT5_TX_PULSE_CTRL, reg);
2141 if (err)
2142 return err;
2143
2144
2145
2146
2147
2148
2149
2150 page = phy_select_page(phydev, MII_MARVELL_VCT5_PAGE);
2151 if (page < 0)
2152 goto restore_page;
2153
2154 for (distance = priv->first;
2155 distance <= priv->last;
2156 distance += priv->step) {
2157 err = marvell_vct5_amplitude_distance(phydev, distance,
2158 priv->pair);
2159 if (err)
2160 goto restore_page;
2161
2162 if (distance > TDR_SHORT_CABLE_LENGTH &&
2163 width == MII_VCT5_TX_PULSE_CTRL_PULSE_WIDTH_32nS) {
2164 width = MII_VCT5_TX_PULSE_CTRL_PULSE_WIDTH_128nS;
2165 reg = MII_VCT5_TX_PULSE_CTRL_GT_140m_46_86mV |
2166 MII_VCT5_TX_PULSE_CTRL_DONT_WAIT_LINK_DOWN |
2167 MII_VCT5_TX_PULSE_CTRL_MAX_AMP | width;
2168 err = __phy_write(phydev, MII_VCT5_TX_PULSE_CTRL, reg);
2169 if (err)
2170 goto restore_page;
2171 }
2172 }
2173
2174 restore_page:
2175 return phy_restore_page(phydev, page, err);
2176 }
2177
2178 static int marvell_cable_test_start_common(struct phy_device *phydev)
2179 {
2180 int bmcr, bmsr, ret;
2181
2182
2183
2184
2185 bmcr = phy_read(phydev, MII_BMCR);
2186 if (bmcr < 0)
2187 return bmcr;
2188
2189 bmsr = phy_read(phydev, MII_BMSR);
2190
2191 if (bmsr < 0)
2192 return bmsr;
2193
2194 if (bmcr & BMCR_ANENABLE) {
2195 ret = phy_clear_bits(phydev, MII_BMCR, BMCR_ANENABLE);
2196 if (ret < 0)
2197 return ret;
2198 ret = genphy_soft_reset(phydev);
2199 if (ret < 0)
2200 return ret;
2201 }
2202
2203
2204 if (bmsr & BMSR_LSTATUS)
2205 msleep(1500);
2206
2207 return 0;
2208 }
2209
2210 static int marvell_vct7_cable_test_start(struct phy_device *phydev)
2211 {
2212 struct marvell_priv *priv = phydev->priv;
2213 int ret;
2214
2215 ret = marvell_cable_test_start_common(phydev);
2216 if (ret)
2217 return ret;
2218
2219 priv->cable_test_tdr = false;
2220
2221
2222
2223
2224 ret = phy_write_paged(phydev, MII_MARVELL_VCT5_PAGE,
2225 MII_VCT5_CTRL,
2226 MII_VCT5_CTRL_TX_SAME_CHANNEL |
2227 MII_VCT5_CTRL_SAMPLES_DEFAULT |
2228 MII_VCT5_CTRL_MODE_MAXIMUM_PEEK |
2229 MII_VCT5_CTRL_PEEK_HYST_DEFAULT);
2230 if (ret)
2231 return ret;
2232
2233 ret = phy_write_paged(phydev, MII_MARVELL_VCT5_PAGE,
2234 MII_VCT5_SAMPLE_POINT_DISTANCE, 0);
2235 if (ret)
2236 return ret;
2237
2238 return phy_write_paged(phydev, MII_MARVELL_VCT7_PAGE,
2239 MII_VCT7_CTRL,
2240 MII_VCT7_CTRL_RUN_NOW |
2241 MII_VCT7_CTRL_CENTIMETERS);
2242 }
2243
2244 static int marvell_vct5_cable_test_tdr_start(struct phy_device *phydev,
2245 const struct phy_tdr_config *cfg)
2246 {
2247 struct marvell_priv *priv = phydev->priv;
2248 int ret;
2249
2250 priv->cable_test_tdr = true;
2251 priv->first = marvell_vct5_cm2distance(cfg->first);
2252 priv->last = marvell_vct5_cm2distance(cfg->last);
2253 priv->step = marvell_vct5_cm2distance(cfg->step);
2254 priv->pair = cfg->pair;
2255
2256 if (priv->first > MII_VCT5_SAMPLE_POINT_DISTANCE_MAX)
2257 return -EINVAL;
2258
2259 if (priv->last > MII_VCT5_SAMPLE_POINT_DISTANCE_MAX)
2260 return -EINVAL;
2261
2262
2263 ret = phy_write_paged(phydev, MII_MARVELL_VCT7_PAGE,
2264 MII_VCT7_CTRL, 0);
2265 if (ret)
2266 return ret;
2267
2268 ret = marvell_cable_test_start_common(phydev);
2269 if (ret)
2270 return ret;
2271
2272 ret = ethnl_cable_test_pulse(phydev, 1000);
2273 if (ret)
2274 return ret;
2275
2276 return ethnl_cable_test_step(phydev,
2277 marvell_vct5_distance2cm(priv->first),
2278 marvell_vct5_distance2cm(priv->last),
2279 marvell_vct5_distance2cm(priv->step));
2280 }
2281
2282 static int marvell_vct7_distance_to_length(int distance, bool meter)
2283 {
2284 if (meter)
2285 distance *= 100;
2286
2287 return distance;
2288 }
2289
2290 static bool marvell_vct7_distance_valid(int result)
2291 {
2292 switch (result) {
2293 case MII_VCT7_RESULTS_OPEN:
2294 case MII_VCT7_RESULTS_SAME_SHORT:
2295 case MII_VCT7_RESULTS_CROSS_SHORT:
2296 return true;
2297 }
2298 return false;
2299 }
2300
2301 static int marvell_vct7_report_length(struct phy_device *phydev,
2302 int pair, bool meter)
2303 {
2304 int length;
2305 int ret;
2306
2307 ret = phy_read_paged(phydev, MII_MARVELL_VCT7_PAGE,
2308 MII_VCT7_PAIR_0_DISTANCE + pair);
2309 if (ret < 0)
2310 return ret;
2311
2312 length = marvell_vct7_distance_to_length(ret, meter);
2313
2314 ethnl_cable_test_fault_length(phydev, pair, length);
2315
2316 return 0;
2317 }
2318
2319 static int marvell_vct7_cable_test_report_trans(int result)
2320 {
2321 switch (result) {
2322 case MII_VCT7_RESULTS_OK:
2323 return ETHTOOL_A_CABLE_RESULT_CODE_OK;
2324 case MII_VCT7_RESULTS_OPEN:
2325 return ETHTOOL_A_CABLE_RESULT_CODE_OPEN;
2326 case MII_VCT7_RESULTS_SAME_SHORT:
2327 return ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT;
2328 case MII_VCT7_RESULTS_CROSS_SHORT:
2329 return ETHTOOL_A_CABLE_RESULT_CODE_CROSS_SHORT;
2330 default:
2331 return ETHTOOL_A_CABLE_RESULT_CODE_UNSPEC;
2332 }
2333 }
2334
2335 static int marvell_vct7_cable_test_report(struct phy_device *phydev)
2336 {
2337 int pair0, pair1, pair2, pair3;
2338 bool meter;
2339 int ret;
2340
2341 ret = phy_read_paged(phydev, MII_MARVELL_VCT7_PAGE,
2342 MII_VCT7_RESULTS);
2343 if (ret < 0)
2344 return ret;
2345
2346 pair3 = (ret & MII_VCT7_RESULTS_PAIR3_MASK) >>
2347 MII_VCT7_RESULTS_PAIR3_SHIFT;
2348 pair2 = (ret & MII_VCT7_RESULTS_PAIR2_MASK) >>
2349 MII_VCT7_RESULTS_PAIR2_SHIFT;
2350 pair1 = (ret & MII_VCT7_RESULTS_PAIR1_MASK) >>
2351 MII_VCT7_RESULTS_PAIR1_SHIFT;
2352 pair0 = (ret & MII_VCT7_RESULTS_PAIR0_MASK) >>
2353 MII_VCT7_RESULTS_PAIR0_SHIFT;
2354
2355 ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_A,
2356 marvell_vct7_cable_test_report_trans(pair0));
2357 ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_B,
2358 marvell_vct7_cable_test_report_trans(pair1));
2359 ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_C,
2360 marvell_vct7_cable_test_report_trans(pair2));
2361 ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_D,
2362 marvell_vct7_cable_test_report_trans(pair3));
2363
2364 ret = phy_read_paged(phydev, MII_MARVELL_VCT7_PAGE, MII_VCT7_CTRL);
2365 if (ret < 0)
2366 return ret;
2367
2368 meter = ret & MII_VCT7_CTRL_METERS;
2369
2370 if (marvell_vct7_distance_valid(pair0))
2371 marvell_vct7_report_length(phydev, 0, meter);
2372 if (marvell_vct7_distance_valid(pair1))
2373 marvell_vct7_report_length(phydev, 1, meter);
2374 if (marvell_vct7_distance_valid(pair2))
2375 marvell_vct7_report_length(phydev, 2, meter);
2376 if (marvell_vct7_distance_valid(pair3))
2377 marvell_vct7_report_length(phydev, 3, meter);
2378
2379 return 0;
2380 }
2381
2382 static int marvell_vct7_cable_test_get_status(struct phy_device *phydev,
2383 bool *finished)
2384 {
2385 struct marvell_priv *priv = phydev->priv;
2386 int ret;
2387
2388 if (priv->cable_test_tdr) {
2389 ret = marvell_vct5_amplitude_graph(phydev);
2390 *finished = true;
2391 return ret;
2392 }
2393
2394 *finished = false;
2395
2396 ret = phy_read_paged(phydev, MII_MARVELL_VCT7_PAGE,
2397 MII_VCT7_CTRL);
2398
2399 if (ret < 0)
2400 return ret;
2401
2402 if (!(ret & MII_VCT7_CTRL_IN_PROGRESS)) {
2403 *finished = true;
2404
2405 return marvell_vct7_cable_test_report(phydev);
2406 }
2407
2408 return 0;
2409 }
2410
2411 #ifdef CONFIG_HWMON
2412 struct marvell_hwmon_ops {
2413 int (*config)(struct phy_device *phydev);
2414 int (*get_temp)(struct phy_device *phydev, long *temp);
2415 int (*get_temp_critical)(struct phy_device *phydev, long *temp);
2416 int (*set_temp_critical)(struct phy_device *phydev, long temp);
2417 int (*get_temp_alarm)(struct phy_device *phydev, long *alarm);
2418 };
2419
2420 static const struct marvell_hwmon_ops *
2421 to_marvell_hwmon_ops(const struct phy_device *phydev)
2422 {
2423 return phydev->drv->driver_data;
2424 }
2425
2426 static int m88e1121_get_temp(struct phy_device *phydev, long *temp)
2427 {
2428 int oldpage;
2429 int ret = 0;
2430 int val;
2431
2432 *temp = 0;
2433
2434 oldpage = phy_select_page(phydev, MII_MARVELL_MISC_TEST_PAGE);
2435 if (oldpage < 0)
2436 goto error;
2437
2438
2439 ret = __phy_read(phydev, MII_88E1121_MISC_TEST);
2440 if (ret < 0)
2441 goto error;
2442
2443 ret = __phy_write(phydev, MII_88E1121_MISC_TEST,
2444 ret | MII_88E1121_MISC_TEST_TEMP_SENSOR_EN);
2445 if (ret < 0)
2446 goto error;
2447
2448
2449 usleep_range(10000, 12000);
2450
2451 val = __phy_read(phydev, MII_88E1121_MISC_TEST);
2452 if (val < 0) {
2453 ret = val;
2454 goto error;
2455 }
2456
2457
2458 ret = __phy_write(phydev, MII_88E1121_MISC_TEST,
2459 ret & ~MII_88E1121_MISC_TEST_TEMP_SENSOR_EN);
2460 if (ret < 0)
2461 goto error;
2462
2463 *temp = ((val & MII_88E1121_MISC_TEST_TEMP_MASK) - 5) * 5000;
2464
2465 error:
2466 return phy_restore_page(phydev, oldpage, ret);
2467 }
2468
2469 static int m88e1510_get_temp(struct phy_device *phydev, long *temp)
2470 {
2471 int ret;
2472
2473 *temp = 0;
2474
2475 ret = phy_read_paged(phydev, MII_MARVELL_MISC_TEST_PAGE,
2476 MII_88E1510_TEMP_SENSOR);
2477 if (ret < 0)
2478 return ret;
2479
2480 *temp = ((ret & MII_88E1510_TEMP_SENSOR_MASK) - 25) * 1000;
2481
2482 return 0;
2483 }
2484
2485 static int m88e1510_get_temp_critical(struct phy_device *phydev, long *temp)
2486 {
2487 int ret;
2488
2489 *temp = 0;
2490
2491 ret = phy_read_paged(phydev, MII_MARVELL_MISC_TEST_PAGE,
2492 MII_88E1121_MISC_TEST);
2493 if (ret < 0)
2494 return ret;
2495
2496 *temp = (((ret & MII_88E1510_MISC_TEST_TEMP_THRESHOLD_MASK) >>
2497 MII_88E1510_MISC_TEST_TEMP_THRESHOLD_SHIFT) * 5) - 25;
2498
2499 *temp *= 1000;
2500
2501 return 0;
2502 }
2503
2504 static int m88e1510_set_temp_critical(struct phy_device *phydev, long temp)
2505 {
2506 temp = temp / 1000;
2507 temp = clamp_val(DIV_ROUND_CLOSEST(temp, 5) + 5, 0, 0x1f);
2508
2509 return phy_modify_paged(phydev, MII_MARVELL_MISC_TEST_PAGE,
2510 MII_88E1121_MISC_TEST,
2511 MII_88E1510_MISC_TEST_TEMP_THRESHOLD_MASK,
2512 temp << MII_88E1510_MISC_TEST_TEMP_THRESHOLD_SHIFT);
2513 }
2514
2515 static int m88e1510_get_temp_alarm(struct phy_device *phydev, long *alarm)
2516 {
2517 int ret;
2518
2519 *alarm = false;
2520
2521 ret = phy_read_paged(phydev, MII_MARVELL_MISC_TEST_PAGE,
2522 MII_88E1121_MISC_TEST);
2523 if (ret < 0)
2524 return ret;
2525
2526 *alarm = !!(ret & MII_88E1510_MISC_TEST_TEMP_IRQ);
2527
2528 return 0;
2529 }
2530
2531 static int m88e6390_get_temp(struct phy_device *phydev, long *temp)
2532 {
2533 int sum = 0;
2534 int oldpage;
2535 int ret = 0;
2536 int i;
2537
2538 *temp = 0;
2539
2540 oldpage = phy_select_page(phydev, MII_MARVELL_MISC_TEST_PAGE);
2541 if (oldpage < 0)
2542 goto error;
2543
2544
2545 ret = __phy_read(phydev, MII_88E6390_MISC_TEST);
2546 if (ret < 0)
2547 goto error;
2548
2549 ret &= ~MII_88E6390_MISC_TEST_TEMP_SENSOR_MASK;
2550 ret |= MII_88E6390_MISC_TEST_TEMP_SENSOR_ENABLE_SAMPLE_1S;
2551
2552 ret = __phy_write(phydev, MII_88E6390_MISC_TEST, ret);
2553 if (ret < 0)
2554 goto error;
2555
2556
2557 usleep_range(10000, 12000);
2558
2559
2560
2561
2562 for (i = 0; i < MII_88E6390_TEMP_SENSOR_SAMPLES; i++) {
2563 ret = __phy_read(phydev, MII_88E6390_TEMP_SENSOR);
2564 if (ret < 0)
2565 goto error;
2566 sum += ret & MII_88E6390_TEMP_SENSOR_MASK;
2567 }
2568
2569 sum /= MII_88E6390_TEMP_SENSOR_SAMPLES;
2570 *temp = (sum - 75) * 1000;
2571
2572
2573 ret = __phy_read(phydev, MII_88E6390_MISC_TEST);
2574 if (ret < 0)
2575 goto error;
2576
2577 ret = ret & ~MII_88E6390_MISC_TEST_TEMP_SENSOR_MASK;
2578 ret |= MII_88E6390_MISC_TEST_TEMP_SENSOR_DISABLE;
2579
2580 ret = __phy_write(phydev, MII_88E6390_MISC_TEST, ret);
2581
2582 error:
2583 phy_restore_page(phydev, oldpage, ret);
2584
2585 return ret;
2586 }
2587
2588 static int m88e6393_get_temp(struct phy_device *phydev, long *temp)
2589 {
2590 int err;
2591
2592 err = m88e1510_get_temp(phydev, temp);
2593
2594
2595
2596
2597 *temp -= 50000;
2598
2599 return err;
2600 }
2601
2602 static int m88e6393_get_temp_critical(struct phy_device *phydev, long *temp)
2603 {
2604 int ret;
2605
2606 *temp = 0;
2607
2608 ret = phy_read_paged(phydev, MII_MARVELL_MISC_TEST_PAGE,
2609 MII_88E6390_TEMP_SENSOR);
2610 if (ret < 0)
2611 return ret;
2612
2613 *temp = (((ret & MII_88E6393_TEMP_SENSOR_THRESHOLD_MASK) >>
2614 MII_88E6393_TEMP_SENSOR_THRESHOLD_SHIFT) - 75) * 1000;
2615
2616 return 0;
2617 }
2618
2619 static int m88e6393_set_temp_critical(struct phy_device *phydev, long temp)
2620 {
2621 temp = (temp / 1000) + 75;
2622
2623 return phy_modify_paged(phydev, MII_MARVELL_MISC_TEST_PAGE,
2624 MII_88E6390_TEMP_SENSOR,
2625 MII_88E6393_TEMP_SENSOR_THRESHOLD_MASK,
2626 temp << MII_88E6393_TEMP_SENSOR_THRESHOLD_SHIFT);
2627 }
2628
2629 static int m88e6393_hwmon_config(struct phy_device *phydev)
2630 {
2631 int err;
2632
2633 err = m88e6393_set_temp_critical(phydev, 100000);
2634 if (err)
2635 return err;
2636
2637 return phy_modify_paged(phydev, MII_MARVELL_MISC_TEST_PAGE,
2638 MII_88E6390_MISC_TEST,
2639 MII_88E6390_MISC_TEST_TEMP_SENSOR_MASK |
2640 MII_88E6393_MISC_TEST_SAMPLES_MASK |
2641 MII_88E6393_MISC_TEST_RATE_MASK,
2642 MII_88E6390_MISC_TEST_TEMP_SENSOR_ENABLE |
2643 MII_88E6393_MISC_TEST_SAMPLES_2048 |
2644 MII_88E6393_MISC_TEST_RATE_2_3MS);
2645 }
2646
2647 static int marvell_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
2648 u32 attr, int channel, long *temp)
2649 {
2650 struct phy_device *phydev = dev_get_drvdata(dev);
2651 const struct marvell_hwmon_ops *ops = to_marvell_hwmon_ops(phydev);
2652 int err = -EOPNOTSUPP;
2653
2654 switch (attr) {
2655 case hwmon_temp_input:
2656 if (ops->get_temp)
2657 err = ops->get_temp(phydev, temp);
2658 break;
2659 case hwmon_temp_crit:
2660 if (ops->get_temp_critical)
2661 err = ops->get_temp_critical(phydev, temp);
2662 break;
2663 case hwmon_temp_max_alarm:
2664 if (ops->get_temp_alarm)
2665 err = ops->get_temp_alarm(phydev, temp);
2666 break;
2667 }
2668
2669 return err;
2670 }
2671
2672 static int marvell_hwmon_write(struct device *dev, enum hwmon_sensor_types type,
2673 u32 attr, int channel, long temp)
2674 {
2675 struct phy_device *phydev = dev_get_drvdata(dev);
2676 const struct marvell_hwmon_ops *ops = to_marvell_hwmon_ops(phydev);
2677 int err = -EOPNOTSUPP;
2678
2679 switch (attr) {
2680 case hwmon_temp_crit:
2681 if (ops->set_temp_critical)
2682 err = ops->set_temp_critical(phydev, temp);
2683 break;
2684 }
2685
2686 return err;
2687 }
2688
2689 static umode_t marvell_hwmon_is_visible(const void *data,
2690 enum hwmon_sensor_types type,
2691 u32 attr, int channel)
2692 {
2693 const struct phy_device *phydev = data;
2694 const struct marvell_hwmon_ops *ops = to_marvell_hwmon_ops(phydev);
2695
2696 if (type != hwmon_temp)
2697 return 0;
2698
2699 switch (attr) {
2700 case hwmon_temp_input:
2701 return ops->get_temp ? 0444 : 0;
2702 case hwmon_temp_max_alarm:
2703 return ops->get_temp_alarm ? 0444 : 0;
2704 case hwmon_temp_crit:
2705 return (ops->get_temp_critical ? 0444 : 0) |
2706 (ops->set_temp_critical ? 0200 : 0);
2707 default:
2708 return 0;
2709 }
2710 }
2711
2712 static u32 marvell_hwmon_chip_config[] = {
2713 HWMON_C_REGISTER_TZ,
2714 0
2715 };
2716
2717 static const struct hwmon_channel_info marvell_hwmon_chip = {
2718 .type = hwmon_chip,
2719 .config = marvell_hwmon_chip_config,
2720 };
2721
2722
2723
2724
2725
2726 static u32 marvell_hwmon_temp_config[] = {
2727 HWMON_T_INPUT | HWMON_T_CRIT | HWMON_T_MAX_ALARM,
2728 0
2729 };
2730
2731 static const struct hwmon_channel_info marvell_hwmon_temp = {
2732 .type = hwmon_temp,
2733 .config = marvell_hwmon_temp_config,
2734 };
2735
2736 static const struct hwmon_channel_info *marvell_hwmon_info[] = {
2737 &marvell_hwmon_chip,
2738 &marvell_hwmon_temp,
2739 NULL
2740 };
2741
2742 static const struct hwmon_ops marvell_hwmon_hwmon_ops = {
2743 .is_visible = marvell_hwmon_is_visible,
2744 .read = marvell_hwmon_read,
2745 .write = marvell_hwmon_write,
2746 };
2747
2748 static const struct hwmon_chip_info marvell_hwmon_chip_info = {
2749 .ops = &marvell_hwmon_hwmon_ops,
2750 .info = marvell_hwmon_info,
2751 };
2752
2753 static int marvell_hwmon_name(struct phy_device *phydev)
2754 {
2755 struct marvell_priv *priv = phydev->priv;
2756 struct device *dev = &phydev->mdio.dev;
2757 const char *devname = dev_name(dev);
2758 size_t len = strlen(devname);
2759 int i, j;
2760
2761 priv->hwmon_name = devm_kzalloc(dev, len, GFP_KERNEL);
2762 if (!priv->hwmon_name)
2763 return -ENOMEM;
2764
2765 for (i = j = 0; i < len && devname[i]; i++) {
2766 if (isalnum(devname[i]))
2767 priv->hwmon_name[j++] = devname[i];
2768 }
2769
2770 return 0;
2771 }
2772
2773 static int marvell_hwmon_probe(struct phy_device *phydev)
2774 {
2775 const struct marvell_hwmon_ops *ops = to_marvell_hwmon_ops(phydev);
2776 struct marvell_priv *priv = phydev->priv;
2777 struct device *dev = &phydev->mdio.dev;
2778 int err;
2779
2780 if (!ops)
2781 return 0;
2782
2783 err = marvell_hwmon_name(phydev);
2784 if (err)
2785 return err;
2786
2787 priv->hwmon_dev = devm_hwmon_device_register_with_info(
2788 dev, priv->hwmon_name, phydev, &marvell_hwmon_chip_info, NULL);
2789 if (IS_ERR(priv->hwmon_dev))
2790 return PTR_ERR(priv->hwmon_dev);
2791
2792 if (ops->config)
2793 err = ops->config(phydev);
2794
2795 return err;
2796 }
2797
2798 static const struct marvell_hwmon_ops m88e1121_hwmon_ops = {
2799 .get_temp = m88e1121_get_temp,
2800 };
2801
2802 static const struct marvell_hwmon_ops m88e1510_hwmon_ops = {
2803 .get_temp = m88e1510_get_temp,
2804 .get_temp_critical = m88e1510_get_temp_critical,
2805 .set_temp_critical = m88e1510_set_temp_critical,
2806 .get_temp_alarm = m88e1510_get_temp_alarm,
2807 };
2808
2809 static const struct marvell_hwmon_ops m88e6390_hwmon_ops = {
2810 .get_temp = m88e6390_get_temp,
2811 };
2812
2813 static const struct marvell_hwmon_ops m88e6393_hwmon_ops = {
2814 .config = m88e6393_hwmon_config,
2815 .get_temp = m88e6393_get_temp,
2816 .get_temp_critical = m88e6393_get_temp_critical,
2817 .set_temp_critical = m88e6393_set_temp_critical,
2818 .get_temp_alarm = m88e1510_get_temp_alarm,
2819 };
2820
2821 #define DEF_MARVELL_HWMON_OPS(s) (&(s))
2822
2823 #else
2824
2825 #define DEF_MARVELL_HWMON_OPS(s) NULL
2826
2827 static int marvell_hwmon_probe(struct phy_device *phydev)
2828 {
2829 return 0;
2830 }
2831 #endif
2832
2833 static int marvell_probe(struct phy_device *phydev)
2834 {
2835 struct marvell_priv *priv;
2836
2837 priv = devm_kzalloc(&phydev->mdio.dev, sizeof(*priv), GFP_KERNEL);
2838 if (!priv)
2839 return -ENOMEM;
2840
2841 phydev->priv = priv;
2842
2843 return marvell_hwmon_probe(phydev);
2844 }
2845
2846 static int m88e1510_sfp_insert(void *upstream, const struct sfp_eeprom_id *id)
2847 {
2848 struct phy_device *phydev = upstream;
2849 phy_interface_t interface;
2850 struct device *dev;
2851 int oldpage;
2852 int ret = 0;
2853 u16 mode;
2854
2855 __ETHTOOL_DECLARE_LINK_MODE_MASK(supported) = { 0, };
2856
2857 dev = &phydev->mdio.dev;
2858
2859 sfp_parse_support(phydev->sfp_bus, id, supported);
2860 interface = sfp_select_interface(phydev->sfp_bus, supported);
2861
2862 dev_info(dev, "%s SFP module inserted\n", phy_modes(interface));
2863
2864 switch (interface) {
2865 case PHY_INTERFACE_MODE_1000BASEX:
2866 mode = MII_88E1510_GEN_CTRL_REG_1_MODE_RGMII_1000X;
2867
2868 break;
2869 case PHY_INTERFACE_MODE_100BASEX:
2870 mode = MII_88E1510_GEN_CTRL_REG_1_MODE_RGMII_100FX;
2871
2872 break;
2873 case PHY_INTERFACE_MODE_SGMII:
2874 mode = MII_88E1510_GEN_CTRL_REG_1_MODE_RGMII_SGMII;
2875
2876 break;
2877 default:
2878 dev_err(dev, "Incompatible SFP module inserted\n");
2879
2880 return -EINVAL;
2881 }
2882
2883 oldpage = phy_select_page(phydev, MII_MARVELL_MODE_PAGE);
2884 if (oldpage < 0)
2885 goto error;
2886
2887 ret = __phy_modify(phydev, MII_88E1510_GEN_CTRL_REG_1,
2888 MII_88E1510_GEN_CTRL_REG_1_MODE_MASK, mode);
2889 if (ret < 0)
2890 goto error;
2891
2892 ret = __phy_set_bits(phydev, MII_88E1510_GEN_CTRL_REG_1,
2893 MII_88E1510_GEN_CTRL_REG_1_RESET);
2894
2895 error:
2896 return phy_restore_page(phydev, oldpage, ret);
2897 }
2898
2899 static void m88e1510_sfp_remove(void *upstream)
2900 {
2901 struct phy_device *phydev = upstream;
2902 int oldpage;
2903 int ret = 0;
2904
2905 oldpage = phy_select_page(phydev, MII_MARVELL_MODE_PAGE);
2906 if (oldpage < 0)
2907 goto error;
2908
2909 ret = __phy_modify(phydev, MII_88E1510_GEN_CTRL_REG_1,
2910 MII_88E1510_GEN_CTRL_REG_1_MODE_MASK,
2911 MII_88E1510_GEN_CTRL_REG_1_MODE_RGMII);
2912 if (ret < 0)
2913 goto error;
2914
2915 ret = __phy_set_bits(phydev, MII_88E1510_GEN_CTRL_REG_1,
2916 MII_88E1510_GEN_CTRL_REG_1_RESET);
2917
2918 error:
2919 phy_restore_page(phydev, oldpage, ret);
2920 }
2921
2922 static const struct sfp_upstream_ops m88e1510_sfp_ops = {
2923 .module_insert = m88e1510_sfp_insert,
2924 .module_remove = m88e1510_sfp_remove,
2925 .attach = phy_sfp_attach,
2926 .detach = phy_sfp_detach,
2927 };
2928
2929 static int m88e1510_probe(struct phy_device *phydev)
2930 {
2931 int err;
2932
2933 err = marvell_probe(phydev);
2934 if (err)
2935 return err;
2936
2937 return phy_sfp_probe(phydev, &m88e1510_sfp_ops);
2938 }
2939
2940 static struct phy_driver marvell_drivers[] = {
2941 {
2942 .phy_id = MARVELL_PHY_ID_88E1101,
2943 .phy_id_mask = MARVELL_PHY_ID_MASK,
2944 .name = "Marvell 88E1101",
2945
2946 .probe = marvell_probe,
2947 .config_init = marvell_config_init,
2948 .config_aneg = m88e1101_config_aneg,
2949 .config_intr = marvell_config_intr,
2950 .handle_interrupt = marvell_handle_interrupt,
2951 .resume = genphy_resume,
2952 .suspend = genphy_suspend,
2953 .read_page = marvell_read_page,
2954 .write_page = marvell_write_page,
2955 .get_sset_count = marvell_get_sset_count,
2956 .get_strings = marvell_get_strings,
2957 .get_stats = marvell_get_stats,
2958 },
2959 {
2960 .phy_id = MARVELL_PHY_ID_88E1112,
2961 .phy_id_mask = MARVELL_PHY_ID_MASK,
2962 .name = "Marvell 88E1112",
2963
2964 .probe = marvell_probe,
2965 .config_init = m88e1112_config_init,
2966 .config_aneg = marvell_config_aneg,
2967 .config_intr = marvell_config_intr,
2968 .handle_interrupt = marvell_handle_interrupt,
2969 .resume = genphy_resume,
2970 .suspend = genphy_suspend,
2971 .read_page = marvell_read_page,
2972 .write_page = marvell_write_page,
2973 .get_sset_count = marvell_get_sset_count,
2974 .get_strings = marvell_get_strings,
2975 .get_stats = marvell_get_stats,
2976 .get_tunable = m88e1011_get_tunable,
2977 .set_tunable = m88e1011_set_tunable,
2978 },
2979 {
2980 .phy_id = MARVELL_PHY_ID_88E1111,
2981 .phy_id_mask = MARVELL_PHY_ID_MASK,
2982 .name = "Marvell 88E1111",
2983
2984 .probe = marvell_probe,
2985 .config_init = m88e1111gbe_config_init,
2986 .config_aneg = m88e1111_config_aneg,
2987 .read_status = marvell_read_status,
2988 .config_intr = marvell_config_intr,
2989 .handle_interrupt = marvell_handle_interrupt,
2990 .resume = genphy_resume,
2991 .suspend = genphy_suspend,
2992 .read_page = marvell_read_page,
2993 .write_page = marvell_write_page,
2994 .get_sset_count = marvell_get_sset_count,
2995 .get_strings = marvell_get_strings,
2996 .get_stats = marvell_get_stats,
2997 .get_tunable = m88e1111_get_tunable,
2998 .set_tunable = m88e1111_set_tunable,
2999 },
3000 {
3001 .phy_id = MARVELL_PHY_ID_88E1111_FINISAR,
3002 .phy_id_mask = MARVELL_PHY_ID_MASK,
3003 .name = "Marvell 88E1111 (Finisar)",
3004
3005 .probe = marvell_probe,
3006 .config_init = m88e1111gbe_config_init,
3007 .config_aneg = m88e1111_config_aneg,
3008 .read_status = marvell_read_status,
3009 .config_intr = marvell_config_intr,
3010 .handle_interrupt = marvell_handle_interrupt,
3011 .resume = genphy_resume,
3012 .suspend = genphy_suspend,
3013 .read_page = marvell_read_page,
3014 .write_page = marvell_write_page,
3015 .get_sset_count = marvell_get_sset_count,
3016 .get_strings = marvell_get_strings,
3017 .get_stats = marvell_get_stats,
3018 .get_tunable = m88e1111_get_tunable,
3019 .set_tunable = m88e1111_set_tunable,
3020 },
3021 {
3022 .phy_id = MARVELL_PHY_ID_88E1118,
3023 .phy_id_mask = MARVELL_PHY_ID_MASK,
3024 .name = "Marvell 88E1118",
3025
3026 .probe = marvell_probe,
3027 .config_init = m88e1118_config_init,
3028 .config_aneg = m88e1118_config_aneg,
3029 .config_intr = marvell_config_intr,
3030 .handle_interrupt = marvell_handle_interrupt,
3031 .resume = genphy_resume,
3032 .suspend = genphy_suspend,
3033 .read_page = marvell_read_page,
3034 .write_page = marvell_write_page,
3035 .get_sset_count = marvell_get_sset_count,
3036 .get_strings = marvell_get_strings,
3037 .get_stats = marvell_get_stats,
3038 },
3039 {
3040 .phy_id = MARVELL_PHY_ID_88E1121R,
3041 .phy_id_mask = MARVELL_PHY_ID_MASK,
3042 .name = "Marvell 88E1121R",
3043 .driver_data = DEF_MARVELL_HWMON_OPS(m88e1121_hwmon_ops),
3044
3045 .probe = marvell_probe,
3046 .config_init = marvell_1011gbe_config_init,
3047 .config_aneg = m88e1121_config_aneg,
3048 .read_status = marvell_read_status,
3049 .config_intr = marvell_config_intr,
3050 .handle_interrupt = marvell_handle_interrupt,
3051 .resume = genphy_resume,
3052 .suspend = genphy_suspend,
3053 .read_page = marvell_read_page,
3054 .write_page = marvell_write_page,
3055 .get_sset_count = marvell_get_sset_count,
3056 .get_strings = marvell_get_strings,
3057 .get_stats = marvell_get_stats,
3058 .get_tunable = m88e1011_get_tunable,
3059 .set_tunable = m88e1011_set_tunable,
3060 },
3061 {
3062 .phy_id = MARVELL_PHY_ID_88E1318S,
3063 .phy_id_mask = MARVELL_PHY_ID_MASK,
3064 .name = "Marvell 88E1318S",
3065
3066 .probe = marvell_probe,
3067 .config_init = m88e1318_config_init,
3068 .config_aneg = m88e1318_config_aneg,
3069 .read_status = marvell_read_status,
3070 .config_intr = marvell_config_intr,
3071 .handle_interrupt = marvell_handle_interrupt,
3072 .get_wol = m88e1318_get_wol,
3073 .set_wol = m88e1318_set_wol,
3074 .resume = genphy_resume,
3075 .suspend = genphy_suspend,
3076 .read_page = marvell_read_page,
3077 .write_page = marvell_write_page,
3078 .get_sset_count = marvell_get_sset_count,
3079 .get_strings = marvell_get_strings,
3080 .get_stats = marvell_get_stats,
3081 },
3082 {
3083 .phy_id = MARVELL_PHY_ID_88E1145,
3084 .phy_id_mask = MARVELL_PHY_ID_MASK,
3085 .name = "Marvell 88E1145",
3086
3087 .probe = marvell_probe,
3088 .config_init = m88e1145_config_init,
3089 .config_aneg = m88e1101_config_aneg,
3090 .config_intr = marvell_config_intr,
3091 .handle_interrupt = marvell_handle_interrupt,
3092 .resume = genphy_resume,
3093 .suspend = genphy_suspend,
3094 .read_page = marvell_read_page,
3095 .write_page = marvell_write_page,
3096 .get_sset_count = marvell_get_sset_count,
3097 .get_strings = marvell_get_strings,
3098 .get_stats = marvell_get_stats,
3099 .get_tunable = m88e1111_get_tunable,
3100 .set_tunable = m88e1111_set_tunable,
3101 },
3102 {
3103 .phy_id = MARVELL_PHY_ID_88E1149R,
3104 .phy_id_mask = MARVELL_PHY_ID_MASK,
3105 .name = "Marvell 88E1149R",
3106
3107 .probe = marvell_probe,
3108 .config_init = m88e1149_config_init,
3109 .config_aneg = m88e1118_config_aneg,
3110 .config_intr = marvell_config_intr,
3111 .handle_interrupt = marvell_handle_interrupt,
3112 .resume = genphy_resume,
3113 .suspend = genphy_suspend,
3114 .read_page = marvell_read_page,
3115 .write_page = marvell_write_page,
3116 .get_sset_count = marvell_get_sset_count,
3117 .get_strings = marvell_get_strings,
3118 .get_stats = marvell_get_stats,
3119 },
3120 {
3121 .phy_id = MARVELL_PHY_ID_88E1240,
3122 .phy_id_mask = MARVELL_PHY_ID_MASK,
3123 .name = "Marvell 88E1240",
3124
3125 .probe = marvell_probe,
3126 .config_init = m88e1112_config_init,
3127 .config_aneg = marvell_config_aneg,
3128 .config_intr = marvell_config_intr,
3129 .handle_interrupt = marvell_handle_interrupt,
3130 .resume = genphy_resume,
3131 .suspend = genphy_suspend,
3132 .read_page = marvell_read_page,
3133 .write_page = marvell_write_page,
3134 .get_sset_count = marvell_get_sset_count,
3135 .get_strings = marvell_get_strings,
3136 .get_stats = marvell_get_stats,
3137 .get_tunable = m88e1011_get_tunable,
3138 .set_tunable = m88e1011_set_tunable,
3139 },
3140 {
3141 .phy_id = MARVELL_PHY_ID_88E1116R,
3142 .phy_id_mask = MARVELL_PHY_ID_MASK,
3143 .name = "Marvell 88E1116R",
3144
3145 .probe = marvell_probe,
3146 .config_init = m88e1116r_config_init,
3147 .config_intr = marvell_config_intr,
3148 .handle_interrupt = marvell_handle_interrupt,
3149 .resume = genphy_resume,
3150 .suspend = genphy_suspend,
3151 .read_page = marvell_read_page,
3152 .write_page = marvell_write_page,
3153 .get_sset_count = marvell_get_sset_count,
3154 .get_strings = marvell_get_strings,
3155 .get_stats = marvell_get_stats,
3156 .get_tunable = m88e1011_get_tunable,
3157 .set_tunable = m88e1011_set_tunable,
3158 },
3159 {
3160 .phy_id = MARVELL_PHY_ID_88E1510,
3161 .phy_id_mask = MARVELL_PHY_ID_MASK,
3162 .name = "Marvell 88E1510",
3163 .driver_data = DEF_MARVELL_HWMON_OPS(m88e1510_hwmon_ops),
3164 .features = PHY_GBIT_FIBRE_FEATURES,
3165 .flags = PHY_POLL_CABLE_TEST,
3166 .probe = m88e1510_probe,
3167 .config_init = m88e1510_config_init,
3168 .config_aneg = m88e1510_config_aneg,
3169 .read_status = marvell_read_status,
3170 .config_intr = marvell_config_intr,
3171 .handle_interrupt = marvell_handle_interrupt,
3172 .get_wol = m88e1318_get_wol,
3173 .set_wol = m88e1318_set_wol,
3174 .resume = marvell_resume,
3175 .suspend = marvell_suspend,
3176 .read_page = marvell_read_page,
3177 .write_page = marvell_write_page,
3178 .get_sset_count = marvell_get_sset_count,
3179 .get_strings = marvell_get_strings,
3180 .get_stats = marvell_get_stats,
3181 .set_loopback = m88e1510_loopback,
3182 .get_tunable = m88e1011_get_tunable,
3183 .set_tunable = m88e1011_set_tunable,
3184 .cable_test_start = marvell_vct7_cable_test_start,
3185 .cable_test_tdr_start = marvell_vct5_cable_test_tdr_start,
3186 .cable_test_get_status = marvell_vct7_cable_test_get_status,
3187 },
3188 {
3189 .phy_id = MARVELL_PHY_ID_88E1540,
3190 .phy_id_mask = MARVELL_PHY_ID_MASK,
3191 .name = "Marvell 88E1540",
3192 .driver_data = DEF_MARVELL_HWMON_OPS(m88e1510_hwmon_ops),
3193
3194 .flags = PHY_POLL_CABLE_TEST,
3195 .probe = marvell_probe,
3196 .config_init = marvell_1011gbe_config_init,
3197 .config_aneg = m88e1510_config_aneg,
3198 .read_status = marvell_read_status,
3199 .config_intr = marvell_config_intr,
3200 .handle_interrupt = marvell_handle_interrupt,
3201 .resume = genphy_resume,
3202 .suspend = genphy_suspend,
3203 .read_page = marvell_read_page,
3204 .write_page = marvell_write_page,
3205 .get_sset_count = marvell_get_sset_count,
3206 .get_strings = marvell_get_strings,
3207 .get_stats = marvell_get_stats,
3208 .get_tunable = m88e1540_get_tunable,
3209 .set_tunable = m88e1540_set_tunable,
3210 .cable_test_start = marvell_vct7_cable_test_start,
3211 .cable_test_tdr_start = marvell_vct5_cable_test_tdr_start,
3212 .cable_test_get_status = marvell_vct7_cable_test_get_status,
3213 },
3214 {
3215 .phy_id = MARVELL_PHY_ID_88E1545,
3216 .phy_id_mask = MARVELL_PHY_ID_MASK,
3217 .name = "Marvell 88E1545",
3218 .driver_data = DEF_MARVELL_HWMON_OPS(m88e1510_hwmon_ops),
3219 .probe = marvell_probe,
3220
3221 .flags = PHY_POLL_CABLE_TEST,
3222 .config_init = marvell_1011gbe_config_init,
3223 .config_aneg = m88e1510_config_aneg,
3224 .read_status = marvell_read_status,
3225 .config_intr = marvell_config_intr,
3226 .handle_interrupt = marvell_handle_interrupt,
3227 .resume = genphy_resume,
3228 .suspend = genphy_suspend,
3229 .read_page = marvell_read_page,
3230 .write_page = marvell_write_page,
3231 .get_sset_count = marvell_get_sset_count,
3232 .get_strings = marvell_get_strings,
3233 .get_stats = marvell_get_stats,
3234 .get_tunable = m88e1540_get_tunable,
3235 .set_tunable = m88e1540_set_tunable,
3236 .cable_test_start = marvell_vct7_cable_test_start,
3237 .cable_test_tdr_start = marvell_vct5_cable_test_tdr_start,
3238 .cable_test_get_status = marvell_vct7_cable_test_get_status,
3239 },
3240 {
3241 .phy_id = MARVELL_PHY_ID_88E3016,
3242 .phy_id_mask = MARVELL_PHY_ID_MASK,
3243 .name = "Marvell 88E3016",
3244
3245 .probe = marvell_probe,
3246 .config_init = m88e3016_config_init,
3247 .aneg_done = marvell_aneg_done,
3248 .read_status = marvell_read_status,
3249 .config_intr = marvell_config_intr,
3250 .handle_interrupt = marvell_handle_interrupt,
3251 .resume = genphy_resume,
3252 .suspend = genphy_suspend,
3253 .read_page = marvell_read_page,
3254 .write_page = marvell_write_page,
3255 .get_sset_count = marvell_get_sset_count,
3256 .get_strings = marvell_get_strings,
3257 .get_stats = marvell_get_stats,
3258 },
3259 {
3260 .phy_id = MARVELL_PHY_ID_88E6341_FAMILY,
3261 .phy_id_mask = MARVELL_PHY_ID_MASK,
3262 .name = "Marvell 88E6341 Family",
3263 .driver_data = DEF_MARVELL_HWMON_OPS(m88e1510_hwmon_ops),
3264
3265 .flags = PHY_POLL_CABLE_TEST,
3266 .probe = marvell_probe,
3267 .config_init = marvell_1011gbe_config_init,
3268 .config_aneg = m88e6390_config_aneg,
3269 .read_status = marvell_read_status,
3270 .config_intr = marvell_config_intr,
3271 .handle_interrupt = marvell_handle_interrupt,
3272 .resume = genphy_resume,
3273 .suspend = genphy_suspend,
3274 .read_page = marvell_read_page,
3275 .write_page = marvell_write_page,
3276 .get_sset_count = marvell_get_sset_count,
3277 .get_strings = marvell_get_strings,
3278 .get_stats = marvell_get_stats,
3279 .get_tunable = m88e1540_get_tunable,
3280 .set_tunable = m88e1540_set_tunable,
3281 .cable_test_start = marvell_vct7_cable_test_start,
3282 .cable_test_tdr_start = marvell_vct5_cable_test_tdr_start,
3283 .cable_test_get_status = marvell_vct7_cable_test_get_status,
3284 },
3285 {
3286 .phy_id = MARVELL_PHY_ID_88E6390_FAMILY,
3287 .phy_id_mask = MARVELL_PHY_ID_MASK,
3288 .name = "Marvell 88E6390 Family",
3289 .driver_data = DEF_MARVELL_HWMON_OPS(m88e6390_hwmon_ops),
3290
3291 .flags = PHY_POLL_CABLE_TEST,
3292 .probe = marvell_probe,
3293 .config_init = marvell_1011gbe_config_init,
3294 .config_aneg = m88e6390_config_aneg,
3295 .read_status = marvell_read_status,
3296 .config_intr = marvell_config_intr,
3297 .handle_interrupt = marvell_handle_interrupt,
3298 .resume = genphy_resume,
3299 .suspend = genphy_suspend,
3300 .read_page = marvell_read_page,
3301 .write_page = marvell_write_page,
3302 .get_sset_count = marvell_get_sset_count,
3303 .get_strings = marvell_get_strings,
3304 .get_stats = marvell_get_stats,
3305 .get_tunable = m88e1540_get_tunable,
3306 .set_tunable = m88e1540_set_tunable,
3307 .cable_test_start = marvell_vct7_cable_test_start,
3308 .cable_test_tdr_start = marvell_vct5_cable_test_tdr_start,
3309 .cable_test_get_status = marvell_vct7_cable_test_get_status,
3310 },
3311 {
3312 .phy_id = MARVELL_PHY_ID_88E6393_FAMILY,
3313 .phy_id_mask = MARVELL_PHY_ID_MASK,
3314 .name = "Marvell 88E6393 Family",
3315 .driver_data = DEF_MARVELL_HWMON_OPS(m88e6393_hwmon_ops),
3316
3317 .flags = PHY_POLL_CABLE_TEST,
3318 .probe = marvell_probe,
3319 .config_init = marvell_1011gbe_config_init,
3320 .config_aneg = m88e1510_config_aneg,
3321 .read_status = marvell_read_status,
3322 .config_intr = marvell_config_intr,
3323 .handle_interrupt = marvell_handle_interrupt,
3324 .resume = genphy_resume,
3325 .suspend = genphy_suspend,
3326 .read_page = marvell_read_page,
3327 .write_page = marvell_write_page,
3328 .get_sset_count = marvell_get_sset_count,
3329 .get_strings = marvell_get_strings,
3330 .get_stats = marvell_get_stats,
3331 .get_tunable = m88e1540_get_tunable,
3332 .set_tunable = m88e1540_set_tunable,
3333 .cable_test_start = marvell_vct7_cable_test_start,
3334 .cable_test_tdr_start = marvell_vct5_cable_test_tdr_start,
3335 .cable_test_get_status = marvell_vct7_cable_test_get_status,
3336 },
3337 {
3338 .phy_id = MARVELL_PHY_ID_88E1340S,
3339 .phy_id_mask = MARVELL_PHY_ID_MASK,
3340 .name = "Marvell 88E1340S",
3341 .driver_data = DEF_MARVELL_HWMON_OPS(m88e1510_hwmon_ops),
3342 .probe = marvell_probe,
3343
3344 .config_init = marvell_1011gbe_config_init,
3345 .config_aneg = m88e1510_config_aneg,
3346 .read_status = marvell_read_status,
3347 .config_intr = marvell_config_intr,
3348 .handle_interrupt = marvell_handle_interrupt,
3349 .resume = genphy_resume,
3350 .suspend = genphy_suspend,
3351 .read_page = marvell_read_page,
3352 .write_page = marvell_write_page,
3353 .get_sset_count = marvell_get_sset_count,
3354 .get_strings = marvell_get_strings,
3355 .get_stats = marvell_get_stats,
3356 .get_tunable = m88e1540_get_tunable,
3357 .set_tunable = m88e1540_set_tunable,
3358 },
3359 {
3360 .phy_id = MARVELL_PHY_ID_88E1548P,
3361 .phy_id_mask = MARVELL_PHY_ID_MASK,
3362 .name = "Marvell 88E1548P",
3363 .driver_data = DEF_MARVELL_HWMON_OPS(m88e1510_hwmon_ops),
3364 .probe = marvell_probe,
3365 .features = PHY_GBIT_FIBRE_FEATURES,
3366 .config_init = marvell_1011gbe_config_init,
3367 .config_aneg = m88e1510_config_aneg,
3368 .read_status = marvell_read_status,
3369 .config_intr = marvell_config_intr,
3370 .handle_interrupt = marvell_handle_interrupt,
3371 .resume = genphy_resume,
3372 .suspend = genphy_suspend,
3373 .read_page = marvell_read_page,
3374 .write_page = marvell_write_page,
3375 .get_sset_count = marvell_get_sset_count,
3376 .get_strings = marvell_get_strings,
3377 .get_stats = marvell_get_stats,
3378 .get_tunable = m88e1540_get_tunable,
3379 .set_tunable = m88e1540_set_tunable,
3380 },
3381 };
3382
3383 module_phy_driver(marvell_drivers);
3384
3385 static struct mdio_device_id __maybe_unused marvell_tbl[] = {
3386 { MARVELL_PHY_ID_88E1101, MARVELL_PHY_ID_MASK },
3387 { MARVELL_PHY_ID_88E1112, MARVELL_PHY_ID_MASK },
3388 { MARVELL_PHY_ID_88E1111, MARVELL_PHY_ID_MASK },
3389 { MARVELL_PHY_ID_88E1111_FINISAR, MARVELL_PHY_ID_MASK },
3390 { MARVELL_PHY_ID_88E1118, MARVELL_PHY_ID_MASK },
3391 { MARVELL_PHY_ID_88E1121R, MARVELL_PHY_ID_MASK },
3392 { MARVELL_PHY_ID_88E1145, MARVELL_PHY_ID_MASK },
3393 { MARVELL_PHY_ID_88E1149R, MARVELL_PHY_ID_MASK },
3394 { MARVELL_PHY_ID_88E1240, MARVELL_PHY_ID_MASK },
3395 { MARVELL_PHY_ID_88E1318S, MARVELL_PHY_ID_MASK },
3396 { MARVELL_PHY_ID_88E1116R, MARVELL_PHY_ID_MASK },
3397 { MARVELL_PHY_ID_88E1510, MARVELL_PHY_ID_MASK },
3398 { MARVELL_PHY_ID_88E1540, MARVELL_PHY_ID_MASK },
3399 { MARVELL_PHY_ID_88E1545, MARVELL_PHY_ID_MASK },
3400 { MARVELL_PHY_ID_88E3016, MARVELL_PHY_ID_MASK },
3401 { MARVELL_PHY_ID_88E6341_FAMILY, MARVELL_PHY_ID_MASK },
3402 { MARVELL_PHY_ID_88E6390_FAMILY, MARVELL_PHY_ID_MASK },
3403 { MARVELL_PHY_ID_88E6393_FAMILY, MARVELL_PHY_ID_MASK },
3404 { MARVELL_PHY_ID_88E1340S, MARVELL_PHY_ID_MASK },
3405 { MARVELL_PHY_ID_88E1548P, MARVELL_PHY_ID_MASK },
3406 { }
3407 };
3408
3409 MODULE_DEVICE_TABLE(mdio, marvell_tbl);