0001
0002
0003
0004
0005
0006
0007 #include <linux/delay.h>
0008 #include <linux/rtnetlink.h>
0009 #include <linux/seq_file.h>
0010 #include <linux/slab.h>
0011 #include "efx.h"
0012 #include "mdio_10g.h"
0013 #include "nic.h"
0014 #include "phy.h"
0015 #include "workarounds.h"
0016
0017
0018 #define TENXPRESS_REQUIRED_DEVS (MDIO_DEVS_PMAPMD | \
0019 MDIO_DEVS_PCS | \
0020 MDIO_DEVS_PHYXS | \
0021 MDIO_DEVS_AN)
0022
0023 #define SFX7101_LOOPBACKS ((1 << LOOPBACK_PHYXS) | \
0024 (1 << LOOPBACK_PCS) | \
0025 (1 << LOOPBACK_PMAPMD) | \
0026 (1 << LOOPBACK_PHYXS_WS))
0027
0028
0029
0030
0031 #define MAX_BAD_LP_TRIES (5)
0032
0033
0034 #define PMA_PMD_XCONTROL_REG 49152
0035 #define PMA_PMD_EXT_GMII_EN_LBN 1
0036 #define PMA_PMD_EXT_GMII_EN_WIDTH 1
0037 #define PMA_PMD_EXT_CLK_OUT_LBN 2
0038 #define PMA_PMD_EXT_CLK_OUT_WIDTH 1
0039 #define PMA_PMD_LNPGA_POWERDOWN_LBN 8
0040 #define PMA_PMD_LNPGA_POWERDOWN_WIDTH 1
0041 #define PMA_PMD_EXT_CLK312_WIDTH 1
0042 #define PMA_PMD_EXT_LPOWER_LBN 12
0043 #define PMA_PMD_EXT_LPOWER_WIDTH 1
0044 #define PMA_PMD_EXT_ROBUST_LBN 14
0045 #define PMA_PMD_EXT_ROBUST_WIDTH 1
0046 #define PMA_PMD_EXT_SSR_LBN 15
0047 #define PMA_PMD_EXT_SSR_WIDTH 1
0048
0049
0050 #define PMA_PMD_XSTATUS_REG 49153
0051 #define PMA_PMD_XSTAT_MDIX_LBN 14
0052 #define PMA_PMD_XSTAT_FLP_LBN (12)
0053
0054
0055 #define PMA_PMD_LED_CTRL_REG 49159
0056 #define PMA_PMA_LED_ACTIVITY_LBN (3)
0057
0058
0059 #define PMA_PMD_LED_OVERR_REG 49161
0060
0061 #define PMA_PMD_LED_LINK_LBN (0)
0062 #define PMA_PMD_LED_SPEED_LBN (2)
0063 #define PMA_PMD_LED_TX_LBN (4)
0064 #define PMA_PMD_LED_RX_LBN (6)
0065
0066 #define PMA_PMD_LED_AUTO (0)
0067 #define PMA_PMD_LED_ON (1)
0068 #define PMA_PMD_LED_OFF (2)
0069 #define PMA_PMD_LED_FLASH (3)
0070 #define PMA_PMD_LED_MASK 3
0071
0072
0073 #define SFX7101_PMA_PMD_LED_DEFAULT (PMA_PMD_LED_OFF << PMA_PMD_LED_RX_LBN)
0074
0075 #define PMA_PMD_SPEED_ENABLE_REG 49192
0076 #define PMA_PMD_100TX_ADV_LBN 1
0077 #define PMA_PMD_100TX_ADV_WIDTH 1
0078 #define PMA_PMD_1000T_ADV_LBN 2
0079 #define PMA_PMD_1000T_ADV_WIDTH 1
0080 #define PMA_PMD_10000T_ADV_LBN 3
0081 #define PMA_PMD_10000T_ADV_WIDTH 1
0082 #define PMA_PMD_SPEED_LBN 4
0083 #define PMA_PMD_SPEED_WIDTH 4
0084
0085
0086 #define PCS_CLOCK_CTRL_REG 55297
0087 #define PLL312_RST_N_LBN 2
0088
0089 #define PCS_SOFT_RST2_REG 55302
0090 #define SERDES_RST_N_LBN 13
0091 #define XGXS_RST_N_LBN 12
0092
0093 #define PCS_TEST_SELECT_REG 55303
0094 #define CLK312_EN_LBN 3
0095
0096
0097 #define PHYXS_XCONTROL_REG 49152
0098 #define PHYXS_RESET_LBN 15
0099 #define PHYXS_RESET_WIDTH 1
0100
0101 #define PHYXS_TEST1 (49162)
0102 #define LOOPBACK_NEAR_LBN (8)
0103 #define LOOPBACK_NEAR_WIDTH (1)
0104
0105
0106 #define PCS_BOOT_STATUS_REG 53248
0107 #define PCS_BOOT_FATAL_ERROR_LBN 0
0108 #define PCS_BOOT_PROGRESS_LBN 1
0109 #define PCS_BOOT_PROGRESS_WIDTH 2
0110 #define PCS_BOOT_PROGRESS_INIT 0
0111 #define PCS_BOOT_PROGRESS_WAIT_MDIO 1
0112 #define PCS_BOOT_PROGRESS_CHECKSUM 2
0113 #define PCS_BOOT_PROGRESS_JUMP 3
0114 #define PCS_BOOT_DOWNLOAD_WAIT_LBN 3
0115 #define PCS_BOOT_CODE_STARTED_LBN 4
0116
0117
0118 #define GPHY_XCONTROL_REG 49152
0119 #define GPHY_ISOLATE_LBN 10
0120 #define GPHY_ISOLATE_WIDTH 1
0121 #define GPHY_DUPLEX_LBN 8
0122 #define GPHY_DUPLEX_WIDTH 1
0123 #define GPHY_LOOPBACK_NEAR_LBN 14
0124 #define GPHY_LOOPBACK_NEAR_WIDTH 1
0125
0126 #define C22EXT_STATUS_REG 49153
0127 #define C22EXT_STATUS_LINK_LBN 2
0128 #define C22EXT_STATUS_LINK_WIDTH 1
0129
0130 #define C22EXT_MSTSLV_CTRL 49161
0131 #define C22EXT_MSTSLV_CTRL_ADV_1000_HD_LBN 8
0132 #define C22EXT_MSTSLV_CTRL_ADV_1000_FD_LBN 9
0133
0134 #define C22EXT_MSTSLV_STATUS 49162
0135 #define C22EXT_MSTSLV_STATUS_LP_1000_HD_LBN 10
0136 #define C22EXT_MSTSLV_STATUS_LP_1000_FD_LBN 11
0137
0138
0139
0140 #define LNPGA_PDOWN_WAIT (HZ / 5)
0141
0142 struct tenxpress_phy_data {
0143 enum ef4_loopback_mode loopback_mode;
0144 enum ef4_phy_mode phy_mode;
0145 int bad_lp_tries;
0146 };
0147
0148 static int tenxpress_init(struct ef4_nic *efx)
0149 {
0150
0151 ef4_mdio_write(efx, MDIO_MMD_PCS, PCS_TEST_SELECT_REG,
0152 1 << CLK312_EN_LBN);
0153
0154
0155 ef4_mdio_set_flag(efx, MDIO_MMD_PMAPMD, PMA_PMD_LED_CTRL_REG,
0156 1 << PMA_PMA_LED_ACTIVITY_LBN, true);
0157 ef4_mdio_write(efx, MDIO_MMD_PMAPMD, PMA_PMD_LED_OVERR_REG,
0158 SFX7101_PMA_PMD_LED_DEFAULT);
0159
0160 return 0;
0161 }
0162
0163 static int tenxpress_phy_probe(struct ef4_nic *efx)
0164 {
0165 struct tenxpress_phy_data *phy_data;
0166
0167
0168 phy_data = kzalloc(sizeof(*phy_data), GFP_KERNEL);
0169 if (!phy_data)
0170 return -ENOMEM;
0171 efx->phy_data = phy_data;
0172 phy_data->phy_mode = efx->phy_mode;
0173
0174 efx->mdio.mmds = TENXPRESS_REQUIRED_DEVS;
0175 efx->mdio.mode_support = MDIO_SUPPORTS_C45;
0176
0177 efx->loopback_modes = SFX7101_LOOPBACKS | FALCON_XMAC_LOOPBACKS;
0178
0179 efx->link_advertising = (ADVERTISED_TP | ADVERTISED_Autoneg |
0180 ADVERTISED_10000baseT_Full);
0181
0182 return 0;
0183 }
0184
0185 static int tenxpress_phy_init(struct ef4_nic *efx)
0186 {
0187 int rc;
0188
0189 falcon_board(efx)->type->init_phy(efx);
0190
0191 if (!(efx->phy_mode & PHY_MODE_SPECIAL)) {
0192 rc = ef4_mdio_wait_reset_mmds(efx, TENXPRESS_REQUIRED_DEVS);
0193 if (rc < 0)
0194 return rc;
0195
0196 rc = ef4_mdio_check_mmds(efx, TENXPRESS_REQUIRED_DEVS);
0197 if (rc < 0)
0198 return rc;
0199 }
0200
0201 rc = tenxpress_init(efx);
0202 if (rc < 0)
0203 return rc;
0204
0205
0206 ef4_link_set_wanted_fc(efx, efx->wanted_fc);
0207 ef4_mdio_an_reconfigure(efx);
0208
0209 schedule_timeout_uninterruptible(HZ / 5);
0210
0211
0212 falcon_reset_xaui(efx);
0213
0214 return 0;
0215 }
0216
0217
0218
0219
0220 static int tenxpress_special_reset(struct ef4_nic *efx)
0221 {
0222 int rc, reg;
0223
0224
0225
0226
0227 falcon_stop_nic_stats(efx);
0228
0229
0230 reg = ef4_mdio_read(efx, MDIO_MMD_PMAPMD, PMA_PMD_XCONTROL_REG);
0231 reg |= (1 << PMA_PMD_EXT_SSR_LBN);
0232 ef4_mdio_write(efx, MDIO_MMD_PMAPMD, PMA_PMD_XCONTROL_REG, reg);
0233
0234 mdelay(200);
0235
0236
0237 rc = ef4_mdio_wait_reset_mmds(efx, TENXPRESS_REQUIRED_DEVS);
0238 if (rc < 0)
0239 goto out;
0240
0241
0242 rc = tenxpress_init(efx);
0243 if (rc < 0)
0244 goto out;
0245
0246
0247 mdelay(10);
0248 out:
0249 falcon_start_nic_stats(efx);
0250 return rc;
0251 }
0252
0253 static void sfx7101_check_bad_lp(struct ef4_nic *efx, bool link_ok)
0254 {
0255 struct tenxpress_phy_data *pd = efx->phy_data;
0256 bool bad_lp;
0257 int reg;
0258
0259 if (link_ok) {
0260 bad_lp = false;
0261 } else {
0262
0263 reg = ef4_mdio_read(efx, MDIO_MMD_AN, MDIO_STAT1);
0264 if (!(reg & MDIO_AN_STAT1_LPABLE))
0265 return;
0266 bad_lp = !(reg & MDIO_AN_STAT1_COMPLETE);
0267 if (bad_lp)
0268 pd->bad_lp_tries++;
0269 }
0270
0271
0272 if (!pd->bad_lp_tries)
0273 return;
0274
0275
0276
0277 if (!bad_lp || pd->bad_lp_tries == MAX_BAD_LP_TRIES) {
0278 reg = ef4_mdio_read(efx, MDIO_MMD_PMAPMD,
0279 PMA_PMD_LED_OVERR_REG);
0280 reg &= ~(PMA_PMD_LED_MASK << PMA_PMD_LED_RX_LBN);
0281 if (!bad_lp) {
0282 reg |= PMA_PMD_LED_OFF << PMA_PMD_LED_RX_LBN;
0283 } else {
0284 reg |= PMA_PMD_LED_FLASH << PMA_PMD_LED_RX_LBN;
0285 netif_err(efx, link, efx->net_dev,
0286 "appears to be plugged into a port"
0287 " that is not 10GBASE-T capable. The PHY"
0288 " supports 10GBASE-T ONLY, so no link can"
0289 " be established\n");
0290 }
0291 ef4_mdio_write(efx, MDIO_MMD_PMAPMD,
0292 PMA_PMD_LED_OVERR_REG, reg);
0293 pd->bad_lp_tries = bad_lp;
0294 }
0295 }
0296
0297 static bool sfx7101_link_ok(struct ef4_nic *efx)
0298 {
0299 return ef4_mdio_links_ok(efx,
0300 MDIO_DEVS_PMAPMD |
0301 MDIO_DEVS_PCS |
0302 MDIO_DEVS_PHYXS);
0303 }
0304
0305 static void tenxpress_ext_loopback(struct ef4_nic *efx)
0306 {
0307 ef4_mdio_set_flag(efx, MDIO_MMD_PHYXS, PHYXS_TEST1,
0308 1 << LOOPBACK_NEAR_LBN,
0309 efx->loopback_mode == LOOPBACK_PHYXS);
0310 }
0311
0312 static void tenxpress_low_power(struct ef4_nic *efx)
0313 {
0314 ef4_mdio_set_mmds_lpower(
0315 efx, !!(efx->phy_mode & PHY_MODE_LOW_POWER),
0316 TENXPRESS_REQUIRED_DEVS);
0317 }
0318
0319 static int tenxpress_phy_reconfigure(struct ef4_nic *efx)
0320 {
0321 struct tenxpress_phy_data *phy_data = efx->phy_data;
0322 bool phy_mode_change, loop_reset;
0323
0324 if (efx->phy_mode & (PHY_MODE_OFF | PHY_MODE_SPECIAL)) {
0325 phy_data->phy_mode = efx->phy_mode;
0326 return 0;
0327 }
0328
0329 phy_mode_change = (efx->phy_mode == PHY_MODE_NORMAL &&
0330 phy_data->phy_mode != PHY_MODE_NORMAL);
0331 loop_reset = (LOOPBACK_OUT_OF(phy_data, efx, LOOPBACKS_EXTERNAL(efx)) ||
0332 LOOPBACK_CHANGED(phy_data, efx, 1 << LOOPBACK_GPHY));
0333
0334 if (loop_reset || phy_mode_change) {
0335 tenxpress_special_reset(efx);
0336 falcon_reset_xaui(efx);
0337 }
0338
0339 tenxpress_low_power(efx);
0340 ef4_mdio_transmit_disable(efx);
0341 ef4_mdio_phy_reconfigure(efx);
0342 tenxpress_ext_loopback(efx);
0343 ef4_mdio_an_reconfigure(efx);
0344
0345 phy_data->loopback_mode = efx->loopback_mode;
0346 phy_data->phy_mode = efx->phy_mode;
0347
0348 return 0;
0349 }
0350
0351
0352 static bool tenxpress_phy_poll(struct ef4_nic *efx)
0353 {
0354 struct ef4_link_state old_state = efx->link_state;
0355
0356 efx->link_state.up = sfx7101_link_ok(efx);
0357 efx->link_state.speed = 10000;
0358 efx->link_state.fd = true;
0359 efx->link_state.fc = ef4_mdio_get_pause(efx);
0360
0361 sfx7101_check_bad_lp(efx, efx->link_state.up);
0362
0363 return !ef4_link_state_equal(&efx->link_state, &old_state);
0364 }
0365
0366 static void sfx7101_phy_fini(struct ef4_nic *efx)
0367 {
0368 int reg;
0369
0370
0371 reg = (1 << PMA_PMD_LNPGA_POWERDOWN_LBN);
0372 ef4_mdio_write(efx, MDIO_MMD_PMAPMD, PMA_PMD_XCONTROL_REG, reg);
0373
0374
0375
0376
0377 schedule_timeout_uninterruptible(LNPGA_PDOWN_WAIT);
0378 }
0379
0380 static void tenxpress_phy_remove(struct ef4_nic *efx)
0381 {
0382 kfree(efx->phy_data);
0383 efx->phy_data = NULL;
0384 }
0385
0386
0387
0388 void tenxpress_set_id_led(struct ef4_nic *efx, enum ef4_led_mode mode)
0389 {
0390 int reg;
0391
0392 switch (mode) {
0393 case EF4_LED_OFF:
0394 reg = (PMA_PMD_LED_OFF << PMA_PMD_LED_TX_LBN) |
0395 (PMA_PMD_LED_OFF << PMA_PMD_LED_RX_LBN) |
0396 (PMA_PMD_LED_OFF << PMA_PMD_LED_LINK_LBN);
0397 break;
0398 case EF4_LED_ON:
0399 reg = (PMA_PMD_LED_ON << PMA_PMD_LED_TX_LBN) |
0400 (PMA_PMD_LED_ON << PMA_PMD_LED_RX_LBN) |
0401 (PMA_PMD_LED_ON << PMA_PMD_LED_LINK_LBN);
0402 break;
0403 default:
0404 reg = SFX7101_PMA_PMD_LED_DEFAULT;
0405 break;
0406 }
0407
0408 ef4_mdio_write(efx, MDIO_MMD_PMAPMD, PMA_PMD_LED_OVERR_REG, reg);
0409 }
0410
0411 static const char *const sfx7101_test_names[] = {
0412 "bist"
0413 };
0414
0415 static const char *sfx7101_test_name(struct ef4_nic *efx, unsigned int index)
0416 {
0417 if (index < ARRAY_SIZE(sfx7101_test_names))
0418 return sfx7101_test_names[index];
0419 return NULL;
0420 }
0421
0422 static int
0423 sfx7101_run_tests(struct ef4_nic *efx, int *results, unsigned flags)
0424 {
0425 int rc;
0426
0427 if (!(flags & ETH_TEST_FL_OFFLINE))
0428 return 0;
0429
0430
0431 rc = tenxpress_special_reset(efx);
0432 results[0] = rc ? -1 : 1;
0433
0434 ef4_mdio_an_reconfigure(efx);
0435
0436 return rc;
0437 }
0438
0439 static void
0440 tenxpress_get_link_ksettings(struct ef4_nic *efx,
0441 struct ethtool_link_ksettings *cmd)
0442 {
0443 u32 adv = 0, lpa = 0;
0444 int reg;
0445
0446 reg = ef4_mdio_read(efx, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL);
0447 if (reg & MDIO_AN_10GBT_CTRL_ADV10G)
0448 adv |= ADVERTISED_10000baseT_Full;
0449 reg = ef4_mdio_read(efx, MDIO_MMD_AN, MDIO_AN_10GBT_STAT);
0450 if (reg & MDIO_AN_10GBT_STAT_LP10G)
0451 lpa |= ADVERTISED_10000baseT_Full;
0452
0453 mdio45_ethtool_ksettings_get_npage(&efx->mdio, cmd, adv, lpa);
0454
0455
0456
0457 if (LOOPBACK_EXTERNAL(efx))
0458 cmd->base.speed = SPEED_10000;
0459 }
0460
0461 static int
0462 tenxpress_set_link_ksettings(struct ef4_nic *efx,
0463 const struct ethtool_link_ksettings *cmd)
0464 {
0465 if (!cmd->base.autoneg)
0466 return -EINVAL;
0467
0468 return ef4_mdio_set_link_ksettings(efx, cmd);
0469 }
0470
0471 static void sfx7101_set_npage_adv(struct ef4_nic *efx, u32 advertising)
0472 {
0473 ef4_mdio_set_flag(efx, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL,
0474 MDIO_AN_10GBT_CTRL_ADV10G,
0475 advertising & ADVERTISED_10000baseT_Full);
0476 }
0477
0478 const struct ef4_phy_operations falcon_sfx7101_phy_ops = {
0479 .probe = tenxpress_phy_probe,
0480 .init = tenxpress_phy_init,
0481 .reconfigure = tenxpress_phy_reconfigure,
0482 .poll = tenxpress_phy_poll,
0483 .fini = sfx7101_phy_fini,
0484 .remove = tenxpress_phy_remove,
0485 .get_link_ksettings = tenxpress_get_link_ksettings,
0486 .set_link_ksettings = tenxpress_set_link_ksettings,
0487 .set_npage_adv = sfx7101_set_npage_adv,
0488 .test_alive = ef4_mdio_test_alive,
0489 .test_name = sfx7101_test_name,
0490 .run_tests = sfx7101_run_tests,
0491 };