1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20#include "pch_gbe.h"
21#include "pch_gbe_phy.h"
22
23#define PHY_MAX_REG_ADDRESS 0x1F
24
25
26
27#define PHY_CONTROL 0x00
28#define PHY_STATUS 0x01
29#define PHY_ID1 0x02
30#define PHY_ID2 0x03
31#define PHY_AUTONEG_ADV 0x04
32#define PHY_LP_ABILITY 0x05
33#define PHY_AUTONEG_EXP 0x06
34#define PHY_NEXT_PAGE_TX 0x07
35#define PHY_LP_NEXT_PAGE 0x08
36#define PHY_1000T_CTRL 0x09
37#define PHY_1000T_STATUS 0x0A
38#define PHY_EXT_STATUS 0x0F
39#define PHY_PHYSP_CONTROL 0x10
40#define PHY_EXT_PHYSP_CONTROL 0x14
41#define PHY_LED_CONTROL 0x18
42#define PHY_EXT_PHYSP_STATUS 0x1B
43
44
45#define MII_CR_SPEED_SELECT_MSB 0x0040
46#define MII_CR_COLL_TEST_ENABLE 0x0080
47#define MII_CR_FULL_DUPLEX 0x0100
48#define MII_CR_RESTART_AUTO_NEG 0x0200
49#define MII_CR_ISOLATE 0x0400
50#define MII_CR_POWER_DOWN 0x0800
51#define MII_CR_AUTO_NEG_EN 0x1000
52#define MII_CR_SPEED_SELECT_LSB 0x2000
53#define MII_CR_LOOPBACK 0x4000
54#define MII_CR_RESET 0x8000
55#define MII_CR_SPEED_1000 0x0040
56#define MII_CR_SPEED_100 0x2000
57#define MII_CR_SPEED_10 0x0000
58
59
60#define MII_SR_EXTENDED_CAPS 0x0001
61#define MII_SR_JABBER_DETECT 0x0002
62#define MII_SR_LINK_STATUS 0x0004
63#define MII_SR_AUTONEG_CAPS 0x0008
64#define MII_SR_REMOTE_FAULT 0x0010
65#define MII_SR_AUTONEG_COMPLETE 0x0020
66#define MII_SR_PREAMBLE_SUPPRESS 0x0040
67#define MII_SR_EXTENDED_STATUS 0x0100
68#define MII_SR_100T2_HD_CAPS 0x0200
69#define MII_SR_100T2_FD_CAPS 0x0400
70#define MII_SR_10T_HD_CAPS 0x0800
71#define MII_SR_10T_FD_CAPS 0x1000
72#define MII_SR_100X_HD_CAPS 0x2000
73#define MII_SR_100X_FD_CAPS 0x4000
74#define MII_SR_100T4_CAPS 0x8000
75
76
77#define PHY_AR803X_ID 0x00001374
78#define PHY_AR8031_DBG_OFF 0x1D
79#define PHY_AR8031_DBG_DAT 0x1E
80#define PHY_AR8031_SERDES 0x05
81#define PHY_AR8031_HIBERNATE 0x0B
82#define PHY_AR8031_SERDES_TX_CLK_DLY 0x0100
83#define PHY_AR8031_PS_HIB_EN 0x8000
84
85
86#define PHY_REVISION_MASK 0x000F
87
88
89#define PHYSP_CTRL_ASSERT_CRS_TX 0x0800
90
91
92
93#define PHY_CONTROL_DEFAULT 0x1140
94#define PHY_AUTONEG_ADV_DEFAULT 0x01e0
95#define PHY_NEXT_PAGE_TX_DEFAULT 0x2001
96#define PHY_1000T_CTRL_DEFAULT 0x0300
97#define PHY_PHYSP_CONTROL_DEFAULT 0x01EE
98
99
100
101
102
103
104
105
106s32 pch_gbe_phy_get_id(struct pch_gbe_hw *hw)
107{
108 struct pch_gbe_adapter *adapter = pch_gbe_hw_to_adapter(hw);
109 struct pch_gbe_phy_info *phy = &hw->phy;
110 s32 ret;
111 u16 phy_id1;
112 u16 phy_id2;
113
114 ret = pch_gbe_phy_read_reg_miic(hw, PHY_ID1, &phy_id1);
115 if (ret)
116 return ret;
117 ret = pch_gbe_phy_read_reg_miic(hw, PHY_ID2, &phy_id2);
118 if (ret)
119 return ret;
120
121
122
123
124 phy->id = (u32)phy_id1;
125 phy->id = ((phy->id << 6) | ((phy_id2 & 0xFC00) >> 10));
126 phy->revision = (u32) (phy_id2 & 0x000F);
127 netdev_dbg(adapter->netdev,
128 "phy->id : 0x%08x phy->revision : 0x%08x\n",
129 phy->id, phy->revision);
130 return 0;
131}
132
133
134
135
136
137
138
139
140
141
142s32 pch_gbe_phy_read_reg_miic(struct pch_gbe_hw *hw, u32 offset, u16 *data)
143{
144 struct pch_gbe_phy_info *phy = &hw->phy;
145
146 if (offset > PHY_MAX_REG_ADDRESS) {
147 struct pch_gbe_adapter *adapter = pch_gbe_hw_to_adapter(hw);
148
149 netdev_err(adapter->netdev, "PHY Address %d is out of range\n",
150 offset);
151 return -EINVAL;
152 }
153 *data = pch_gbe_mac_ctrl_miim(hw, phy->addr, PCH_GBE_HAL_MIIM_READ,
154 offset, (u16)0);
155 return 0;
156}
157
158
159
160
161
162
163
164
165
166
167s32 pch_gbe_phy_write_reg_miic(struct pch_gbe_hw *hw, u32 offset, u16 data)
168{
169 struct pch_gbe_phy_info *phy = &hw->phy;
170
171 if (offset > PHY_MAX_REG_ADDRESS) {
172 struct pch_gbe_adapter *adapter = pch_gbe_hw_to_adapter(hw);
173
174 netdev_err(adapter->netdev, "PHY Address %d is out of range\n",
175 offset);
176 return -EINVAL;
177 }
178 pch_gbe_mac_ctrl_miim(hw, phy->addr, PCH_GBE_HAL_MIIM_WRITE,
179 offset, data);
180 return 0;
181}
182
183
184
185
186
187static void pch_gbe_phy_sw_reset(struct pch_gbe_hw *hw)
188{
189 u16 phy_ctrl;
190
191 pch_gbe_phy_read_reg_miic(hw, PHY_CONTROL, &phy_ctrl);
192 phy_ctrl |= MII_CR_RESET;
193 pch_gbe_phy_write_reg_miic(hw, PHY_CONTROL, phy_ctrl);
194 udelay(1);
195}
196
197
198
199
200
201void pch_gbe_phy_hw_reset(struct pch_gbe_hw *hw)
202{
203 pch_gbe_phy_write_reg_miic(hw, PHY_CONTROL, PHY_CONTROL_DEFAULT);
204 pch_gbe_phy_write_reg_miic(hw, PHY_AUTONEG_ADV,
205 PHY_AUTONEG_ADV_DEFAULT);
206 pch_gbe_phy_write_reg_miic(hw, PHY_NEXT_PAGE_TX,
207 PHY_NEXT_PAGE_TX_DEFAULT);
208 pch_gbe_phy_write_reg_miic(hw, PHY_1000T_CTRL, PHY_1000T_CTRL_DEFAULT);
209 pch_gbe_phy_write_reg_miic(hw, PHY_PHYSP_CONTROL,
210 PHY_PHYSP_CONTROL_DEFAULT);
211}
212
213
214
215
216
217void pch_gbe_phy_power_up(struct pch_gbe_hw *hw)
218{
219 u16 mii_reg;
220
221 mii_reg = 0;
222
223
224
225 pch_gbe_phy_read_reg_miic(hw, PHY_CONTROL, &mii_reg);
226 mii_reg &= ~MII_CR_POWER_DOWN;
227 pch_gbe_phy_write_reg_miic(hw, PHY_CONTROL, mii_reg);
228}
229
230
231
232
233
234void pch_gbe_phy_power_down(struct pch_gbe_hw *hw)
235{
236 u16 mii_reg;
237
238 mii_reg = 0;
239
240
241
242
243
244 pch_gbe_phy_read_reg_miic(hw, PHY_CONTROL, &mii_reg);
245 mii_reg |= MII_CR_POWER_DOWN;
246 pch_gbe_phy_write_reg_miic(hw, PHY_CONTROL, mii_reg);
247 mdelay(1);
248}
249
250
251
252
253
254void pch_gbe_phy_set_rgmii(struct pch_gbe_hw *hw)
255{
256 pch_gbe_phy_sw_reset(hw);
257}
258
259
260
261
262
263
264
265
266static int pch_gbe_phy_tx_clk_delay(struct pch_gbe_hw *hw)
267{
268
269
270
271
272 struct pch_gbe_adapter *adapter = pch_gbe_hw_to_adapter(hw);
273 u16 mii_reg;
274 int ret = 0;
275
276 switch (hw->phy.id) {
277 case PHY_AR803X_ID:
278 netdev_dbg(adapter->netdev,
279 "Configuring AR803X PHY for 2ns TX clock delay\n");
280 pch_gbe_phy_read_reg_miic(hw, PHY_AR8031_DBG_OFF, &mii_reg);
281 ret = pch_gbe_phy_write_reg_miic(hw, PHY_AR8031_DBG_OFF,
282 PHY_AR8031_SERDES);
283 if (ret)
284 break;
285
286 pch_gbe_phy_read_reg_miic(hw, PHY_AR8031_DBG_DAT, &mii_reg);
287 mii_reg |= PHY_AR8031_SERDES_TX_CLK_DLY;
288 ret = pch_gbe_phy_write_reg_miic(hw, PHY_AR8031_DBG_DAT,
289 mii_reg);
290 break;
291 default:
292 netdev_err(adapter->netdev,
293 "Unknown PHY (%x), could not set TX clock delay\n",
294 hw->phy.id);
295 return -EINVAL;
296 }
297
298 if (ret)
299 netdev_err(adapter->netdev,
300 "Could not configure tx clock delay for PHY\n");
301 return ret;
302}
303
304
305
306
307
308void pch_gbe_phy_init_setting(struct pch_gbe_hw *hw)
309{
310 struct pch_gbe_adapter *adapter = pch_gbe_hw_to_adapter(hw);
311 struct ethtool_cmd cmd = { .cmd = ETHTOOL_GSET };
312 int ret;
313 u16 mii_reg;
314
315 ret = mii_ethtool_gset(&adapter->mii, &cmd);
316 if (ret)
317 netdev_err(adapter->netdev, "Error: mii_ethtool_gset\n");
318
319 ethtool_cmd_speed_set(&cmd, hw->mac.link_speed);
320 cmd.duplex = hw->mac.link_duplex;
321 cmd.advertising = hw->phy.autoneg_advertised;
322 cmd.autoneg = hw->mac.autoneg;
323 pch_gbe_phy_write_reg_miic(hw, MII_BMCR, BMCR_RESET);
324 ret = mii_ethtool_sset(&adapter->mii, &cmd);
325 if (ret)
326 netdev_err(adapter->netdev, "Error: mii_ethtool_sset\n");
327
328 pch_gbe_phy_sw_reset(hw);
329
330 pch_gbe_phy_read_reg_miic(hw, PHY_PHYSP_CONTROL, &mii_reg);
331 mii_reg |= PHYSP_CTRL_ASSERT_CRS_TX;
332 pch_gbe_phy_write_reg_miic(hw, PHY_PHYSP_CONTROL, mii_reg);
333
334
335 if (adapter->pdata && adapter->pdata->phy_tx_clk_delay)
336 pch_gbe_phy_tx_clk_delay(hw);
337}
338
339
340
341
342
343
344
345
346int pch_gbe_phy_disable_hibernate(struct pch_gbe_hw *hw)
347{
348 struct pch_gbe_adapter *adapter = pch_gbe_hw_to_adapter(hw);
349 u16 mii_reg;
350 int ret = 0;
351
352 switch (hw->phy.id) {
353 case PHY_AR803X_ID:
354 netdev_dbg(adapter->netdev,
355 "Disabling hibernation for AR803X PHY\n");
356 ret = pch_gbe_phy_write_reg_miic(hw, PHY_AR8031_DBG_OFF,
357 PHY_AR8031_HIBERNATE);
358 if (ret)
359 break;
360
361 pch_gbe_phy_read_reg_miic(hw, PHY_AR8031_DBG_DAT, &mii_reg);
362 mii_reg &= ~PHY_AR8031_PS_HIB_EN;
363 ret = pch_gbe_phy_write_reg_miic(hw, PHY_AR8031_DBG_DAT,
364 mii_reg);
365 break;
366 default:
367 netdev_err(adapter->netdev,
368 "Unknown PHY (%x), could not disable hibernation\n",
369 hw->phy.id);
370 return -EINVAL;
371 }
372
373 if (ret)
374 netdev_err(adapter->netdev,
375 "Could not disable PHY hibernation\n");
376 return ret;
377}
378