0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "pch_gbe.h"
0010 #include "pch_gbe_phy.h"
0011
0012 #define PHY_MAX_REG_ADDRESS 0x1F
0013
0014
0015
0016 #define PHY_CONTROL 0x00
0017 #define PHY_STATUS 0x01
0018 #define PHY_ID1 0x02
0019 #define PHY_ID2 0x03
0020 #define PHY_AUTONEG_ADV 0x04
0021 #define PHY_LP_ABILITY 0x05
0022 #define PHY_AUTONEG_EXP 0x06
0023 #define PHY_NEXT_PAGE_TX 0x07
0024 #define PHY_LP_NEXT_PAGE 0x08
0025 #define PHY_1000T_CTRL 0x09
0026 #define PHY_1000T_STATUS 0x0A
0027 #define PHY_EXT_STATUS 0x0F
0028 #define PHY_PHYSP_CONTROL 0x10
0029 #define PHY_EXT_PHYSP_CONTROL 0x14
0030 #define PHY_LED_CONTROL 0x18
0031 #define PHY_EXT_PHYSP_STATUS 0x1B
0032
0033
0034 #define MII_CR_SPEED_SELECT_MSB 0x0040
0035 #define MII_CR_COLL_TEST_ENABLE 0x0080
0036 #define MII_CR_FULL_DUPLEX 0x0100
0037 #define MII_CR_RESTART_AUTO_NEG 0x0200
0038 #define MII_CR_ISOLATE 0x0400
0039 #define MII_CR_POWER_DOWN 0x0800
0040 #define MII_CR_AUTO_NEG_EN 0x1000
0041 #define MII_CR_SPEED_SELECT_LSB 0x2000
0042 #define MII_CR_LOOPBACK 0x4000
0043 #define MII_CR_RESET 0x8000
0044 #define MII_CR_SPEED_1000 0x0040
0045 #define MII_CR_SPEED_100 0x2000
0046 #define MII_CR_SPEED_10 0x0000
0047
0048
0049 #define MII_SR_EXTENDED_CAPS 0x0001
0050 #define MII_SR_JABBER_DETECT 0x0002
0051 #define MII_SR_LINK_STATUS 0x0004
0052 #define MII_SR_AUTONEG_CAPS 0x0008
0053 #define MII_SR_REMOTE_FAULT 0x0010
0054 #define MII_SR_AUTONEG_COMPLETE 0x0020
0055 #define MII_SR_PREAMBLE_SUPPRESS 0x0040
0056 #define MII_SR_EXTENDED_STATUS 0x0100
0057 #define MII_SR_100T2_HD_CAPS 0x0200
0058 #define MII_SR_100T2_FD_CAPS 0x0400
0059 #define MII_SR_10T_HD_CAPS 0x0800
0060 #define MII_SR_10T_FD_CAPS 0x1000
0061 #define MII_SR_100X_HD_CAPS 0x2000
0062 #define MII_SR_100X_FD_CAPS 0x4000
0063 #define MII_SR_100T4_CAPS 0x8000
0064
0065
0066 #define PHY_AR803X_ID 0x00001374
0067 #define PHY_AR8031_DBG_OFF 0x1D
0068 #define PHY_AR8031_DBG_DAT 0x1E
0069 #define PHY_AR8031_SERDES 0x05
0070 #define PHY_AR8031_HIBERNATE 0x0B
0071 #define PHY_AR8031_SERDES_TX_CLK_DLY 0x0100
0072 #define PHY_AR8031_PS_HIB_EN 0x8000
0073
0074
0075 #define PHY_REVISION_MASK 0x000F
0076
0077
0078 #define PHYSP_CTRL_ASSERT_CRS_TX 0x0800
0079
0080
0081
0082 #define PHY_CONTROL_DEFAULT 0x1140
0083 #define PHY_AUTONEG_ADV_DEFAULT 0x01e0
0084 #define PHY_NEXT_PAGE_TX_DEFAULT 0x2001
0085 #define PHY_1000T_CTRL_DEFAULT 0x0300
0086 #define PHY_PHYSP_CONTROL_DEFAULT 0x01EE
0087
0088
0089
0090
0091
0092
0093
0094
0095 s32 pch_gbe_phy_get_id(struct pch_gbe_hw *hw)
0096 {
0097 struct pch_gbe_adapter *adapter = pch_gbe_hw_to_adapter(hw);
0098 struct pch_gbe_phy_info *phy = &hw->phy;
0099 s32 ret;
0100 u16 phy_id1;
0101 u16 phy_id2;
0102
0103 ret = pch_gbe_phy_read_reg_miic(hw, PHY_ID1, &phy_id1);
0104 if (ret)
0105 return ret;
0106 ret = pch_gbe_phy_read_reg_miic(hw, PHY_ID2, &phy_id2);
0107 if (ret)
0108 return ret;
0109
0110
0111
0112
0113 phy->id = (u32)phy_id1;
0114 phy->id = ((phy->id << 6) | ((phy_id2 & 0xFC00) >> 10));
0115 phy->revision = (u32) (phy_id2 & 0x000F);
0116 netdev_dbg(adapter->netdev,
0117 "phy->id : 0x%08x phy->revision : 0x%08x\n",
0118 phy->id, phy->revision);
0119 return 0;
0120 }
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131 s32 pch_gbe_phy_read_reg_miic(struct pch_gbe_hw *hw, u32 offset, u16 *data)
0132 {
0133 struct pch_gbe_phy_info *phy = &hw->phy;
0134
0135 if (offset > PHY_MAX_REG_ADDRESS) {
0136 struct pch_gbe_adapter *adapter = pch_gbe_hw_to_adapter(hw);
0137
0138 netdev_err(adapter->netdev, "PHY Address %d is out of range\n",
0139 offset);
0140 return -EINVAL;
0141 }
0142 *data = pch_gbe_mac_ctrl_miim(hw, phy->addr, PCH_GBE_HAL_MIIM_READ,
0143 offset, (u16)0);
0144 return 0;
0145 }
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156 s32 pch_gbe_phy_write_reg_miic(struct pch_gbe_hw *hw, u32 offset, u16 data)
0157 {
0158 struct pch_gbe_phy_info *phy = &hw->phy;
0159
0160 if (offset > PHY_MAX_REG_ADDRESS) {
0161 struct pch_gbe_adapter *adapter = pch_gbe_hw_to_adapter(hw);
0162
0163 netdev_err(adapter->netdev, "PHY Address %d is out of range\n",
0164 offset);
0165 return -EINVAL;
0166 }
0167 pch_gbe_mac_ctrl_miim(hw, phy->addr, PCH_GBE_HAL_MIIM_WRITE,
0168 offset, data);
0169 return 0;
0170 }
0171
0172
0173
0174
0175
0176 static void pch_gbe_phy_sw_reset(struct pch_gbe_hw *hw)
0177 {
0178 u16 phy_ctrl;
0179
0180 pch_gbe_phy_read_reg_miic(hw, PHY_CONTROL, &phy_ctrl);
0181 phy_ctrl |= MII_CR_RESET;
0182 pch_gbe_phy_write_reg_miic(hw, PHY_CONTROL, phy_ctrl);
0183 udelay(1);
0184 }
0185
0186
0187
0188
0189
0190 void pch_gbe_phy_hw_reset(struct pch_gbe_hw *hw)
0191 {
0192 pch_gbe_phy_write_reg_miic(hw, PHY_CONTROL, PHY_CONTROL_DEFAULT);
0193 pch_gbe_phy_write_reg_miic(hw, PHY_AUTONEG_ADV,
0194 PHY_AUTONEG_ADV_DEFAULT);
0195 pch_gbe_phy_write_reg_miic(hw, PHY_NEXT_PAGE_TX,
0196 PHY_NEXT_PAGE_TX_DEFAULT);
0197 pch_gbe_phy_write_reg_miic(hw, PHY_1000T_CTRL, PHY_1000T_CTRL_DEFAULT);
0198 pch_gbe_phy_write_reg_miic(hw, PHY_PHYSP_CONTROL,
0199 PHY_PHYSP_CONTROL_DEFAULT);
0200 }
0201
0202
0203
0204
0205
0206 void pch_gbe_phy_power_up(struct pch_gbe_hw *hw)
0207 {
0208 u16 mii_reg;
0209
0210 mii_reg = 0;
0211
0212
0213
0214 pch_gbe_phy_read_reg_miic(hw, PHY_CONTROL, &mii_reg);
0215 mii_reg &= ~MII_CR_POWER_DOWN;
0216 pch_gbe_phy_write_reg_miic(hw, PHY_CONTROL, mii_reg);
0217 }
0218
0219
0220
0221
0222
0223 void pch_gbe_phy_power_down(struct pch_gbe_hw *hw)
0224 {
0225 u16 mii_reg;
0226
0227 mii_reg = 0;
0228
0229
0230
0231
0232
0233 pch_gbe_phy_read_reg_miic(hw, PHY_CONTROL, &mii_reg);
0234 mii_reg |= MII_CR_POWER_DOWN;
0235 pch_gbe_phy_write_reg_miic(hw, PHY_CONTROL, mii_reg);
0236 mdelay(1);
0237 }
0238
0239
0240
0241
0242
0243 void pch_gbe_phy_set_rgmii(struct pch_gbe_hw *hw)
0244 {
0245 pch_gbe_phy_sw_reset(hw);
0246 }
0247
0248
0249
0250
0251
0252
0253
0254
0255 static int pch_gbe_phy_tx_clk_delay(struct pch_gbe_hw *hw)
0256 {
0257
0258
0259
0260
0261 struct pch_gbe_adapter *adapter = pch_gbe_hw_to_adapter(hw);
0262 u16 mii_reg;
0263 int ret = 0;
0264
0265 switch (hw->phy.id) {
0266 case PHY_AR803X_ID:
0267 netdev_dbg(adapter->netdev,
0268 "Configuring AR803X PHY for 2ns TX clock delay\n");
0269 pch_gbe_phy_read_reg_miic(hw, PHY_AR8031_DBG_OFF, &mii_reg);
0270 ret = pch_gbe_phy_write_reg_miic(hw, PHY_AR8031_DBG_OFF,
0271 PHY_AR8031_SERDES);
0272 if (ret)
0273 break;
0274
0275 pch_gbe_phy_read_reg_miic(hw, PHY_AR8031_DBG_DAT, &mii_reg);
0276 mii_reg |= PHY_AR8031_SERDES_TX_CLK_DLY;
0277 ret = pch_gbe_phy_write_reg_miic(hw, PHY_AR8031_DBG_DAT,
0278 mii_reg);
0279 break;
0280 default:
0281 netdev_err(adapter->netdev,
0282 "Unknown PHY (%x), could not set TX clock delay\n",
0283 hw->phy.id);
0284 return -EINVAL;
0285 }
0286
0287 if (ret)
0288 netdev_err(adapter->netdev,
0289 "Could not configure tx clock delay for PHY\n");
0290 return ret;
0291 }
0292
0293
0294
0295
0296
0297 void pch_gbe_phy_init_setting(struct pch_gbe_hw *hw)
0298 {
0299 struct pch_gbe_adapter *adapter = pch_gbe_hw_to_adapter(hw);
0300 struct ethtool_cmd cmd = { .cmd = ETHTOOL_GSET };
0301 int ret;
0302 u16 mii_reg;
0303
0304 mii_ethtool_gset(&adapter->mii, &cmd);
0305
0306 ethtool_cmd_speed_set(&cmd, hw->mac.link_speed);
0307 cmd.duplex = hw->mac.link_duplex;
0308 cmd.advertising = hw->phy.autoneg_advertised;
0309 cmd.autoneg = hw->mac.autoneg;
0310 pch_gbe_phy_write_reg_miic(hw, MII_BMCR, BMCR_RESET);
0311 ret = mii_ethtool_sset(&adapter->mii, &cmd);
0312 if (ret)
0313 netdev_err(adapter->netdev, "Error: mii_ethtool_sset\n");
0314
0315 pch_gbe_phy_sw_reset(hw);
0316
0317 pch_gbe_phy_read_reg_miic(hw, PHY_PHYSP_CONTROL, &mii_reg);
0318 mii_reg |= PHYSP_CTRL_ASSERT_CRS_TX;
0319 pch_gbe_phy_write_reg_miic(hw, PHY_PHYSP_CONTROL, mii_reg);
0320
0321
0322 if (adapter->pdata && adapter->pdata->phy_tx_clk_delay)
0323 pch_gbe_phy_tx_clk_delay(hw);
0324 }
0325
0326
0327
0328
0329
0330
0331
0332
0333 int pch_gbe_phy_disable_hibernate(struct pch_gbe_hw *hw)
0334 {
0335 struct pch_gbe_adapter *adapter = pch_gbe_hw_to_adapter(hw);
0336 u16 mii_reg;
0337 int ret = 0;
0338
0339 switch (hw->phy.id) {
0340 case PHY_AR803X_ID:
0341 netdev_dbg(adapter->netdev,
0342 "Disabling hibernation for AR803X PHY\n");
0343 ret = pch_gbe_phy_write_reg_miic(hw, PHY_AR8031_DBG_OFF,
0344 PHY_AR8031_HIBERNATE);
0345 if (ret)
0346 break;
0347
0348 pch_gbe_phy_read_reg_miic(hw, PHY_AR8031_DBG_DAT, &mii_reg);
0349 mii_reg &= ~PHY_AR8031_PS_HIB_EN;
0350 ret = pch_gbe_phy_write_reg_miic(hw, PHY_AR8031_DBG_DAT,
0351 mii_reg);
0352 break;
0353 default:
0354 netdev_err(adapter->netdev,
0355 "Unknown PHY (%x), could not disable hibernation\n",
0356 hw->phy.id);
0357 return -EINVAL;
0358 }
0359
0360 if (ret)
0361 netdev_err(adapter->netdev,
0362 "Could not disable PHY hibernation\n");
0363 return ret;
0364 }