1eef4f27bSRobert Mustacchi /*
2eef4f27bSRobert Mustacchi * Copyright 2014-2017 Cavium, Inc.
3eef4f27bSRobert Mustacchi * The contents of this file are subject to the terms of the Common Development
4eef4f27bSRobert Mustacchi * and Distribution License, v.1, (the "License").
5eef4f27bSRobert Mustacchi *
6eef4f27bSRobert Mustacchi * You may not use this file except in compliance with the License.
7eef4f27bSRobert Mustacchi *
8eef4f27bSRobert Mustacchi * You can obtain a copy of the License at available
9eef4f27bSRobert Mustacchi * at http://opensource.org/licenses/CDDL-1.0
10eef4f27bSRobert Mustacchi *
11eef4f27bSRobert Mustacchi * See the License for the specific language governing permissions and
12eef4f27bSRobert Mustacchi * limitations under the License.
13eef4f27bSRobert Mustacchi */
14eef4f27bSRobert Mustacchi
15eef4f27bSRobert Mustacchi #include "54xx_reg.h"
16eef4f27bSRobert Mustacchi #include "serdes.h"
17eef4f27bSRobert Mustacchi #include "lm5706.h"
18eef4f27bSRobert Mustacchi #include "netlink.h"
19eef4f27bSRobert Mustacchi
20eef4f27bSRobert Mustacchi
21eef4f27bSRobert Mustacchi
22eef4f27bSRobert Mustacchi /*******************************************************************************
23eef4f27bSRobert Mustacchi * Macros.
24eef4f27bSRobert Mustacchi ******************************************************************************/
25eef4f27bSRobert Mustacchi
26eef4f27bSRobert Mustacchi #define MII_REG(_type, _field) (OFFSETOF(_type, _field)/2)
27eef4f27bSRobert Mustacchi
28eef4f27bSRobert Mustacchi
29eef4f27bSRobert Mustacchi
30eef4f27bSRobert Mustacchi /*******************************************************************************
31eef4f27bSRobert Mustacchi * Description:
32eef4f27bSRobert Mustacchi *
33eef4f27bSRobert Mustacchi * Return:
34eef4f27bSRobert Mustacchi ******************************************************************************/
35eef4f27bSRobert Mustacchi lm_status_t
lm_mwrite(lm_device_t * pdev,u32_t phy_addr,u32_t reg,u32_t val)36eef4f27bSRobert Mustacchi lm_mwrite(
37eef4f27bSRobert Mustacchi lm_device_t *pdev,
38eef4f27bSRobert Mustacchi u32_t phy_addr,
39eef4f27bSRobert Mustacchi u32_t reg,
40eef4f27bSRobert Mustacchi u32_t val)
41eef4f27bSRobert Mustacchi {
42eef4f27bSRobert Mustacchi lm_status_t lm_status;
43eef4f27bSRobert Mustacchi u32_t tmp;
44eef4f27bSRobert Mustacchi u32_t cnt;
45eef4f27bSRobert Mustacchi
46eef4f27bSRobert Mustacchi DbgBreakIf(pdev->params.enable_remote_phy);
47eef4f27bSRobert Mustacchi
48eef4f27bSRobert Mustacchi if(pdev->params.phy_int_mode == PHY_INT_MODE_AUTO_POLLING)
49eef4f27bSRobert Mustacchi {
50eef4f27bSRobert Mustacchi REG_RD(pdev, emac.emac_mdio_mode, &tmp);
51eef4f27bSRobert Mustacchi tmp &= ~EMAC_MDIO_MODE_AUTO_POLL;
52eef4f27bSRobert Mustacchi
53eef4f27bSRobert Mustacchi REG_WR(pdev, emac.emac_mdio_mode, tmp);
54eef4f27bSRobert Mustacchi
55eef4f27bSRobert Mustacchi mm_wait(pdev, 40);
56eef4f27bSRobert Mustacchi }
57eef4f27bSRobert Mustacchi
58*55fea89dSDan Cross tmp = (phy_addr << 21) |
59*55fea89dSDan Cross (reg << 16) |
60eef4f27bSRobert Mustacchi val |
61eef4f27bSRobert Mustacchi EMAC_MDIO_COMM_COMMAND_WRITE_TE |
62eef4f27bSRobert Mustacchi EMAC_MDIO_COMM_START_BUSY |
63eef4f27bSRobert Mustacchi EMAC_MDIO_COMM_DISEXT;
64eef4f27bSRobert Mustacchi
65eef4f27bSRobert Mustacchi REG_WR(pdev, emac.emac_mdio_comm, tmp);
66*55fea89dSDan Cross
67eef4f27bSRobert Mustacchi for(cnt = 0; cnt < 1000; cnt++)
68eef4f27bSRobert Mustacchi {
69eef4f27bSRobert Mustacchi mm_wait(pdev, 10);
70eef4f27bSRobert Mustacchi
71eef4f27bSRobert Mustacchi REG_RD(pdev, emac.emac_mdio_comm, &tmp);
72eef4f27bSRobert Mustacchi if(!(tmp & EMAC_MDIO_COMM_START_BUSY))
73eef4f27bSRobert Mustacchi {
74eef4f27bSRobert Mustacchi mm_wait(pdev, 5);
75eef4f27bSRobert Mustacchi break;
76eef4f27bSRobert Mustacchi }
77eef4f27bSRobert Mustacchi }
78eef4f27bSRobert Mustacchi
79eef4f27bSRobert Mustacchi if(tmp & EMAC_MDIO_COMM_START_BUSY)
80eef4f27bSRobert Mustacchi {
81eef4f27bSRobert Mustacchi DbgBreakMsg("Write phy register failed\n");
82eef4f27bSRobert Mustacchi
83eef4f27bSRobert Mustacchi lm_status = LM_STATUS_FAILURE;
84eef4f27bSRobert Mustacchi }
85eef4f27bSRobert Mustacchi else
86eef4f27bSRobert Mustacchi {
87eef4f27bSRobert Mustacchi lm_status = LM_STATUS_SUCCESS;
88eef4f27bSRobert Mustacchi }
89eef4f27bSRobert Mustacchi
90eef4f27bSRobert Mustacchi if(pdev->params.phy_int_mode == PHY_INT_MODE_AUTO_POLLING)
91eef4f27bSRobert Mustacchi {
92eef4f27bSRobert Mustacchi REG_RD(pdev, emac.emac_mdio_mode, &tmp);
93eef4f27bSRobert Mustacchi tmp |= EMAC_MDIO_MODE_AUTO_POLL;
94eef4f27bSRobert Mustacchi
95eef4f27bSRobert Mustacchi REG_WR(pdev, emac.emac_mdio_mode, tmp);
96eef4f27bSRobert Mustacchi }
97eef4f27bSRobert Mustacchi
98eef4f27bSRobert Mustacchi return lm_status;
99eef4f27bSRobert Mustacchi } /* lm_mwrite */
100eef4f27bSRobert Mustacchi
101eef4f27bSRobert Mustacchi
102eef4f27bSRobert Mustacchi
103eef4f27bSRobert Mustacchi /*******************************************************************************
104eef4f27bSRobert Mustacchi * Description:
105eef4f27bSRobert Mustacchi *
106eef4f27bSRobert Mustacchi * Return:
107eef4f27bSRobert Mustacchi ******************************************************************************/
108eef4f27bSRobert Mustacchi lm_status_t
lm_mread(lm_device_t * pdev,u32_t phy_addr,u32_t reg,u32_t * ret_val)109eef4f27bSRobert Mustacchi lm_mread(
110eef4f27bSRobert Mustacchi lm_device_t *pdev,
111eef4f27bSRobert Mustacchi u32_t phy_addr,
112eef4f27bSRobert Mustacchi u32_t reg,
113eef4f27bSRobert Mustacchi u32_t *ret_val)
114eef4f27bSRobert Mustacchi {
115eef4f27bSRobert Mustacchi lm_status_t lm_status;
116eef4f27bSRobert Mustacchi u32_t val;
117eef4f27bSRobert Mustacchi u32_t cnt;
118eef4f27bSRobert Mustacchi
119eef4f27bSRobert Mustacchi DbgBreakIf(pdev->params.enable_remote_phy);
120eef4f27bSRobert Mustacchi
121eef4f27bSRobert Mustacchi if(pdev->params.phy_int_mode == PHY_INT_MODE_AUTO_POLLING)
122eef4f27bSRobert Mustacchi {
123eef4f27bSRobert Mustacchi REG_RD(pdev, emac.emac_mdio_mode, &val);
124eef4f27bSRobert Mustacchi val &= ~EMAC_MDIO_MODE_AUTO_POLL;
125eef4f27bSRobert Mustacchi
126eef4f27bSRobert Mustacchi REG_WR(pdev, emac.emac_mdio_mode, val);
127eef4f27bSRobert Mustacchi
128eef4f27bSRobert Mustacchi mm_wait(pdev, 40);
129eef4f27bSRobert Mustacchi }
130eef4f27bSRobert Mustacchi
131*55fea89dSDan Cross val = (phy_addr << 21) |
132eef4f27bSRobert Mustacchi (reg << 16) |
133eef4f27bSRobert Mustacchi EMAC_MDIO_COMM_COMMAND_READ_TE |
134eef4f27bSRobert Mustacchi EMAC_MDIO_COMM_DISEXT |
135eef4f27bSRobert Mustacchi EMAC_MDIO_COMM_START_BUSY;
136eef4f27bSRobert Mustacchi
137eef4f27bSRobert Mustacchi REG_WR(pdev, emac.emac_mdio_comm, val);
138eef4f27bSRobert Mustacchi
139eef4f27bSRobert Mustacchi for(cnt = 0; cnt < 1000; cnt++)
140eef4f27bSRobert Mustacchi {
141eef4f27bSRobert Mustacchi mm_wait(pdev, 10);
142eef4f27bSRobert Mustacchi
143eef4f27bSRobert Mustacchi REG_RD(pdev, emac.emac_mdio_comm, &val);
144eef4f27bSRobert Mustacchi if(!(val & EMAC_MDIO_COMM_START_BUSY))
145eef4f27bSRobert Mustacchi {
146eef4f27bSRobert Mustacchi /* There is a bug here. The MI_COM_BUSY bit may be cleared
147eef4f27bSRobert Mustacchi * before the data is loaded into the register. */
148eef4f27bSRobert Mustacchi REG_RD(pdev, emac.emac_mdio_comm, &val);
149eef4f27bSRobert Mustacchi
150eef4f27bSRobert Mustacchi REG_RD(pdev, emac.emac_mdio_comm, &val);
151eef4f27bSRobert Mustacchi val &= EMAC_MDIO_COMM_DATA;
152eef4f27bSRobert Mustacchi
153eef4f27bSRobert Mustacchi break;
154eef4f27bSRobert Mustacchi }
155eef4f27bSRobert Mustacchi }
156eef4f27bSRobert Mustacchi
157eef4f27bSRobert Mustacchi if(val & EMAC_MDIO_COMM_START_BUSY)
158eef4f27bSRobert Mustacchi {
159eef4f27bSRobert Mustacchi DbgBreakMsg("Read phy register failed\n");
160eef4f27bSRobert Mustacchi
161eef4f27bSRobert Mustacchi val = 0;
162eef4f27bSRobert Mustacchi
163eef4f27bSRobert Mustacchi lm_status = LM_STATUS_FAILURE;
164eef4f27bSRobert Mustacchi }
165eef4f27bSRobert Mustacchi else
166eef4f27bSRobert Mustacchi {
167eef4f27bSRobert Mustacchi lm_status = LM_STATUS_SUCCESS;
168eef4f27bSRobert Mustacchi }
169eef4f27bSRobert Mustacchi
170eef4f27bSRobert Mustacchi *ret_val = val;
171eef4f27bSRobert Mustacchi
172eef4f27bSRobert Mustacchi if(pdev->params.phy_int_mode == PHY_INT_MODE_AUTO_POLLING)
173eef4f27bSRobert Mustacchi {
174eef4f27bSRobert Mustacchi REG_RD(pdev, emac.emac_mdio_mode, &val);
175eef4f27bSRobert Mustacchi val |= EMAC_MDIO_MODE_AUTO_POLL;
176eef4f27bSRobert Mustacchi
177eef4f27bSRobert Mustacchi REG_WR(pdev, emac.emac_mdio_mode, val);
178eef4f27bSRobert Mustacchi }
179eef4f27bSRobert Mustacchi
180eef4f27bSRobert Mustacchi return lm_status;
181eef4f27bSRobert Mustacchi } /* lm_mread */
182eef4f27bSRobert Mustacchi
183eef4f27bSRobert Mustacchi
184eef4f27bSRobert Mustacchi
185eef4f27bSRobert Mustacchi /*******************************************************************************
186eef4f27bSRobert Mustacchi * Description:
187eef4f27bSRobert Mustacchi *
188eef4f27bSRobert Mustacchi * Return:
189eef4f27bSRobert Mustacchi ******************************************************************************/
190eef4f27bSRobert Mustacchi STATIC u32_t
phy_ad_settings(lm_device_t * pdev,lm_medium_t req_medium,lm_flow_control_t flow_ctrl)191eef4f27bSRobert Mustacchi phy_ad_settings(
192eef4f27bSRobert Mustacchi lm_device_t *pdev,
193eef4f27bSRobert Mustacchi lm_medium_t req_medium,
194eef4f27bSRobert Mustacchi lm_flow_control_t flow_ctrl)
195eef4f27bSRobert Mustacchi {
196eef4f27bSRobert Mustacchi u32_t val;
197eef4f27bSRobert Mustacchi
198eef4f27bSRobert Mustacchi val = 0;
199eef4f27bSRobert Mustacchi
200eef4f27bSRobert Mustacchi /* Please refer to Table 28B-3 of the 802.3ab-1999 spec. */
201eef4f27bSRobert Mustacchi if((flow_ctrl == LM_FLOW_CONTROL_AUTO_PAUSE) ||
202eef4f27bSRobert Mustacchi ((flow_ctrl & LM_FLOW_CONTROL_RECEIVE_PAUSE) &&
203eef4f27bSRobert Mustacchi (flow_ctrl & LM_FLOW_CONTROL_TRANSMIT_PAUSE)))
204eef4f27bSRobert Mustacchi {
205eef4f27bSRobert Mustacchi if(GET_MEDIUM_TYPE(req_medium) == LM_MEDIUM_TYPE_FIBER)
206eef4f27bSRobert Mustacchi {
207eef4f27bSRobert Mustacchi if(CHIP_NUM(pdev) == CHIP_NUM_5706)
208eef4f27bSRobert Mustacchi {
209eef4f27bSRobert Mustacchi val |= PHY_AN_AD_1000X_PAUSE_CAPABLE |
210eef4f27bSRobert Mustacchi PHY_AN_AD_1000X_ASYM_PAUSE;
211eef4f27bSRobert Mustacchi }
212eef4f27bSRobert Mustacchi else
213eef4f27bSRobert Mustacchi {
214eef4f27bSRobert Mustacchi val |= MII_ADVERT_PAUSE;
215eef4f27bSRobert Mustacchi }
216eef4f27bSRobert Mustacchi }
217eef4f27bSRobert Mustacchi else
218eef4f27bSRobert Mustacchi {
219eef4f27bSRobert Mustacchi val |= PHY_AN_AD_PAUSE_CAPABLE | PHY_AN_AD_ASYM_PAUSE;
220eef4f27bSRobert Mustacchi }
221eef4f27bSRobert Mustacchi }
222eef4f27bSRobert Mustacchi else if(flow_ctrl & LM_FLOW_CONTROL_TRANSMIT_PAUSE)
223eef4f27bSRobert Mustacchi {
224eef4f27bSRobert Mustacchi if(GET_MEDIUM_TYPE(req_medium) == LM_MEDIUM_TYPE_FIBER)
225eef4f27bSRobert Mustacchi {
226eef4f27bSRobert Mustacchi if(CHIP_NUM(pdev) == CHIP_NUM_5706)
227eef4f27bSRobert Mustacchi {
228eef4f27bSRobert Mustacchi val |= PHY_AN_AD_1000X_ASYM_PAUSE;
229eef4f27bSRobert Mustacchi }
230eef4f27bSRobert Mustacchi else
231eef4f27bSRobert Mustacchi {
232eef4f27bSRobert Mustacchi val |= MII_ADVERT_ASYM_PAUSE;
233eef4f27bSRobert Mustacchi }
234eef4f27bSRobert Mustacchi }
235eef4f27bSRobert Mustacchi else
236eef4f27bSRobert Mustacchi {
237eef4f27bSRobert Mustacchi val |= PHY_AN_AD_ASYM_PAUSE;
238eef4f27bSRobert Mustacchi }
239eef4f27bSRobert Mustacchi }
240eef4f27bSRobert Mustacchi else if(flow_ctrl & LM_FLOW_CONTROL_RECEIVE_PAUSE)
241eef4f27bSRobert Mustacchi {
242eef4f27bSRobert Mustacchi if(GET_MEDIUM_TYPE(req_medium) == LM_MEDIUM_TYPE_FIBER)
243eef4f27bSRobert Mustacchi {
244eef4f27bSRobert Mustacchi if(CHIP_NUM(pdev) == CHIP_NUM_5706)
245eef4f27bSRobert Mustacchi {
246eef4f27bSRobert Mustacchi val |= PHY_AN_AD_1000X_PAUSE_CAPABLE |
247eef4f27bSRobert Mustacchi PHY_AN_AD_1000X_ASYM_PAUSE;
248eef4f27bSRobert Mustacchi }
249eef4f27bSRobert Mustacchi else
250eef4f27bSRobert Mustacchi {
251eef4f27bSRobert Mustacchi val |= MII_ADVERT_PAUSE;
252eef4f27bSRobert Mustacchi }
253eef4f27bSRobert Mustacchi }
254eef4f27bSRobert Mustacchi else
255eef4f27bSRobert Mustacchi {
256eef4f27bSRobert Mustacchi val |= PHY_AN_AD_PAUSE_CAPABLE | PHY_AN_AD_ASYM_PAUSE;
257eef4f27bSRobert Mustacchi }
258eef4f27bSRobert Mustacchi }
259eef4f27bSRobert Mustacchi
260eef4f27bSRobert Mustacchi return val;
261eef4f27bSRobert Mustacchi } /* phy_ad_settings */
262eef4f27bSRobert Mustacchi
263eef4f27bSRobert Mustacchi
264eef4f27bSRobert Mustacchi
265eef4f27bSRobert Mustacchi /*******************************************************************************
266eef4f27bSRobert Mustacchi * Description:
267eef4f27bSRobert Mustacchi *
268eef4f27bSRobert Mustacchi * Return:
269eef4f27bSRobert Mustacchi ******************************************************************************/
270eef4f27bSRobert Mustacchi STATIC lm_status_t
init_utp(lm_device_t * pdev,lm_medium_t req_medium,lm_flow_control_t flow_ctrl,u32_t selective_autoneg,u32_t wire_speed,u32_t wait_link_timeout_us)271eef4f27bSRobert Mustacchi init_utp(
272eef4f27bSRobert Mustacchi lm_device_t *pdev,
273eef4f27bSRobert Mustacchi lm_medium_t req_medium,
274eef4f27bSRobert Mustacchi lm_flow_control_t flow_ctrl,
275eef4f27bSRobert Mustacchi u32_t selective_autoneg,
276eef4f27bSRobert Mustacchi u32_t wire_speed,
277eef4f27bSRobert Mustacchi u32_t wait_link_timeout_us)
278eef4f27bSRobert Mustacchi {
279eef4f27bSRobert Mustacchi u32_t restart_autoneg;
280eef4f27bSRobert Mustacchi lm_status_t lm_status;
281eef4f27bSRobert Mustacchi lm_medium_t duplex;
282eef4f27bSRobert Mustacchi lm_medium_t speed;
283eef4f27bSRobert Mustacchi u32_t val;
284eef4f27bSRobert Mustacchi u32_t cnt;
285eef4f27bSRobert Mustacchi
286eef4f27bSRobert Mustacchi if(GET_MEDIUM_TYPE(req_medium) != LM_MEDIUM_TYPE_UTP)
287eef4f27bSRobert Mustacchi {
288eef4f27bSRobert Mustacchi return LM_STATUS_INVALID_PARAMETER;
289eef4f27bSRobert Mustacchi }
290eef4f27bSRobert Mustacchi
291eef4f27bSRobert Mustacchi speed = GET_MEDIUM_SPEED(req_medium);
292eef4f27bSRobert Mustacchi duplex = GET_MEDIUM_DUPLEX(req_medium);
293eef4f27bSRobert Mustacchi
294eef4f27bSRobert Mustacchi lm_status = LM_STATUS_SUCCESS;
295eef4f27bSRobert Mustacchi
296eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, PHY_CTRL_REG, PHY_CTRL_PHY_RESET);
297eef4f27bSRobert Mustacchi for(cnt = 0; cnt < 1000; cnt++)
298eef4f27bSRobert Mustacchi {
299eef4f27bSRobert Mustacchi mm_wait(pdev, 5);
300*55fea89dSDan Cross
301eef4f27bSRobert Mustacchi (void) lm_mread(pdev, pdev->params.phy_addr, PHY_CTRL_REG, &val);
302eef4f27bSRobert Mustacchi
303eef4f27bSRobert Mustacchi if(!(val & PHY_CTRL_PHY_RESET))
304eef4f27bSRobert Mustacchi {
305eef4f27bSRobert Mustacchi mm_wait(pdev, 5);
306eef4f27bSRobert Mustacchi
307eef4f27bSRobert Mustacchi break;
308eef4f27bSRobert Mustacchi }
309eef4f27bSRobert Mustacchi }
310eef4f27bSRobert Mustacchi
311eef4f27bSRobert Mustacchi DbgBreakIf(val & PHY_CTRL_PHY_RESET);
312eef4f27bSRobert Mustacchi
313eef4f27bSRobert Mustacchi /* Get the PHY id. */
314eef4f27bSRobert Mustacchi (void) lm_mread(pdev, pdev->params.phy_addr, PHY_ID1_REG, &val);
315eef4f27bSRobert Mustacchi pdev->hw_info.phy_id = val << 16;
316eef4f27bSRobert Mustacchi DbgMessage1(pdev, INFORM, "Phy Id1 0x%x\n", val);
317eef4f27bSRobert Mustacchi
318eef4f27bSRobert Mustacchi (void) lm_mread(pdev, pdev->params.phy_addr, PHY_ID2_REG, &val);
319eef4f27bSRobert Mustacchi pdev->hw_info.phy_id |= val & 0xffff;
320eef4f27bSRobert Mustacchi DbgMessage1(pdev, INFORM, "Phy Id2 0x%x\n", val);
321eef4f27bSRobert Mustacchi
322eef4f27bSRobert Mustacchi DbgBreakIf(
323eef4f27bSRobert Mustacchi (pdev->hw_info.phy_id & 0x0fffffff) == 0x0fffffff ||
324eef4f27bSRobert Mustacchi pdev->hw_info.phy_id == 0);
325eef4f27bSRobert Mustacchi
326eef4f27bSRobert Mustacchi if(CHIP_REV(pdev) == CHIP_REV_FPGA)
327eef4f27bSRobert Mustacchi {
328eef4f27bSRobert Mustacchi /* Configure how the MAC obtain link from the external PHY.
329eef4f27bSRobert Mustacchi * On the FPGA board, LED2 is used as a link signal into the
330eef4f27bSRobert Mustacchi * MAC. Configure LED2 to a link event on the AC101L PHY. */
331eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, 28, 0x3044);
332eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, 29, 0x0100);
333eef4f27bSRobert Mustacchi }
334eef4f27bSRobert Mustacchi else
335eef4f27bSRobert Mustacchi {
336eef4f27bSRobert Mustacchi if(CHIP_NUM(pdev) == CHIP_NUM_5706 || CHIP_NUM(pdev) == CHIP_NUM_5708)
337eef4f27bSRobert Mustacchi {
338eef4f27bSRobert Mustacchi /* Gen6 PHY core has a slight increase in CRC error.
339eef4f27bSRobert Mustacchi * This will workaround the problem which will be
340eef4f27bSRobert Mustacchi * fixed in Gen7 PHY core. */
341eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x18, 0x0c00);
342eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x17, 0x000a);
343eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x15, 0x310b);
344eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x17, 0x201f);
345eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x15, 0x9506);
346eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x17, 0x401f);
347eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x15, 0x14e2);
348eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x18, 0x0400);
349eef4f27bSRobert Mustacchi }
350eef4f27bSRobert Mustacchi
351eef4f27bSRobert Mustacchi /* Enable/Disable Ethernet@WireSpeed. */
352eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x18, 0x7007);
353eef4f27bSRobert Mustacchi (void) lm_mread(pdev, pdev->params.phy_addr, 0x18, &val);
354*55fea89dSDan Cross
355eef4f27bSRobert Mustacchi val &= 0x0ff8;
356eef4f27bSRobert Mustacchi
357eef4f27bSRobert Mustacchi if(wire_speed)
358eef4f27bSRobert Mustacchi {
359eef4f27bSRobert Mustacchi val |= 0x10;
360eef4f27bSRobert Mustacchi }
361eef4f27bSRobert Mustacchi else
362eef4f27bSRobert Mustacchi {
363eef4f27bSRobert Mustacchi val &= ~0x10;
364eef4f27bSRobert Mustacchi }
365eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x18, val | 0x8000 | 0x7);
366eef4f27bSRobert Mustacchi
367eef4f27bSRobert Mustacchi /*
368*55fea89dSDan Cross * Cont00039501 Issue Description: Auto MDIX mode doesn't work in forced speed
369eef4f27bSRobert Mustacchi * while two 5716 connected back-to-back
370eef4f27bSRobert Mustacchi */
371eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x18, 0x7007);
372eef4f27bSRobert Mustacchi (void) lm_mread(pdev, pdev->params.phy_addr, 0x18, &val);
373eef4f27bSRobert Mustacchi val |= BIT_9; /*auto mdix*/
374eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, BCM5401_AUX_CTRL, val | 0x8000 | 0x7);
375*55fea89dSDan Cross
376eef4f27bSRobert Mustacchi }
377eef4f27bSRobert Mustacchi
378eef4f27bSRobert Mustacchi /* Expansion register 0x8 is the 10BT control register. BIT 8 of this
379eef4f27bSRobert Mustacchi * register controls the Early DAC Wakeup Enable. this bit allows the
380eef4f27bSRobert Mustacchi * transmitter to be shutdown in 10BT mode except for sending out link
381eef4f27bSRobert Mustacchi * pulses. This allows for a low power operation in 10BT mode which is
382eef4f27bSRobert Mustacchi * useful in WOL application. The default value of this register bit
383eef4f27bSRobert Mustacchi * gets loaded from a strap value on the GPHY provided by the chip that
384eef4f27bSRobert Mustacchi * instantiates the PHY. in Xinan this strap value is 1, meaning that
385eef4f27bSRobert Mustacchi * the early DAC Wakeup Enable bit is set by default. FW/Driver needs to
386eef4f27bSRobert Mustacchi * clear this bit when bringing the PHY out of reset. */
387eef4f27bSRobert Mustacchi if(CHIP_ID(pdev) == CHIP_ID_5709_A0 ||
388eef4f27bSRobert Mustacchi CHIP_ID(pdev) == CHIP_ID_5709_A1 ||
389eef4f27bSRobert Mustacchi CHIP_ID(pdev) == CHIP_ID_5709_B0 ||
390eef4f27bSRobert Mustacchi CHIP_ID(pdev) == CHIP_ID_5709_B1)
391eef4f27bSRobert Mustacchi {
392eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x17, 0xf08);
393eef4f27bSRobert Mustacchi (void) lm_mread(pdev, pdev->params.phy_addr, 0x15, &val);
394eef4f27bSRobert Mustacchi val &= ~0x100;
395eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x15, val);
396eef4f27bSRobert Mustacchi }
397eef4f27bSRobert Mustacchi
398eef4f27bSRobert Mustacchi /* Configure the PHY for jumbo frame. */
399eef4f27bSRobert Mustacchi if(pdev->params.mtu > MAX_ETHERNET_PACKET_SIZE)
400eef4f27bSRobert Mustacchi {
401eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x10, 0x0001);
402eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x18, 0x4400);
403eef4f27bSRobert Mustacchi }
404eef4f27bSRobert Mustacchi else
405eef4f27bSRobert Mustacchi {
406eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x10, 0x0000);
407eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x18, 0x0400);
408eef4f27bSRobert Mustacchi }
409eef4f27bSRobert Mustacchi
410eef4f27bSRobert Mustacchi /* Configure line speed. */
411eef4f27bSRobert Mustacchi restart_autoneg = FALSE;
412eef4f27bSRobert Mustacchi
413eef4f27bSRobert Mustacchi switch(speed)
414eef4f27bSRobert Mustacchi {
415eef4f27bSRobert Mustacchi case LM_MEDIUM_SPEED_10MBPS:
416eef4f27bSRobert Mustacchi /* Don't advertise 1000mb. This register is undefined on a
417eef4f27bSRobert Mustacchi * 10/100 Mb PHY. */
418*55fea89dSDan Cross (void) lm_mwrite(pdev, pdev->params.phy_addr, PHY_1000BASET_CTRL_REG, 0);
419eef4f27bSRobert Mustacchi
420eef4f27bSRobert Mustacchi /* Setup AN_AD to advertise 10mb. */
421eef4f27bSRobert Mustacchi val = PHY_AN_AD_PROTOCOL_802_3_CSMA_CD;
422eef4f27bSRobert Mustacchi val |= phy_ad_settings(pdev, req_medium, flow_ctrl);
423eef4f27bSRobert Mustacchi
424eef4f27bSRobert Mustacchi if(duplex == LM_MEDIUM_FULL_DUPLEX)
425eef4f27bSRobert Mustacchi {
426eef4f27bSRobert Mustacchi val |= PHY_AN_AD_10BASET_FULL;
427eef4f27bSRobert Mustacchi
428eef4f27bSRobert Mustacchi if(selective_autoneg == SELECTIVE_AUTONEG_ENABLE_SLOWER_SPEEDS)
429eef4f27bSRobert Mustacchi {
430eef4f27bSRobert Mustacchi val |= PHY_AN_AD_10BASET_HALF;
431eef4f27bSRobert Mustacchi }
432eef4f27bSRobert Mustacchi }
433eef4f27bSRobert Mustacchi else
434eef4f27bSRobert Mustacchi {
435eef4f27bSRobert Mustacchi val |= PHY_AN_AD_10BASET_HALF;
436eef4f27bSRobert Mustacchi }
437eef4f27bSRobert Mustacchi
438eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, PHY_AN_AD_REG, val);
439eef4f27bSRobert Mustacchi
440eef4f27bSRobert Mustacchi /* Forcing or advertising 10mb. */
441eef4f27bSRobert Mustacchi if(selective_autoneg)
442eef4f27bSRobert Mustacchi {
443eef4f27bSRobert Mustacchi restart_autoneg = TRUE;
444eef4f27bSRobert Mustacchi
445eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, "autoneg 10mb hd\n");
446eef4f27bSRobert Mustacchi if(duplex == LM_MEDIUM_FULL_DUPLEX)
447eef4f27bSRobert Mustacchi {
448eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, "and 10mb fd\n");
449eef4f27bSRobert Mustacchi }
450eef4f27bSRobert Mustacchi }
451eef4f27bSRobert Mustacchi else
452eef4f27bSRobert Mustacchi {
453eef4f27bSRobert Mustacchi if(duplex == LM_MEDIUM_HALF_DUPLEX)
454eef4f27bSRobert Mustacchi {
455eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, "force 10mb hd\n");
456eef4f27bSRobert Mustacchi (void) lm_mwrite(
457*55fea89dSDan Cross pdev,
458eef4f27bSRobert Mustacchi pdev->params.phy_addr,
459*55fea89dSDan Cross PHY_CTRL_REG,
460eef4f27bSRobert Mustacchi PHY_CTRL_SPEED_SELECT_10MBPS);
461eef4f27bSRobert Mustacchi }
462eef4f27bSRobert Mustacchi else
463eef4f27bSRobert Mustacchi {
464eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, "force 10mb fd\n");
465eef4f27bSRobert Mustacchi (void) lm_mwrite(
466*55fea89dSDan Cross pdev,
467eef4f27bSRobert Mustacchi pdev->params.phy_addr,
468*55fea89dSDan Cross PHY_CTRL_REG,
469eef4f27bSRobert Mustacchi PHY_CTRL_SPEED_SELECT_10MBPS |
470eef4f27bSRobert Mustacchi PHY_CTRL_FULL_DUPLEX_MODE);
471eef4f27bSRobert Mustacchi }
472eef4f27bSRobert Mustacchi }
473eef4f27bSRobert Mustacchi
474eef4f27bSRobert Mustacchi break;
475eef4f27bSRobert Mustacchi
476eef4f27bSRobert Mustacchi case LM_MEDIUM_SPEED_100MBPS:
477eef4f27bSRobert Mustacchi /* Don't advertise 1000mb. This register is undefined on a
478eef4f27bSRobert Mustacchi * 10/100 PHY. */
479*55fea89dSDan Cross (void) lm_mwrite(pdev, pdev->params.phy_addr, PHY_1000BASET_CTRL_REG, 0);
480eef4f27bSRobert Mustacchi
481eef4f27bSRobert Mustacchi /* Setup AN_AD to advertise 10/100mb. */
482eef4f27bSRobert Mustacchi val = PHY_AN_AD_PROTOCOL_802_3_CSMA_CD;
483eef4f27bSRobert Mustacchi val |= phy_ad_settings(pdev, req_medium, flow_ctrl);
484eef4f27bSRobert Mustacchi
485eef4f27bSRobert Mustacchi if(selective_autoneg == SELECTIVE_AUTONEG_ENABLE_SLOWER_SPEEDS)
486eef4f27bSRobert Mustacchi {
487eef4f27bSRobert Mustacchi val |= PHY_AN_AD_10BASET_HALF | PHY_AN_AD_10BASET_FULL;
488eef4f27bSRobert Mustacchi }
489eef4f27bSRobert Mustacchi
490eef4f27bSRobert Mustacchi if(duplex == LM_MEDIUM_FULL_DUPLEX)
491eef4f27bSRobert Mustacchi {
492eef4f27bSRobert Mustacchi val |= PHY_AN_AD_100BASETX_FULL;
493eef4f27bSRobert Mustacchi
494eef4f27bSRobert Mustacchi if(selective_autoneg == SELECTIVE_AUTONEG_ENABLE_SLOWER_SPEEDS)
495eef4f27bSRobert Mustacchi {
496eef4f27bSRobert Mustacchi val |= PHY_AN_AD_100BASETX_HALF;
497eef4f27bSRobert Mustacchi }
498eef4f27bSRobert Mustacchi }
499eef4f27bSRobert Mustacchi else
500eef4f27bSRobert Mustacchi {
501eef4f27bSRobert Mustacchi val |= PHY_AN_AD_100BASETX_HALF;
502eef4f27bSRobert Mustacchi }
503eef4f27bSRobert Mustacchi
504eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, PHY_AN_AD_REG, val);
505eef4f27bSRobert Mustacchi
506eef4f27bSRobert Mustacchi /* Forcing or advertising 100mb. */
507eef4f27bSRobert Mustacchi if(selective_autoneg)
508eef4f27bSRobert Mustacchi {
509eef4f27bSRobert Mustacchi restart_autoneg = TRUE;
510eef4f27bSRobert Mustacchi
511eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, "autoneg 10mb and 100mb hd\n");
512eef4f27bSRobert Mustacchi if(duplex == LM_MEDIUM_FULL_DUPLEX)
513eef4f27bSRobert Mustacchi {
514eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, "and 100mb fd\n");
515eef4f27bSRobert Mustacchi }
516eef4f27bSRobert Mustacchi }
517eef4f27bSRobert Mustacchi else
518eef4f27bSRobert Mustacchi {
519eef4f27bSRobert Mustacchi if(duplex == LM_MEDIUM_HALF_DUPLEX)
520eef4f27bSRobert Mustacchi {
521eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, "force 100mb hd\n");
522eef4f27bSRobert Mustacchi (void) lm_mwrite(
523*55fea89dSDan Cross pdev,
524eef4f27bSRobert Mustacchi pdev->params.phy_addr,
525eef4f27bSRobert Mustacchi PHY_CTRL_REG,
526eef4f27bSRobert Mustacchi PHY_CTRL_SPEED_SELECT_100MBPS);
527eef4f27bSRobert Mustacchi }
528eef4f27bSRobert Mustacchi else
529eef4f27bSRobert Mustacchi {
530eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, "force 100mb fd\n");
531eef4f27bSRobert Mustacchi (void) lm_mwrite(
532*55fea89dSDan Cross pdev,
533eef4f27bSRobert Mustacchi pdev->params.phy_addr,
534eef4f27bSRobert Mustacchi PHY_CTRL_REG,
535eef4f27bSRobert Mustacchi PHY_CTRL_SPEED_SELECT_100MBPS |
536eef4f27bSRobert Mustacchi PHY_CTRL_FULL_DUPLEX_MODE);
537eef4f27bSRobert Mustacchi }
538eef4f27bSRobert Mustacchi }
539eef4f27bSRobert Mustacchi
540eef4f27bSRobert Mustacchi break;
541eef4f27bSRobert Mustacchi
542eef4f27bSRobert Mustacchi case LM_MEDIUM_SPEED_1000MBPS:
543eef4f27bSRobert Mustacchi /* Don't advertise 10/100mb. */
544eef4f27bSRobert Mustacchi val = PHY_AN_AD_PROTOCOL_802_3_CSMA_CD;
545eef4f27bSRobert Mustacchi val |= phy_ad_settings(pdev, req_medium, flow_ctrl);
546eef4f27bSRobert Mustacchi
547eef4f27bSRobert Mustacchi if(selective_autoneg == SELECTIVE_AUTONEG_ENABLE_SLOWER_SPEEDS)
548eef4f27bSRobert Mustacchi {
549eef4f27bSRobert Mustacchi val |= PHY_AN_AD_10BASET_HALF | PHY_AN_AD_10BASET_FULL;
550eef4f27bSRobert Mustacchi val |= PHY_AN_AD_100BASETX_HALF | PHY_AN_AD_100BASETX_FULL;
551eef4f27bSRobert Mustacchi }
552eef4f27bSRobert Mustacchi
553eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, PHY_AN_AD_REG, val);
554eef4f27bSRobert Mustacchi
555eef4f27bSRobert Mustacchi /* Setup AN_AD to advertise 1000mb. This register is defined on
556eef4f27bSRobert Mustacchi * a 10/100 Mb PHY. */
557eef4f27bSRobert Mustacchi if(duplex == LM_MEDIUM_FULL_DUPLEX)
558eef4f27bSRobert Mustacchi {
559eef4f27bSRobert Mustacchi val |= PHY_AN_AD_1000BASET_FULL;
560eef4f27bSRobert Mustacchi
561eef4f27bSRobert Mustacchi if(selective_autoneg == SELECTIVE_AUTONEG_ENABLE_SLOWER_SPEEDS)
562eef4f27bSRobert Mustacchi {
563eef4f27bSRobert Mustacchi val |= PHY_AN_AD_1000BASET_HALF;
564eef4f27bSRobert Mustacchi }
565eef4f27bSRobert Mustacchi }
566eef4f27bSRobert Mustacchi else
567eef4f27bSRobert Mustacchi {
568eef4f27bSRobert Mustacchi val |= PHY_AN_AD_1000BASET_HALF;
569eef4f27bSRobert Mustacchi }
570eef4f27bSRobert Mustacchi
571eef4f27bSRobert Mustacchi /* Forcing or advertising 1000mb. */
572eef4f27bSRobert Mustacchi if(selective_autoneg)
573eef4f27bSRobert Mustacchi {
574eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, "autoneg 10/100mb and 1000mb hd\n");
575eef4f27bSRobert Mustacchi if(duplex == LM_MEDIUM_FULL_DUPLEX)
576eef4f27bSRobert Mustacchi {
577eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, "and 1000mb fd\n");
578eef4f27bSRobert Mustacchi }
579eef4f27bSRobert Mustacchi
580eef4f27bSRobert Mustacchi restart_autoneg = TRUE;
581eef4f27bSRobert Mustacchi }
582eef4f27bSRobert Mustacchi else
583eef4f27bSRobert Mustacchi {
584eef4f27bSRobert Mustacchi /* external loopback at 1gb link. */
585eef4f27bSRobert Mustacchi (void) lm_mwrite(
586*55fea89dSDan Cross pdev,
587*55fea89dSDan Cross pdev->params.phy_addr,
588*55fea89dSDan Cross PHY_CTRL_REG,
589eef4f27bSRobert Mustacchi PHY_CTRL_SPEED_SELECT_1000MBPS);
590eef4f27bSRobert Mustacchi
591eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, BCM5401_AUX_CTRL, 0x7);
592eef4f27bSRobert Mustacchi (void) lm_mread(pdev, pdev->params.phy_addr, BCM5401_AUX_CTRL, &val);
593eef4f27bSRobert Mustacchi val |= BCM5401_SHDW_NORMAL_EXTERNAL_LOOPBACK;
594eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, BCM5401_AUX_CTRL, val);
595eef4f27bSRobert Mustacchi
596eef4f27bSRobert Mustacchi val = PHY_CONFIG_AS_MASTER | PHY_ENABLE_CONFIG_AS_MASTER;
597eef4f27bSRobert Mustacchi }
598eef4f27bSRobert Mustacchi
599eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, PHY_1000BASET_CTRL_REG, val);
600eef4f27bSRobert Mustacchi break;
601eef4f27bSRobert Mustacchi
602eef4f27bSRobert Mustacchi default:
603eef4f27bSRobert Mustacchi val = PHY_AN_AD_PROTOCOL_802_3_CSMA_CD |
604eef4f27bSRobert Mustacchi PHY_AN_AD_10BASET_HALF |
605eef4f27bSRobert Mustacchi PHY_AN_AD_10BASET_FULL |
606eef4f27bSRobert Mustacchi PHY_AN_AD_100BASETX_FULL |
607eef4f27bSRobert Mustacchi PHY_AN_AD_100BASETX_HALF;
608eef4f27bSRobert Mustacchi val |= phy_ad_settings(pdev, req_medium, flow_ctrl);
609eef4f27bSRobert Mustacchi
610eef4f27bSRobert Mustacchi /* Set up the 10/100 advertisement register. */
611eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, PHY_AN_AD_REG, val);
612eef4f27bSRobert Mustacchi
613eef4f27bSRobert Mustacchi /* Advertise 1000Mbps. This register is undefined on a
614eef4f27bSRobert Mustacchi * 10/100 Mb PHY. */
615eef4f27bSRobert Mustacchi (void) lm_mwrite(
616*55fea89dSDan Cross pdev,
617eef4f27bSRobert Mustacchi pdev->params.phy_addr,
618eef4f27bSRobert Mustacchi PHY_1000BASET_CTRL_REG,
619eef4f27bSRobert Mustacchi PHY_AN_AD_1000BASET_HALF |
620eef4f27bSRobert Mustacchi PHY_AN_AD_1000BASET_FULL);
621eef4f27bSRobert Mustacchi
622eef4f27bSRobert Mustacchi restart_autoneg = TRUE;
623eef4f27bSRobert Mustacchi speed = LM_MEDIUM_SPEED_AUTONEG;
624eef4f27bSRobert Mustacchi break;
625eef4f27bSRobert Mustacchi }
626eef4f27bSRobert Mustacchi
627eef4f27bSRobert Mustacchi /* exit mac loopback. we could be in mac loopback mode if previously
628eef4f27bSRobert Mustacchi * the upper module calls lm_init_phy with LM_MEDIUM_TYPE_MAC_LOOPBACK
629eef4f27bSRobert Mustacchi * medium type for diagnostic. */
630eef4f27bSRobert Mustacchi REG_RD(pdev, emac.emac_mode, &val);
631eef4f27bSRobert Mustacchi val &= ~(EMAC_MODE_MAC_LOOP | EMAC_MODE_FORCE_LINK);
632eef4f27bSRobert Mustacchi REG_WR(pdev, emac.emac_mode, val);
633eef4f27bSRobert Mustacchi
634eef4f27bSRobert Mustacchi /* Restart auto-negotation. */
635eef4f27bSRobert Mustacchi if(restart_autoneg)
636eef4f27bSRobert Mustacchi {
637eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, "phy init - restart autoneg\n");
638eef4f27bSRobert Mustacchi
639eef4f27bSRobert Mustacchi (void) lm_mwrite(
640*55fea89dSDan Cross pdev,
641eef4f27bSRobert Mustacchi pdev->params.phy_addr,
642eef4f27bSRobert Mustacchi PHY_CTRL_REG,
643eef4f27bSRobert Mustacchi PHY_CTRL_AUTO_NEG_ENABLE | PHY_CTRL_RESTART_AUTO_NEG);
644eef4f27bSRobert Mustacchi }
645eef4f27bSRobert Mustacchi
646eef4f27bSRobert Mustacchi /* Save current medium settings. */
647eef4f27bSRobert Mustacchi SET_MEDIUM_TYPE(pdev->vars.medium, LM_MEDIUM_TYPE_UTP);
648eef4f27bSRobert Mustacchi SET_MEDIUM_SPEED(pdev->vars.medium, speed);
649eef4f27bSRobert Mustacchi SET_MEDIUM_DUPLEX(pdev->vars.medium, duplex);
650eef4f27bSRobert Mustacchi
651eef4f27bSRobert Mustacchi pdev->vars.cable_is_attached = FALSE;
652eef4f27bSRobert Mustacchi
653eef4f27bSRobert Mustacchi /* Wait for link. */
654eef4f27bSRobert Mustacchi (void) lm_mread(pdev, pdev->params.phy_addr, PHY_STATUS_REG, &val);
655eef4f27bSRobert Mustacchi
656eef4f27bSRobert Mustacchi if(CHIP_REV(pdev) != CHIP_REV_FPGA)
657eef4f27bSRobert Mustacchi {
658eef4f27bSRobert Mustacchi /* Wait for link only if the cable is connected. */
659eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1c, 0x7c00);
660eef4f27bSRobert Mustacchi (void) lm_mread(pdev, pdev->params.phy_addr, 0x1c, &val);
661eef4f27bSRobert Mustacchi if(val & 0x20)
662eef4f27bSRobert Mustacchi {
663eef4f27bSRobert Mustacchi for(; ;)
664eef4f27bSRobert Mustacchi {
665eef4f27bSRobert Mustacchi (void) lm_mread(pdev, pdev->params.phy_addr, PHY_STATUS_REG, &val);
666eef4f27bSRobert Mustacchi if(val & PHY_STATUS_LINK_PASS)
667eef4f27bSRobert Mustacchi {
668eef4f27bSRobert Mustacchi break;
669eef4f27bSRobert Mustacchi }
670eef4f27bSRobert Mustacchi
671eef4f27bSRobert Mustacchi mm_wait(pdev, 10);
672eef4f27bSRobert Mustacchi
673eef4f27bSRobert Mustacchi if(wait_link_timeout_us <= 10)
674eef4f27bSRobert Mustacchi {
675eef4f27bSRobert Mustacchi break;
676eef4f27bSRobert Mustacchi }
677eef4f27bSRobert Mustacchi
678eef4f27bSRobert Mustacchi wait_link_timeout_us -= 10;
679eef4f27bSRobert Mustacchi }
680eef4f27bSRobert Mustacchi
681eef4f27bSRobert Mustacchi pdev->vars.cable_is_attached = TRUE;
682eef4f27bSRobert Mustacchi }
683eef4f27bSRobert Mustacchi }
684eef4f27bSRobert Mustacchi
685eef4f27bSRobert Mustacchi /* Need to read a second time to get the current link status. */
686eef4f27bSRobert Mustacchi (void) lm_mread(pdev, pdev->params.phy_addr, PHY_STATUS_REG, &val);
687eef4f27bSRobert Mustacchi if(val & PHY_STATUS_LINK_PASS)
688eef4f27bSRobert Mustacchi {
689eef4f27bSRobert Mustacchi pdev->vars.link_status = LM_STATUS_LINK_ACTIVE;
690eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, "phy init link up\n");
691eef4f27bSRobert Mustacchi
692eef4f27bSRobert Mustacchi pdev->vars.cable_is_attached = TRUE;
693eef4f27bSRobert Mustacchi }
694eef4f27bSRobert Mustacchi else
695eef4f27bSRobert Mustacchi {
696eef4f27bSRobert Mustacchi pdev->vars.link_status = LM_STATUS_LINK_DOWN;
697eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, "phy init link down\n");
698eef4f27bSRobert Mustacchi }
699eef4f27bSRobert Mustacchi
700eef4f27bSRobert Mustacchi return lm_status;
701eef4f27bSRobert Mustacchi } /* init_utp */
702eef4f27bSRobert Mustacchi
703eef4f27bSRobert Mustacchi
704eef4f27bSRobert Mustacchi
705eef4f27bSRobert Mustacchi /*******************************************************************************
706eef4f27bSRobert Mustacchi * Description:
707eef4f27bSRobert Mustacchi *
708eef4f27bSRobert Mustacchi * Return:
709eef4f27bSRobert Mustacchi ******************************************************************************/
710eef4f27bSRobert Mustacchi STATIC u32_t
mii_get_serdes_link_status(lm_device_t * pdev)711eef4f27bSRobert Mustacchi mii_get_serdes_link_status(
712eef4f27bSRobert Mustacchi lm_device_t *pdev)
713eef4f27bSRobert Mustacchi {
714eef4f27bSRobert Mustacchi u32_t val;
715eef4f27bSRobert Mustacchi
716eef4f27bSRobert Mustacchi /* The link status in the MII status register is not reliable for
717eef4f27bSRobert Mustacchi * the SERDES part. We need to get the link info from the MAC. */
718eef4f27bSRobert Mustacchi if(CHIP_NUM(pdev) == CHIP_NUM_5706 &&
719eef4f27bSRobert Mustacchi lm_get_medium(pdev) == LM_MEDIUM_TYPE_FIBER)
720eef4f27bSRobert Mustacchi {
721eef4f27bSRobert Mustacchi REG_RD(pdev, emac.emac_status, &val);
722eef4f27bSRobert Mustacchi if(val & EMAC_STATUS_LINK)
723eef4f27bSRobert Mustacchi {
724eef4f27bSRobert Mustacchi val = PHY_STATUS_LINK_PASS;
725eef4f27bSRobert Mustacchi }
726eef4f27bSRobert Mustacchi else
727eef4f27bSRobert Mustacchi {
728eef4f27bSRobert Mustacchi val = 0;
729eef4f27bSRobert Mustacchi }
730eef4f27bSRobert Mustacchi }
731eef4f27bSRobert Mustacchi else
732eef4f27bSRobert Mustacchi {
733eef4f27bSRobert Mustacchi /* The second read returns the current status. */
734eef4f27bSRobert Mustacchi (void) lm_mread(pdev, pdev->params.phy_addr, PHY_STATUS_REG, &val);
735eef4f27bSRobert Mustacchi (void) lm_mread(pdev, pdev->params.phy_addr, PHY_STATUS_REG, &val);
736eef4f27bSRobert Mustacchi }
737eef4f27bSRobert Mustacchi
738eef4f27bSRobert Mustacchi return val;
739eef4f27bSRobert Mustacchi } /* mii_get_serdes_link_status */
740eef4f27bSRobert Mustacchi
741eef4f27bSRobert Mustacchi
742eef4f27bSRobert Mustacchi
743eef4f27bSRobert Mustacchi /*******************************************************************************
744eef4f27bSRobert Mustacchi * Description:
745eef4f27bSRobert Mustacchi *
746eef4f27bSRobert Mustacchi * Return:
747eef4f27bSRobert Mustacchi ******************************************************************************/
748eef4f27bSRobert Mustacchi STATIC u8_t
set_5708_serdes_pre_emphasis(lm_device_t * pdev,u32_t pre_emphasis)749eef4f27bSRobert Mustacchi set_5708_serdes_pre_emphasis(
750eef4f27bSRobert Mustacchi lm_device_t *pdev,
751eef4f27bSRobert Mustacchi u32_t pre_emphasis)
752eef4f27bSRobert Mustacchi {
753eef4f27bSRobert Mustacchi u8_t restart_autoneg;
754eef4f27bSRobert Mustacchi u32_t val;
755eef4f27bSRobert Mustacchi
756eef4f27bSRobert Mustacchi restart_autoneg = FALSE;
757eef4f27bSRobert Mustacchi
758eef4f27bSRobert Mustacchi if(pre_emphasis == 0)
759eef4f27bSRobert Mustacchi {
760eef4f27bSRobert Mustacchi (void) lm_mread(
761*55fea89dSDan Cross pdev,
762eef4f27bSRobert Mustacchi pdev->params.phy_addr,
763eef4f27bSRobert Mustacchi MII_REG(serdes_reg_t, mii_aneg_nxt_pg_rcv2),
764eef4f27bSRobert Mustacchi &pre_emphasis);
765eef4f27bSRobert Mustacchi pre_emphasis &= 0xf;
766eef4f27bSRobert Mustacchi
767eef4f27bSRobert Mustacchi if(pre_emphasis != pdev->vars.serdes_pre_emphasis)
768eef4f27bSRobert Mustacchi {
769eef4f27bSRobert Mustacchi pdev->vars.serdes_pre_emphasis = pre_emphasis;
770eef4f27bSRobert Mustacchi
771eef4f27bSRobert Mustacchi restart_autoneg = TRUE;
772eef4f27bSRobert Mustacchi
773eef4f27bSRobert Mustacchi /* Switch to Bank 5. */
774eef4f27bSRobert Mustacchi (void) lm_mwrite(
775*55fea89dSDan Cross pdev,
776eef4f27bSRobert Mustacchi pdev->params.phy_addr,
777eef4f27bSRobert Mustacchi MII_REG(serdes_reg_t, mii_block_addr),
778eef4f27bSRobert Mustacchi MII_BLK_ADDR_TXMISC);
779eef4f27bSRobert Mustacchi
780eef4f27bSRobert Mustacchi /* Write the new pre-emphasis. */
781eef4f27bSRobert Mustacchi (void) lm_mread(
782*55fea89dSDan Cross pdev,
783eef4f27bSRobert Mustacchi pdev->params.phy_addr,
784eef4f27bSRobert Mustacchi 0x10+MII_REG(serdes_tx_misc_reg_t, mii_txactl3),
785eef4f27bSRobert Mustacchi &val);
786eef4f27bSRobert Mustacchi
787eef4f27bSRobert Mustacchi pre_emphasis =
788eef4f27bSRobert Mustacchi ((pre_emphasis & 0x1) << 15) |
789eef4f27bSRobert Mustacchi ((pre_emphasis & 0x2) << 13) |
790eef4f27bSRobert Mustacchi ((pre_emphasis & 0x4) << 11) |
791eef4f27bSRobert Mustacchi ((pre_emphasis & 0x8) << 9);
792eef4f27bSRobert Mustacchi val = (val & 0x0fff) | pre_emphasis;
793eef4f27bSRobert Mustacchi
794eef4f27bSRobert Mustacchi (void) lm_mwrite(
795*55fea89dSDan Cross pdev,
796eef4f27bSRobert Mustacchi pdev->params.phy_addr,
797eef4f27bSRobert Mustacchi 0x10+MII_REG(serdes_tx_misc_reg_t, mii_txactl3),
798eef4f27bSRobert Mustacchi val);
799*55fea89dSDan Cross
800eef4f27bSRobert Mustacchi /* Select Bank 0. */
801eef4f27bSRobert Mustacchi (void) lm_mwrite(
802*55fea89dSDan Cross pdev,
803eef4f27bSRobert Mustacchi pdev->params.phy_addr,
804eef4f27bSRobert Mustacchi MII_REG(serdes_reg_t, mii_block_addr),
805eef4f27bSRobert Mustacchi MII_BLK_ADDR_DIGITAL);
806eef4f27bSRobert Mustacchi
807eef4f27bSRobert Mustacchi /* Restart autoneg. */
808eef4f27bSRobert Mustacchi (void) lm_mwrite(
809*55fea89dSDan Cross pdev,
810eef4f27bSRobert Mustacchi pdev->params.phy_addr,
811eef4f27bSRobert Mustacchi MII_REG(serdes_reg_t, mii_ctrl),
812eef4f27bSRobert Mustacchi MII_CTRL_RESTART_ANEG | MII_CTRL_ANEG_ENA);
813eef4f27bSRobert Mustacchi }
814eef4f27bSRobert Mustacchi }
815eef4f27bSRobert Mustacchi else
816eef4f27bSRobert Mustacchi {
817eef4f27bSRobert Mustacchi (void) lm_mwrite(
818*55fea89dSDan Cross pdev,
819eef4f27bSRobert Mustacchi pdev->params.phy_addr,
820eef4f27bSRobert Mustacchi MII_REG(serdes_reg_t, mii_block_addr),
821eef4f27bSRobert Mustacchi MII_BLK_ADDR_TXMISC);
822eef4f27bSRobert Mustacchi
823eef4f27bSRobert Mustacchi (void) lm_mwrite(
824*55fea89dSDan Cross pdev,
825eef4f27bSRobert Mustacchi pdev->params.phy_addr,
826eef4f27bSRobert Mustacchi 0x10+MII_REG(serdes_tx_misc_reg_t, mii_txactl3),
827eef4f27bSRobert Mustacchi pre_emphasis);
828*55fea89dSDan Cross
829eef4f27bSRobert Mustacchi (void) lm_mwrite(
830*55fea89dSDan Cross pdev,
831eef4f27bSRobert Mustacchi pdev->params.phy_addr,
832eef4f27bSRobert Mustacchi MII_REG(serdes_reg_t, mii_block_addr),
833eef4f27bSRobert Mustacchi MII_BLK_ADDR_DIGITAL);
834eef4f27bSRobert Mustacchi }
835eef4f27bSRobert Mustacchi
836eef4f27bSRobert Mustacchi return restart_autoneg;
837eef4f27bSRobert Mustacchi } /* set_5708_serdes_pre_emphasis */
838eef4f27bSRobert Mustacchi
839eef4f27bSRobert Mustacchi
840eef4f27bSRobert Mustacchi
841eef4f27bSRobert Mustacchi /*******************************************************************************
842eef4f27bSRobert Mustacchi * Description:
843eef4f27bSRobert Mustacchi *
844eef4f27bSRobert Mustacchi * Return:
845eef4f27bSRobert Mustacchi ******************************************************************************/
846eef4f27bSRobert Mustacchi STATIC lm_status_t
init_5708_serdes(lm_device_t * pdev,lm_medium_t req_medium,lm_flow_control_t flow_ctrl,u32_t selective_autoneg,u32_t wait_link_timeout_us)847eef4f27bSRobert Mustacchi init_5708_serdes(
848eef4f27bSRobert Mustacchi lm_device_t *pdev,
849eef4f27bSRobert Mustacchi lm_medium_t req_medium,
850eef4f27bSRobert Mustacchi lm_flow_control_t flow_ctrl,
851eef4f27bSRobert Mustacchi u32_t selective_autoneg,
852eef4f27bSRobert Mustacchi u32_t wait_link_timeout_us)
853eef4f27bSRobert Mustacchi {
854eef4f27bSRobert Mustacchi lm_medium_t duplex;
855eef4f27bSRobert Mustacchi lm_medium_t speed;
856eef4f27bSRobert Mustacchi u32_t cnt;
857eef4f27bSRobert Mustacchi u32_t val;
858eef4f27bSRobert Mustacchi
859eef4f27bSRobert Mustacchi if(GET_MEDIUM_SPEED(req_medium) == LM_MEDIUM_SPEED_UNKNOWN)
860eef4f27bSRobert Mustacchi {
861eef4f27bSRobert Mustacchi selective_autoneg = FALSE;
862eef4f27bSRobert Mustacchi }
863eef4f27bSRobert Mustacchi
864eef4f27bSRobert Mustacchi speed = GET_MEDIUM_SPEED(req_medium);
865eef4f27bSRobert Mustacchi duplex = GET_MEDIUM_DUPLEX(req_medium);
866eef4f27bSRobert Mustacchi
867eef4f27bSRobert Mustacchi if(speed == LM_MEDIUM_SPEED_HARDWARE_DEFAULT)
868eef4f27bSRobert Mustacchi {
869eef4f27bSRobert Mustacchi REG_RD_IND(
870eef4f27bSRobert Mustacchi pdev,
871eef4f27bSRobert Mustacchi pdev->hw_info.shmem_base +
872eef4f27bSRobert Mustacchi OFFSETOF(shmem_region_t, dev_info.port_hw_config.config),
873eef4f27bSRobert Mustacchi &val);
874eef4f27bSRobert Mustacchi
875eef4f27bSRobert Mustacchi switch(val & PORT_HW_CFG_DEFAULT_LINK_MASK)
876eef4f27bSRobert Mustacchi {
877eef4f27bSRobert Mustacchi case PORT_HW_CFG_DEFAULT_LINK_1G:
878eef4f27bSRobert Mustacchi speed = LM_MEDIUM_SPEED_1000MBPS;
879eef4f27bSRobert Mustacchi break;
880eef4f27bSRobert Mustacchi
881eef4f27bSRobert Mustacchi case PORT_HW_CFG_DEFAULT_LINK_2_5G:
882eef4f27bSRobert Mustacchi speed = LM_MEDIUM_SPEED_2500MBPS;
883eef4f27bSRobert Mustacchi break;
884eef4f27bSRobert Mustacchi
885eef4f27bSRobert Mustacchi default:
886eef4f27bSRobert Mustacchi speed = LM_MEDIUM_SPEED_UNKNOWN;
887eef4f27bSRobert Mustacchi break;
888eef4f27bSRobert Mustacchi }
889eef4f27bSRobert Mustacchi }
890eef4f27bSRobert Mustacchi
891eef4f27bSRobert Mustacchi /* Reset the SERDES. */
892eef4f27bSRobert Mustacchi (void) lm_mwrite(
893*55fea89dSDan Cross pdev,
894*55fea89dSDan Cross pdev->params.phy_addr,
895*55fea89dSDan Cross MII_REG(serdes_reg_t, mii_ctrl),
896eef4f27bSRobert Mustacchi MII_CTRL_RESET);
897eef4f27bSRobert Mustacchi
898eef4f27bSRobert Mustacchi for(cnt = 0; cnt < 1000; cnt++)
899eef4f27bSRobert Mustacchi {
900eef4f27bSRobert Mustacchi mm_wait(pdev, 5);
901*55fea89dSDan Cross
902eef4f27bSRobert Mustacchi (void) lm_mread(
903*55fea89dSDan Cross pdev,
904*55fea89dSDan Cross pdev->params.phy_addr,
905*55fea89dSDan Cross MII_REG(serdes_reg_t, mii_ctrl),
906eef4f27bSRobert Mustacchi &val);
907eef4f27bSRobert Mustacchi
908eef4f27bSRobert Mustacchi if(!(val & MII_CTRL_RESET))
909eef4f27bSRobert Mustacchi {
910eef4f27bSRobert Mustacchi mm_wait(pdev, 5);
911eef4f27bSRobert Mustacchi
912eef4f27bSRobert Mustacchi break;
913eef4f27bSRobert Mustacchi }
914eef4f27bSRobert Mustacchi }
915eef4f27bSRobert Mustacchi
916eef4f27bSRobert Mustacchi DbgBreakIf(val & MII_CTRL_RESET);
917eef4f27bSRobert Mustacchi
918eef4f27bSRobert Mustacchi /* Workaround for 5708A0 and B0.
919eef4f27bSRobert Mustacchi *
920eef4f27bSRobert Mustacchi * Errata 1.75: Tx peak-to-peak amplitude was measured as low
921eef4f27bSRobert Mustacchi * as 765mV under full PVT testing, whereas 800mV is considered
922eef4f27bSRobert Mustacchi * a passing result. */
923eef4f27bSRobert Mustacchi if(CHIP_NUM(pdev) == CHIP_NUM_5708)
924eef4f27bSRobert Mustacchi {
925eef4f27bSRobert Mustacchi /* Switch to Bank 5. */
926eef4f27bSRobert Mustacchi (void) lm_mwrite(
927*55fea89dSDan Cross pdev,
928eef4f27bSRobert Mustacchi pdev->params.phy_addr,
929eef4f27bSRobert Mustacchi MII_REG(serdes_reg_t, mii_block_addr),
930eef4f27bSRobert Mustacchi MII_BLK_ADDR_TXMISC);
931eef4f27bSRobert Mustacchi
932eef4f27bSRobert Mustacchi (void) lm_mread(
933*55fea89dSDan Cross pdev,
934eef4f27bSRobert Mustacchi pdev->params.phy_addr,
935eef4f27bSRobert Mustacchi 0x10+MII_REG(serdes_tx_misc_reg_t, mii_txactl1),
936eef4f27bSRobert Mustacchi &val);
937eef4f27bSRobert Mustacchi
938eef4f27bSRobert Mustacchi val &= ~ MII_TXACTL1_DRIVER_VCM;
939eef4f27bSRobert Mustacchi
940eef4f27bSRobert Mustacchi (void) lm_mwrite(
941*55fea89dSDan Cross pdev,
942eef4f27bSRobert Mustacchi pdev->params.phy_addr,
943eef4f27bSRobert Mustacchi 0x10+MII_REG(serdes_tx_misc_reg_t, mii_txactl1),
944eef4f27bSRobert Mustacchi val);
945eef4f27bSRobert Mustacchi }
946eef4f27bSRobert Mustacchi
947eef4f27bSRobert Mustacchi /* Set up pre-emphasis for a backplane application. */
948eef4f27bSRobert Mustacchi if(pdev->hw_info.nvm_hw_config & SHARED_HW_CFG_BACKPLANE_APP)
949eef4f27bSRobert Mustacchi {
950eef4f27bSRobert Mustacchi (void) set_5708_serdes_pre_emphasis(pdev, pdev->params.serdes_pre_emphasis);
951eef4f27bSRobert Mustacchi }
952eef4f27bSRobert Mustacchi
953eef4f27bSRobert Mustacchi /* Reset the pre_emphasis. */
954eef4f27bSRobert Mustacchi pdev->vars.serdes_pre_emphasis = 0;
955eef4f27bSRobert Mustacchi
956eef4f27bSRobert Mustacchi /* Get the PHY id. */
957eef4f27bSRobert Mustacchi (void) lm_mread(
958*55fea89dSDan Cross pdev,
959*55fea89dSDan Cross pdev->params.phy_addr,
960*55fea89dSDan Cross MII_REG(serdes_reg_t, mii_phy_id_msb),
961eef4f27bSRobert Mustacchi &val);
962eef4f27bSRobert Mustacchi pdev->hw_info.phy_id = val << 16;
963eef4f27bSRobert Mustacchi DbgMessage1(pdev, INFORM, "Phy Id1 0x%x\n", val);
964eef4f27bSRobert Mustacchi
965eef4f27bSRobert Mustacchi (void) lm_mread(
966*55fea89dSDan Cross pdev,
967*55fea89dSDan Cross pdev->params.phy_addr,
968*55fea89dSDan Cross MII_REG(serdes_reg_t, mii_phy_id_lsb),
969eef4f27bSRobert Mustacchi &val);
970eef4f27bSRobert Mustacchi pdev->hw_info.phy_id |= val & 0xffff;
971eef4f27bSRobert Mustacchi DbgMessage1(pdev, INFORM, "Phy Id2 0x%x\n", val);
972eef4f27bSRobert Mustacchi
973eef4f27bSRobert Mustacchi DbgBreakIf((pdev->hw_info.phy_id & 0x0fffffff) == 0x0fffffff ||
974eef4f27bSRobert Mustacchi pdev->hw_info.phy_id == 0);
975eef4f27bSRobert Mustacchi
976eef4f27bSRobert Mustacchi /* Enable 2.5G register set to be accessible in the IEEE registers. */
977eef4f27bSRobert Mustacchi (void) lm_mwrite(
978*55fea89dSDan Cross pdev,
979eef4f27bSRobert Mustacchi pdev->params.phy_addr,
980eef4f27bSRobert Mustacchi MII_REG(serdes_reg_t, mii_block_addr),
981eef4f27bSRobert Mustacchi MII_BLK_ADDR_DIGITAL3);
982eef4f27bSRobert Mustacchi (void) lm_mwrite(
983*55fea89dSDan Cross pdev,
984eef4f27bSRobert Mustacchi pdev->params.phy_addr,
985eef4f27bSRobert Mustacchi 0x10+MII_REG(serdes_digital3_reg_t, mii_digctl_3_0),
986eef4f27bSRobert Mustacchi MII_DIG3_USE_IEEE);
987eef4f27bSRobert Mustacchi
988eef4f27bSRobert Mustacchi /* Switch back to the IEEE Bank. */
989eef4f27bSRobert Mustacchi (void) lm_mwrite(
990*55fea89dSDan Cross pdev,
991eef4f27bSRobert Mustacchi pdev->params.phy_addr,
992eef4f27bSRobert Mustacchi MII_REG(serdes_reg_t, mii_block_addr),
993eef4f27bSRobert Mustacchi MII_BLK_ADDR_DIGITAL);
994eef4f27bSRobert Mustacchi
995eef4f27bSRobert Mustacchi /* Enable SGMII/Fiber mode autodetection. */
996eef4f27bSRobert Mustacchi (void) lm_mread(
997*55fea89dSDan Cross pdev,
998eef4f27bSRobert Mustacchi pdev->params.phy_addr,
999eef4f27bSRobert Mustacchi 0x10+MII_REG(serdes_digital_reg_t, mii_1000x_ctl1),
1000eef4f27bSRobert Mustacchi &val);
1001eef4f27bSRobert Mustacchi
1002eef4f27bSRobert Mustacchi val |= MII_1000X_CTL1_FIBER_MODE | MII_1000X_CTL1_AUTODET_EN;
1003eef4f27bSRobert Mustacchi
1004eef4f27bSRobert Mustacchi /* Sigdet is enabled by default. For backplane application, we need
1005eef4f27bSRobert Mustacchi * to disable Sigdet by clearing 0*0x10.2 of the Digital Bank. */
1006eef4f27bSRobert Mustacchi if(pdev->hw_info.nvm_hw_config & SHARED_HW_CFG_BACKPLANE_APP)
1007eef4f27bSRobert Mustacchi {
1008eef4f27bSRobert Mustacchi val &= ~MII_1000X_CTL1_SIG_DET_EN;
1009eef4f27bSRobert Mustacchi }
1010eef4f27bSRobert Mustacchi else
1011eef4f27bSRobert Mustacchi {
1012eef4f27bSRobert Mustacchi val |= MII_1000X_CTL1_SIG_DET_EN;
1013eef4f27bSRobert Mustacchi }
1014eef4f27bSRobert Mustacchi
1015eef4f27bSRobert Mustacchi (void) lm_mwrite(
1016*55fea89dSDan Cross pdev,
1017eef4f27bSRobert Mustacchi pdev->params.phy_addr,
1018eef4f27bSRobert Mustacchi 0x10+MII_REG(serdes_digital_reg_t, mii_1000x_ctl1),
1019eef4f27bSRobert Mustacchi val);
1020eef4f27bSRobert Mustacchi
1021eef4f27bSRobert Mustacchi /* We should always enable parallel detection. */
1022eef4f27bSRobert Mustacchi (void) lm_mread(
1023*55fea89dSDan Cross pdev,
1024eef4f27bSRobert Mustacchi pdev->params.phy_addr,
1025eef4f27bSRobert Mustacchi 0x10+MII_REG(serdes_digital_reg_t, mii_1000x_ctl2),
1026eef4f27bSRobert Mustacchi &val);
1027eef4f27bSRobert Mustacchi
1028eef4f27bSRobert Mustacchi val |= MII_1000X_CTL2_PAR_DET_EN;
1029eef4f27bSRobert Mustacchi
1030eef4f27bSRobert Mustacchi (void) lm_mwrite(
1031*55fea89dSDan Cross pdev,
1032eef4f27bSRobert Mustacchi pdev->params.phy_addr,
1033eef4f27bSRobert Mustacchi 0x10+MII_REG(serdes_digital_reg_t, mii_1000x_ctl2),
1034eef4f27bSRobert Mustacchi val);
1035eef4f27bSRobert Mustacchi
1036eef4f27bSRobert Mustacchi /* Enable/disable 2.5G capability. */
1037eef4f27bSRobert Mustacchi (void) lm_mread(
1038*55fea89dSDan Cross pdev,
1039eef4f27bSRobert Mustacchi pdev->params.phy_addr,
1040eef4f27bSRobert Mustacchi MII_REG(serdes_reg_t, mii_aneg_nxt_pg_xmit1),
1041eef4f27bSRobert Mustacchi &val);
1042eef4f27bSRobert Mustacchi
1043eef4f27bSRobert Mustacchi val &= ~MII_ANEG_NXT_PG_XMIT1_2G5;
1044eef4f27bSRobert Mustacchi
1045eef4f27bSRobert Mustacchi if(selective_autoneg)
1046eef4f27bSRobert Mustacchi {
1047eef4f27bSRobert Mustacchi if(speed == LM_MEDIUM_SPEED_2500MBPS)
1048eef4f27bSRobert Mustacchi {
1049eef4f27bSRobert Mustacchi val |= MII_ANEG_NXT_PG_XMIT1_2G5;
1050eef4f27bSRobert Mustacchi }
1051eef4f27bSRobert Mustacchi }
1052eef4f27bSRobert Mustacchi else if(speed == LM_MEDIUM_SPEED_AUTONEG)
1053eef4f27bSRobert Mustacchi {
1054eef4f27bSRobert Mustacchi if(pdev->hw_info.nvm_hw_config & SHARED_HW_CFG_PHY_FIBER_2_5G)
1055eef4f27bSRobert Mustacchi {
1056eef4f27bSRobert Mustacchi val |= MII_ANEG_NXT_PG_XMIT1_2G5;
1057eef4f27bSRobert Mustacchi }
1058eef4f27bSRobert Mustacchi }
1059eef4f27bSRobert Mustacchi else if(speed == LM_MEDIUM_SPEED_2500MBPS)
1060eef4f27bSRobert Mustacchi {
1061eef4f27bSRobert Mustacchi val |= MII_ANEG_NXT_PG_XMIT1_2G5;
1062eef4f27bSRobert Mustacchi }
1063eef4f27bSRobert Mustacchi
1064eef4f27bSRobert Mustacchi (void) lm_mwrite(
1065*55fea89dSDan Cross pdev,
1066eef4f27bSRobert Mustacchi pdev->params.phy_addr,
1067eef4f27bSRobert Mustacchi MII_REG(serdes_reg_t, mii_aneg_nxt_pg_xmit1),
1068eef4f27bSRobert Mustacchi val);
1069eef4f27bSRobert Mustacchi
1070eef4f27bSRobert Mustacchi val = 0;
1071eef4f27bSRobert Mustacchi
1072eef4f27bSRobert Mustacchi if(selective_autoneg || speed == LM_MEDIUM_SPEED_UNKNOWN)
1073eef4f27bSRobert Mustacchi {
1074eef4f27bSRobert Mustacchi val |= phy_ad_settings(pdev, req_medium, flow_ctrl);
1075eef4f27bSRobert Mustacchi
1076eef4f27bSRobert Mustacchi if((selective_autoneg && speed == LM_MEDIUM_SPEED_1000MBPS) ||
1077eef4f27bSRobert Mustacchi speed == LM_MEDIUM_SPEED_UNKNOWN)
1078eef4f27bSRobert Mustacchi {
1079eef4f27bSRobert Mustacchi val |= MII_ABILITY_HALF | MII_ABILITY_FULL;
1080eef4f27bSRobert Mustacchi }
1081eef4f27bSRobert Mustacchi
1082eef4f27bSRobert Mustacchi (void) lm_mwrite(
1083*55fea89dSDan Cross pdev,
1084*55fea89dSDan Cross pdev->params.phy_addr,
1085*55fea89dSDan Cross MII_REG(serdes_reg_t, mii_aneg_advert),
1086eef4f27bSRobert Mustacchi val);
1087eef4f27bSRobert Mustacchi
1088eef4f27bSRobert Mustacchi (void) lm_mwrite(
1089*55fea89dSDan Cross pdev,
1090eef4f27bSRobert Mustacchi pdev->params.phy_addr,
1091eef4f27bSRobert Mustacchi MII_REG(serdes_reg_t, mii_ctrl),
1092eef4f27bSRobert Mustacchi MII_CTRL_RESTART_ANEG | MII_CTRL_ANEG_ENA);
1093eef4f27bSRobert Mustacchi
1094eef4f27bSRobert Mustacchi speed = LM_MEDIUM_SPEED_AUTONEG;
1095eef4f27bSRobert Mustacchi }
1096eef4f27bSRobert Mustacchi else
1097eef4f27bSRobert Mustacchi {
1098eef4f27bSRobert Mustacchi switch(speed)
1099eef4f27bSRobert Mustacchi {
1100eef4f27bSRobert Mustacchi case LM_MEDIUM_SPEED_10MBPS:
1101eef4f27bSRobert Mustacchi if(duplex == LM_MEDIUM_FULL_DUPLEX)
1102eef4f27bSRobert Mustacchi {
1103eef4f27bSRobert Mustacchi val |= MII_CTRL_DUPLEX_MODE;
1104eef4f27bSRobert Mustacchi }
1105eef4f27bSRobert Mustacchi
1106eef4f27bSRobert Mustacchi (void) lm_mwrite(
1107*55fea89dSDan Cross pdev,
1108*55fea89dSDan Cross pdev->params.phy_addr,
1109*55fea89dSDan Cross MII_REG(serdes_reg_t, mii_ctrl),
1110eef4f27bSRobert Mustacchi val);
1111eef4f27bSRobert Mustacchi /* Switch to SGMII mode and disable auto-detect */
1112eef4f27bSRobert Mustacchi (void) lm_mread(
1113*55fea89dSDan Cross pdev,
1114eef4f27bSRobert Mustacchi pdev->params.phy_addr,
1115eef4f27bSRobert Mustacchi 0x10+MII_REG(serdes_digital_reg_t, mii_1000x_ctl1),
1116eef4f27bSRobert Mustacchi &val);
1117eef4f27bSRobert Mustacchi (void) lm_mwrite(
1118*55fea89dSDan Cross pdev,
1119eef4f27bSRobert Mustacchi pdev->params.phy_addr,
1120eef4f27bSRobert Mustacchi 0x10+MII_REG(serdes_digital_reg_t, mii_1000x_ctl1),
1121eef4f27bSRobert Mustacchi val & ~(MII_1000X_CTL1_FIBER_MODE | MII_1000X_CTL1_AUTODET_EN));
1122eef4f27bSRobert Mustacchi break;
1123eef4f27bSRobert Mustacchi
1124eef4f27bSRobert Mustacchi case LM_MEDIUM_SPEED_100MBPS:
1125eef4f27bSRobert Mustacchi if(duplex == LM_MEDIUM_FULL_DUPLEX)
1126eef4f27bSRobert Mustacchi {
1127eef4f27bSRobert Mustacchi val |= MII_CTRL_DUPLEX_MODE;
1128eef4f27bSRobert Mustacchi }
1129eef4f27bSRobert Mustacchi
1130eef4f27bSRobert Mustacchi val |= MII_CTRL_MANUAL_SPD0;
1131eef4f27bSRobert Mustacchi
1132eef4f27bSRobert Mustacchi (void) lm_mwrite(
1133*55fea89dSDan Cross pdev,
1134*55fea89dSDan Cross pdev->params.phy_addr,
1135*55fea89dSDan Cross MII_REG(serdes_reg_t, mii_ctrl),
1136eef4f27bSRobert Mustacchi val);
1137eef4f27bSRobert Mustacchi /* Switch to SGMII mode and disable auto-detect */
1138eef4f27bSRobert Mustacchi (void) lm_mread(
1139*55fea89dSDan Cross pdev,
1140eef4f27bSRobert Mustacchi pdev->params.phy_addr,
1141eef4f27bSRobert Mustacchi 0x10+MII_REG(serdes_digital_reg_t, mii_1000x_ctl1),
1142eef4f27bSRobert Mustacchi &val);
1143eef4f27bSRobert Mustacchi (void) lm_mwrite(
1144*55fea89dSDan Cross pdev,
1145eef4f27bSRobert Mustacchi pdev->params.phy_addr,
1146eef4f27bSRobert Mustacchi 0x10+MII_REG(serdes_digital_reg_t, mii_1000x_ctl1),
1147eef4f27bSRobert Mustacchi val & ~(MII_1000X_CTL1_FIBER_MODE | MII_1000X_CTL1_AUTODET_EN));
1148eef4f27bSRobert Mustacchi break;
1149eef4f27bSRobert Mustacchi
1150eef4f27bSRobert Mustacchi case LM_MEDIUM_SPEED_1000MBPS:
1151eef4f27bSRobert Mustacchi if(duplex == LM_MEDIUM_FULL_DUPLEX)
1152eef4f27bSRobert Mustacchi {
1153eef4f27bSRobert Mustacchi val |= MII_CTRL_DUPLEX_MODE;
1154eef4f27bSRobert Mustacchi }
1155eef4f27bSRobert Mustacchi
1156eef4f27bSRobert Mustacchi val |= MII_CTRL_MANUAL_SPD1;
1157eef4f27bSRobert Mustacchi
1158eef4f27bSRobert Mustacchi (void) lm_mwrite(
1159*55fea89dSDan Cross pdev,
1160*55fea89dSDan Cross pdev->params.phy_addr,
1161*55fea89dSDan Cross MII_REG(serdes_reg_t, mii_ctrl),
1162eef4f27bSRobert Mustacchi val);
1163eef4f27bSRobert Mustacchi break;
1164eef4f27bSRobert Mustacchi
1165eef4f27bSRobert Mustacchi case LM_MEDIUM_SPEED_2500MBPS:
1166eef4f27bSRobert Mustacchi if(duplex == LM_MEDIUM_FULL_DUPLEX)
1167eef4f27bSRobert Mustacchi {
1168eef4f27bSRobert Mustacchi val |= MII_CTRL_DUPLEX_MODE;
1169eef4f27bSRobert Mustacchi }
1170eef4f27bSRobert Mustacchi
1171eef4f27bSRobert Mustacchi val |= MII_CTRL_MANUAL_FORCE_2500;
1172eef4f27bSRobert Mustacchi
1173eef4f27bSRobert Mustacchi (void) lm_mwrite(
1174*55fea89dSDan Cross pdev,
1175*55fea89dSDan Cross pdev->params.phy_addr,
1176*55fea89dSDan Cross MII_REG(serdes_reg_t, mii_ctrl),
1177eef4f27bSRobert Mustacchi val);
1178eef4f27bSRobert Mustacchi break;
1179eef4f27bSRobert Mustacchi }
1180eef4f27bSRobert Mustacchi }
1181eef4f27bSRobert Mustacchi
1182eef4f27bSRobert Mustacchi /* exit mac loopback. we could be in mac loopback mode if previously
1183eef4f27bSRobert Mustacchi * the upper module calls lm_init_phy with LM_MEDIUM_TYPE_MAC_LOOPBACK
1184eef4f27bSRobert Mustacchi * medium type for diagnostic. */
1185eef4f27bSRobert Mustacchi REG_RD(pdev, emac.emac_mode, &val);
1186eef4f27bSRobert Mustacchi val &= ~(EMAC_MODE_MAC_LOOP | EMAC_MODE_FORCE_LINK);
1187eef4f27bSRobert Mustacchi REG_WR(pdev, emac.emac_mode, val);
1188eef4f27bSRobert Mustacchi
1189eef4f27bSRobert Mustacchi /* Configure the PHY for jumbo frame. */
1190eef4f27bSRobert Mustacchi if(pdev->params.mtu > MAX_ETHERNET_PACKET_SIZE)
1191eef4f27bSRobert Mustacchi {
1192eef4f27bSRobert Mustacchi (void) lm_mwrite(
1193*55fea89dSDan Cross pdev,
1194eef4f27bSRobert Mustacchi pdev->params.phy_addr,
1195eef4f27bSRobert Mustacchi 0x10+MII_REG(serdes_digital_reg_t, mii_1000x_ctl3),
1196eef4f27bSRobert Mustacchi MII_1000X_CTL3_FIFO_ELAST_10K);
1197eef4f27bSRobert Mustacchi }
1198eef4f27bSRobert Mustacchi else
1199eef4f27bSRobert Mustacchi {
1200eef4f27bSRobert Mustacchi (void) lm_mwrite(
1201*55fea89dSDan Cross pdev,
1202eef4f27bSRobert Mustacchi pdev->params.phy_addr,
1203eef4f27bSRobert Mustacchi 0x10+MII_REG(serdes_digital_reg_t, mii_1000x_ctl3),
1204eef4f27bSRobert Mustacchi 0);
1205eef4f27bSRobert Mustacchi }
1206eef4f27bSRobert Mustacchi
1207eef4f27bSRobert Mustacchi /* Save current medium settings. */
1208eef4f27bSRobert Mustacchi SET_MEDIUM_TYPE(pdev->vars.medium, LM_MEDIUM_TYPE_FIBER);
1209eef4f27bSRobert Mustacchi SET_MEDIUM_SPEED(pdev->vars.medium, speed);
1210eef4f27bSRobert Mustacchi SET_MEDIUM_DUPLEX(pdev->vars.medium, duplex);
1211eef4f27bSRobert Mustacchi
1212eef4f27bSRobert Mustacchi pdev->vars.cable_is_attached = FALSE;
1213eef4f27bSRobert Mustacchi
1214eef4f27bSRobert Mustacchi /* Wait for link. */
1215eef4f27bSRobert Mustacchi (void) lm_mread(
1216*55fea89dSDan Cross pdev,
1217eef4f27bSRobert Mustacchi pdev->params.phy_addr,
1218eef4f27bSRobert Mustacchi MII_REG(serdes_reg_t, mii_status),
1219eef4f27bSRobert Mustacchi &val);
1220eef4f27bSRobert Mustacchi
1221eef4f27bSRobert Mustacchi for(; ;)
1222eef4f27bSRobert Mustacchi {
1223eef4f27bSRobert Mustacchi (void) lm_mread(
1224*55fea89dSDan Cross pdev,
1225eef4f27bSRobert Mustacchi pdev->params.phy_addr,
1226eef4f27bSRobert Mustacchi MII_REG(serdes_reg_t, mii_status),
1227eef4f27bSRobert Mustacchi &val);
1228eef4f27bSRobert Mustacchi if(val & MII_STAT_LINK_STATUS)
1229eef4f27bSRobert Mustacchi {
1230eef4f27bSRobert Mustacchi break;
1231eef4f27bSRobert Mustacchi }
1232eef4f27bSRobert Mustacchi
1233eef4f27bSRobert Mustacchi mm_wait(pdev, 10);
1234eef4f27bSRobert Mustacchi
1235eef4f27bSRobert Mustacchi if(wait_link_timeout_us <= 10)
1236eef4f27bSRobert Mustacchi {
1237eef4f27bSRobert Mustacchi break;
1238eef4f27bSRobert Mustacchi }
1239eef4f27bSRobert Mustacchi
1240eef4f27bSRobert Mustacchi wait_link_timeout_us -= 10;
1241eef4f27bSRobert Mustacchi }
1242eef4f27bSRobert Mustacchi
1243eef4f27bSRobert Mustacchi /* Need to read a second time to get the current link status. */
1244eef4f27bSRobert Mustacchi (void) lm_mread(
1245*55fea89dSDan Cross pdev,
1246eef4f27bSRobert Mustacchi pdev->params.phy_addr,
1247eef4f27bSRobert Mustacchi MII_REG(serdes_reg_t, mii_status),
1248eef4f27bSRobert Mustacchi &val);
1249eef4f27bSRobert Mustacchi if(val & MII_STAT_LINK_STATUS)
1250eef4f27bSRobert Mustacchi {
1251eef4f27bSRobert Mustacchi pdev->vars.link_status = LM_STATUS_LINK_ACTIVE;
1252eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, "phy init link up\n");
1253eef4f27bSRobert Mustacchi
1254eef4f27bSRobert Mustacchi pdev->vars.cable_is_attached = TRUE;
1255eef4f27bSRobert Mustacchi }
1256eef4f27bSRobert Mustacchi else
1257eef4f27bSRobert Mustacchi {
1258eef4f27bSRobert Mustacchi pdev->vars.link_status = LM_STATUS_LINK_DOWN;
1259eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, "phy init link down\n");
1260eef4f27bSRobert Mustacchi }
1261eef4f27bSRobert Mustacchi
1262eef4f27bSRobert Mustacchi return LM_STATUS_SUCCESS;
1263eef4f27bSRobert Mustacchi } /* init_5708_serdes */
1264eef4f27bSRobert Mustacchi
1265eef4f27bSRobert Mustacchi
1266eef4f27bSRobert Mustacchi
1267eef4f27bSRobert Mustacchi /*******************************************************************************
1268eef4f27bSRobert Mustacchi * Description:
1269eef4f27bSRobert Mustacchi *
1270eef4f27bSRobert Mustacchi * Return:
1271eef4f27bSRobert Mustacchi ******************************************************************************/
1272eef4f27bSRobert Mustacchi STATIC void
force_5709_serdes_link(lm_device_t * pdev,lm_medium_t speed,lm_medium_t duplex)1273eef4f27bSRobert Mustacchi force_5709_serdes_link(
1274eef4f27bSRobert Mustacchi lm_device_t *pdev,
1275eef4f27bSRobert Mustacchi lm_medium_t speed,
1276eef4f27bSRobert Mustacchi lm_medium_t duplex)
1277eef4f27bSRobert Mustacchi {
1278eef4f27bSRobert Mustacchi u32_t val;
1279eef4f27bSRobert Mustacchi
1280eef4f27bSRobert Mustacchi /* select serdes digital block. */
1281eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1f, 0x8300);
1282eef4f27bSRobert Mustacchi
1283eef4f27bSRobert Mustacchi /* disable sgmii/fiber mode autodetection. */
1284eef4f27bSRobert Mustacchi (void) lm_mread(pdev, pdev->params.phy_addr, 0x10, &val);
1285eef4f27bSRobert Mustacchi val &= ~0x10;
1286eef4f27bSRobert Mustacchi
1287eef4f27bSRobert Mustacchi /* sgmii or 1000x_fiber mode. */
1288eef4f27bSRobert Mustacchi val &= ~1;
1289eef4f27bSRobert Mustacchi if(speed == LM_MEDIUM_SPEED_2500MBPS)
1290eef4f27bSRobert Mustacchi {
1291eef4f27bSRobert Mustacchi val |= 1;
1292eef4f27bSRobert Mustacchi }
1293eef4f27bSRobert Mustacchi
1294eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x10, val);
1295eef4f27bSRobert Mustacchi
1296eef4f27bSRobert Mustacchi /* select combo ieee0 block. */
1297eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1f, 0xffe0);
1298eef4f27bSRobert Mustacchi
1299eef4f27bSRobert Mustacchi /* phy control register. */
1300eef4f27bSRobert Mustacchi (void) lm_mread(pdev, pdev->params.phy_addr, 0x10, &val);
1301eef4f27bSRobert Mustacchi
1302eef4f27bSRobert Mustacchi val &= ~0x1000; /* autoneg. */
1303eef4f27bSRobert Mustacchi val &= ~0x100; /* duplex. */
1304eef4f27bSRobert Mustacchi val &= ~0x2060; /* speed. */
1305eef4f27bSRobert Mustacchi
1306eef4f27bSRobert Mustacchi if(duplex == LM_MEDIUM_FULL_DUPLEX)
1307eef4f27bSRobert Mustacchi {
1308eef4f27bSRobert Mustacchi val |= 0x100;
1309eef4f27bSRobert Mustacchi }
1310eef4f27bSRobert Mustacchi
1311eef4f27bSRobert Mustacchi if(speed == LM_MEDIUM_SPEED_10MBPS)
1312eef4f27bSRobert Mustacchi {
1313eef4f27bSRobert Mustacchi /* bit 13 and 6 are already cleared. */
1314eef4f27bSRobert Mustacchi ;
1315eef4f27bSRobert Mustacchi }
1316eef4f27bSRobert Mustacchi else if(speed == LM_MEDIUM_SPEED_100MBPS)
1317eef4f27bSRobert Mustacchi {
1318eef4f27bSRobert Mustacchi val |= 0x2000;
1319eef4f27bSRobert Mustacchi }
1320eef4f27bSRobert Mustacchi else if(speed == LM_MEDIUM_SPEED_1000MBPS)
1321eef4f27bSRobert Mustacchi {
1322eef4f27bSRobert Mustacchi val |= 0x2040;
1323eef4f27bSRobert Mustacchi }
1324eef4f27bSRobert Mustacchi else if(speed == LM_MEDIUM_SPEED_2500MBPS)
1325eef4f27bSRobert Mustacchi {
1326eef4f27bSRobert Mustacchi val |= 0x20;
1327eef4f27bSRobert Mustacchi }
1328eef4f27bSRobert Mustacchi else
1329eef4f27bSRobert Mustacchi {
1330eef4f27bSRobert Mustacchi DbgBreakMsg("unknown forced speed.\n");
1331eef4f27bSRobert Mustacchi }
1332eef4f27bSRobert Mustacchi
1333eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x10, val);
1334eef4f27bSRobert Mustacchi
1335eef4f27bSRobert Mustacchi /* set speed. */
1336eef4f27bSRobert Mustacchi if(speed == LM_MEDIUM_SPEED_2500MBPS)
1337eef4f27bSRobert Mustacchi {
1338eef4f27bSRobert Mustacchi /* select serdes digital block. */
1339eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1f, 0x8300);
1340eef4f27bSRobert Mustacchi
1341eef4f27bSRobert Mustacchi /* set 2.5g speed. */
1342eef4f27bSRobert Mustacchi (void) lm_mread(pdev, pdev->params.phy_addr, 0x18, &val);
1343eef4f27bSRobert Mustacchi val &= 0xfff0;
1344eef4f27bSRobert Mustacchi val |= 0x10;
1345eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x18, val);
1346eef4f27bSRobert Mustacchi }
1347eef4f27bSRobert Mustacchi } /* force_5709_serdes_link */
1348eef4f27bSRobert Mustacchi
1349eef4f27bSRobert Mustacchi
1350eef4f27bSRobert Mustacchi
1351eef4f27bSRobert Mustacchi /*******************************************************************************
1352eef4f27bSRobert Mustacchi * Description:
1353eef4f27bSRobert Mustacchi *
1354eef4f27bSRobert Mustacchi * Return:
1355eef4f27bSRobert Mustacchi ******************************************************************************/
1356eef4f27bSRobert Mustacchi STATIC void
init_5709_serdes_for_autoneg(lm_device_t * pdev,lm_medium_t req_medium,lm_flow_control_t flow_ctrl,u32_t selective_autoneg)1357eef4f27bSRobert Mustacchi init_5709_serdes_for_autoneg(
1358eef4f27bSRobert Mustacchi lm_device_t *pdev,
1359eef4f27bSRobert Mustacchi lm_medium_t req_medium,
1360eef4f27bSRobert Mustacchi lm_flow_control_t flow_ctrl,
1361eef4f27bSRobert Mustacchi u32_t selective_autoneg)
1362eef4f27bSRobert Mustacchi {
1363eef4f27bSRobert Mustacchi u32_t val;
1364eef4f27bSRobert Mustacchi
1365eef4f27bSRobert Mustacchi if(GET_MEDIUM_SPEED(req_medium) == LM_MEDIUM_SPEED_UNKNOWN)
1366eef4f27bSRobert Mustacchi {
1367eef4f27bSRobert Mustacchi selective_autoneg = FALSE;
1368eef4f27bSRobert Mustacchi }
1369eef4f27bSRobert Mustacchi
1370eef4f27bSRobert Mustacchi if(!(pdev->hw_info.nvm_hw_config & SHARED_HW_CFG_PHY_FIBER_2_5G) ||
1371eef4f27bSRobert Mustacchi (selective_autoneg &&
1372eef4f27bSRobert Mustacchi GET_MEDIUM_SPEED(req_medium) != LM_MEDIUM_SPEED_2500MBPS))
1373eef4f27bSRobert Mustacchi {
1374eef4f27bSRobert Mustacchi /* disable 2.5g adv */
1375eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1f, 0x8320);
1376eef4f27bSRobert Mustacchi (void) lm_mread(pdev, pdev->params.phy_addr, 0x19, &val);
1377eef4f27bSRobert Mustacchi val &= ~1;
1378eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x19, val);
1379eef4f27bSRobert Mustacchi }
1380eef4f27bSRobert Mustacchi
1381eef4f27bSRobert Mustacchi /* select serdes digital block. */
1382eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1f, 0x8300);
1383eef4f27bSRobert Mustacchi
1384eef4f27bSRobert Mustacchi /* enable sgmii/fiber mode autodetection. */
1385eef4f27bSRobert Mustacchi (void) lm_mread(pdev, pdev->params.phy_addr, 0x10, &val);
1386eef4f27bSRobert Mustacchi val |= 0x10;
1387eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x10, val);
1388eef4f27bSRobert Mustacchi
1389eef4f27bSRobert Mustacchi /* disable parallel detection. */
1390eef4f27bSRobert Mustacchi if(selective_autoneg)
1391eef4f27bSRobert Mustacchi {
1392eef4f27bSRobert Mustacchi (void) lm_mread(pdev, pdev->params.phy_addr, 0x11, &val);
1393eef4f27bSRobert Mustacchi val &= ~0x1;
1394eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x11, val);
1395eef4f27bSRobert Mustacchi }
1396eef4f27bSRobert Mustacchi
1397eef4f27bSRobert Mustacchi /* select bam next page block. */
1398eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1f, 0x8350);
1399*55fea89dSDan Cross
1400eef4f27bSRobert Mustacchi /* mp5_next_page_control. */
1401eef4f27bSRobert Mustacchi (void) lm_mread(pdev, pdev->params.phy_addr, 0x10, &val);
1402eef4f27bSRobert Mustacchi val &= ~3;
1403eef4f27bSRobert Mustacchi val |= 1; /* set bam mode. */
1404eef4f27bSRobert Mustacchi val |= 2; /* enable t2 mode. */
1405eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x10, val);
1406eef4f27bSRobert Mustacchi
1407eef4f27bSRobert Mustacchi /* select cl73_userb0 block. */
1408eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1f, 0x8370);
1409eef4f27bSRobert Mustacchi
1410eef4f27bSRobert Mustacchi /* enable bam_en, bam_station_mngr_en, bam_np_after_bp_en. */
1411eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x12, 0xe000);
1412eef4f27bSRobert Mustacchi
1413eef4f27bSRobert Mustacchi /* select ieee1 block. */
1414eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1f, 0x10);
1415eef4f27bSRobert Mustacchi
1416eef4f27bSRobert Mustacchi /* advertise 1000kx. */
1417eef4f27bSRobert Mustacchi (void) lm_mread(pdev, pdev->params.phy_addr, 0x1, &val);
1418eef4f27bSRobert Mustacchi val |= 0x20;
1419eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1, val);
1420eef4f27bSRobert Mustacchi
1421eef4f27bSRobert Mustacchi /* select ieee0 block. */
1422eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1f, 0);
1423eef4f27bSRobert Mustacchi
1424eef4f27bSRobert Mustacchi /* enable cl73 aneg. */
1425eef4f27bSRobert Mustacchi (void) lm_mread(pdev, pdev->params.phy_addr, 0x0, &val);
1426eef4f27bSRobert Mustacchi val |= 0x1200;
1427eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x0, val);
1428eef4f27bSRobert Mustacchi
1429eef4f27bSRobert Mustacchi /* select combo ieee0 block. */
1430eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1f, 0xffe0);
1431eef4f27bSRobert Mustacchi
1432eef4f27bSRobert Mustacchi /* advertise pause capability and duplex mode. */
1433eef4f27bSRobert Mustacchi val = phy_ad_settings(pdev, req_medium, flow_ctrl);
1434eef4f27bSRobert Mustacchi if(selective_autoneg &&
1435eef4f27bSRobert Mustacchi GET_MEDIUM_SPEED(req_medium) == LM_MEDIUM_SPEED_2500MBPS)
1436eef4f27bSRobert Mustacchi {
1437eef4f27bSRobert Mustacchi val &= ~0x60;
1438eef4f27bSRobert Mustacchi }
1439eef4f27bSRobert Mustacchi else
1440eef4f27bSRobert Mustacchi {
1441eef4f27bSRobert Mustacchi val |= 0x60; /* half/full duplex. */
1442eef4f27bSRobert Mustacchi }
1443eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x14, val);
1444eef4f27bSRobert Mustacchi
1445eef4f27bSRobert Mustacchi /* autoneg_enable and restart. */
1446eef4f27bSRobert Mustacchi (void) lm_mread(pdev, pdev->params.phy_addr, 0x10, &val);
1447*55fea89dSDan Cross val |= 0x1200;
1448eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x10, val);
1449eef4f27bSRobert Mustacchi } /* init_5709_serdes_for_autoneg */
1450eef4f27bSRobert Mustacchi
1451eef4f27bSRobert Mustacchi
1452eef4f27bSRobert Mustacchi
1453eef4f27bSRobert Mustacchi /*******************************************************************************
1454eef4f27bSRobert Mustacchi * Description:
1455eef4f27bSRobert Mustacchi *
1456eef4f27bSRobert Mustacchi * Return:
1457eef4f27bSRobert Mustacchi ******************************************************************************/
1458eef4f27bSRobert Mustacchi STATIC lm_status_t
init_5709_serdes(lm_device_t * pdev,lm_medium_t req_medium,lm_flow_control_t flow_ctrl,u32_t selective_autoneg,u32_t wait_link_timeout_us)1459eef4f27bSRobert Mustacchi init_5709_serdes(
1460eef4f27bSRobert Mustacchi lm_device_t *pdev,
1461eef4f27bSRobert Mustacchi lm_medium_t req_medium,
1462eef4f27bSRobert Mustacchi lm_flow_control_t flow_ctrl,
1463eef4f27bSRobert Mustacchi u32_t selective_autoneg,
1464eef4f27bSRobert Mustacchi u32_t wait_link_timeout_us)
1465eef4f27bSRobert Mustacchi {
1466eef4f27bSRobert Mustacchi lm_medium_t duplex;
1467eef4f27bSRobert Mustacchi lm_medium_t speed;
1468eef4f27bSRobert Mustacchi u32_t idx;
1469eef4f27bSRobert Mustacchi u32_t val;
1470eef4f27bSRobert Mustacchi
1471eef4f27bSRobert Mustacchi speed = GET_MEDIUM_SPEED(req_medium);
1472eef4f27bSRobert Mustacchi duplex = GET_MEDIUM_DUPLEX(req_medium);
1473eef4f27bSRobert Mustacchi
1474eef4f27bSRobert Mustacchi /* use nvram link speed configuration. */
1475eef4f27bSRobert Mustacchi if(speed == LM_MEDIUM_SPEED_HARDWARE_DEFAULT)
1476eef4f27bSRobert Mustacchi {
1477eef4f27bSRobert Mustacchi REG_RD_IND(
1478eef4f27bSRobert Mustacchi pdev,
1479eef4f27bSRobert Mustacchi pdev->hw_info.shmem_base +
1480eef4f27bSRobert Mustacchi OFFSETOF(shmem_region_t, dev_info.port_hw_config.config),
1481eef4f27bSRobert Mustacchi &val);
1482eef4f27bSRobert Mustacchi
1483eef4f27bSRobert Mustacchi switch(val & PORT_HW_CFG_DEFAULT_LINK_MASK)
1484eef4f27bSRobert Mustacchi {
1485eef4f27bSRobert Mustacchi case PORT_HW_CFG_DEFAULT_LINK_1G:
1486eef4f27bSRobert Mustacchi speed = LM_MEDIUM_SPEED_1000MBPS;
1487eef4f27bSRobert Mustacchi break;
1488eef4f27bSRobert Mustacchi
1489eef4f27bSRobert Mustacchi case PORT_HW_CFG_DEFAULT_LINK_2_5G:
1490eef4f27bSRobert Mustacchi speed = LM_MEDIUM_SPEED_2500MBPS;
1491eef4f27bSRobert Mustacchi break;
1492eef4f27bSRobert Mustacchi
1493eef4f27bSRobert Mustacchi default:
1494eef4f27bSRobert Mustacchi speed = LM_MEDIUM_SPEED_UNKNOWN;
1495eef4f27bSRobert Mustacchi break;
1496eef4f27bSRobert Mustacchi }
1497eef4f27bSRobert Mustacchi
1498eef4f27bSRobert Mustacchi selective_autoneg = FALSE;
1499eef4f27bSRobert Mustacchi }
1500eef4f27bSRobert Mustacchi
1501eef4f27bSRobert Mustacchi /* set an_mmd. an_mmd is the only register set we need for
1502eef4f27bSRobert Mustacchi * programming xinan serdes. all other registers are can
1503eef4f27bSRobert Mustacchi * be access through an_mmd. */
1504eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1f, 0xffd0);
1505eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1e, 0x3800);
1506eef4f27bSRobert Mustacchi
1507eef4f27bSRobert Mustacchi /* select combo_ieee0 block. */
1508eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1f, 0xffe0);
1509eef4f27bSRobert Mustacchi
1510eef4f27bSRobert Mustacchi /* reset. */
1511eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x10, MII_CTRL_RESET);
1512eef4f27bSRobert Mustacchi for(idx = 0; idx < 1000; idx++)
1513eef4f27bSRobert Mustacchi {
1514eef4f27bSRobert Mustacchi mm_wait(pdev, 5);
1515*55fea89dSDan Cross
1516eef4f27bSRobert Mustacchi (void) lm_mread(pdev, pdev->params.phy_addr, 0x10, &val);
1517eef4f27bSRobert Mustacchi if(!(val & MII_CTRL_RESET))
1518eef4f27bSRobert Mustacchi {
1519eef4f27bSRobert Mustacchi mm_wait(pdev, 5);
1520eef4f27bSRobert Mustacchi break;
1521eef4f27bSRobert Mustacchi }
1522eef4f27bSRobert Mustacchi }
1523eef4f27bSRobert Mustacchi DbgBreakIf(val & MII_CTRL_RESET);
1524eef4f27bSRobert Mustacchi
1525eef4f27bSRobert Mustacchi /* get phy id. */
1526eef4f27bSRobert Mustacchi (void) lm_mread(pdev, pdev->params.phy_addr, 0x12, &val);
1527eef4f27bSRobert Mustacchi pdev->hw_info.phy_id = val << 16;
1528eef4f27bSRobert Mustacchi (void) lm_mread(pdev, pdev->params.phy_addr, 0x13, &val);
1529eef4f27bSRobert Mustacchi pdev->hw_info.phy_id |= val & 0xffff;
1530eef4f27bSRobert Mustacchi
1531eef4f27bSRobert Mustacchi if(speed == LM_MEDIUM_SPEED_AUTONEG_1G_FALLBACK)
1532eef4f27bSRobert Mustacchi {
1533eef4f27bSRobert Mustacchi speed = LM_MEDIUM_SPEED_AUTONEG;
1534eef4f27bSRobert Mustacchi }
1535eef4f27bSRobert Mustacchi
1536eef4f27bSRobert Mustacchi /* config link speed or autoneg setting. */
1537eef4f27bSRobert Mustacchi if(speed == LM_MEDIUM_SPEED_AUTONEG || selective_autoneg)
1538eef4f27bSRobert Mustacchi {
1539eef4f27bSRobert Mustacchi init_5709_serdes_for_autoneg(
1540eef4f27bSRobert Mustacchi pdev,
1541eef4f27bSRobert Mustacchi req_medium,
1542eef4f27bSRobert Mustacchi flow_ctrl,
1543eef4f27bSRobert Mustacchi selective_autoneg);
1544eef4f27bSRobert Mustacchi }
1545eef4f27bSRobert Mustacchi else
1546eef4f27bSRobert Mustacchi {
1547eef4f27bSRobert Mustacchi force_5709_serdes_link(pdev, speed, duplex);
1548eef4f27bSRobert Mustacchi }
1549eef4f27bSRobert Mustacchi
1550eef4f27bSRobert Mustacchi /* exit mac loopback. we could be in mac loopback mode if previously
1551eef4f27bSRobert Mustacchi * the upper module calls lm_init_phy with LM_MEDIUM_TYPE_MAC_LOOPBACK
1552eef4f27bSRobert Mustacchi * medium type for diagnostic. */
1553eef4f27bSRobert Mustacchi REG_RD(pdev, emac.emac_mode, &val);
1554eef4f27bSRobert Mustacchi val &= ~(EMAC_MODE_MAC_LOOP | EMAC_MODE_FORCE_LINK);
1555eef4f27bSRobert Mustacchi REG_WR(pdev, emac.emac_mode, val);
1556eef4f27bSRobert Mustacchi
1557eef4f27bSRobert Mustacchi SET_MEDIUM_TYPE(pdev->vars.medium, LM_MEDIUM_TYPE_FIBER);
1558eef4f27bSRobert Mustacchi SET_MEDIUM_SPEED(pdev->vars.medium, speed);
1559eef4f27bSRobert Mustacchi SET_MEDIUM_DUPLEX(pdev->vars.medium, duplex);
1560eef4f27bSRobert Mustacchi
1561eef4f27bSRobert Mustacchi pdev->vars.cable_is_attached = FALSE;
1562eef4f27bSRobert Mustacchi
1563eef4f27bSRobert Mustacchi /* select combo_ieee0 block. */
1564eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1f, 0xffe0);
1565eef4f27bSRobert Mustacchi
1566eef4f27bSRobert Mustacchi /* wait for link. */
1567eef4f27bSRobert Mustacchi (void) lm_mread(pdev, pdev->params.phy_addr, 0x11, &val);
1568eef4f27bSRobert Mustacchi
1569eef4f27bSRobert Mustacchi for(; ;)
1570eef4f27bSRobert Mustacchi {
1571eef4f27bSRobert Mustacchi (void) lm_mread(pdev, pdev->params.phy_addr, 0x11, &val);
1572eef4f27bSRobert Mustacchi if(val & 0x4)
1573eef4f27bSRobert Mustacchi {
1574eef4f27bSRobert Mustacchi break;
1575eef4f27bSRobert Mustacchi }
1576eef4f27bSRobert Mustacchi
1577eef4f27bSRobert Mustacchi mm_wait(pdev, 10);
1578eef4f27bSRobert Mustacchi
1579eef4f27bSRobert Mustacchi if(wait_link_timeout_us <= 10)
1580eef4f27bSRobert Mustacchi {
1581eef4f27bSRobert Mustacchi break;
1582eef4f27bSRobert Mustacchi }
1583eef4f27bSRobert Mustacchi
1584eef4f27bSRobert Mustacchi wait_link_timeout_us -= 10;
1585eef4f27bSRobert Mustacchi }
1586eef4f27bSRobert Mustacchi
1587eef4f27bSRobert Mustacchi /* need to read a second time to get the current link status. */
1588eef4f27bSRobert Mustacchi (void) lm_mread(pdev, pdev->params.phy_addr, 0x11, &val);
1589eef4f27bSRobert Mustacchi
1590eef4f27bSRobert Mustacchi if(val & MII_STAT_LINK_STATUS)
1591eef4f27bSRobert Mustacchi {
1592eef4f27bSRobert Mustacchi pdev->vars.link_status = LM_STATUS_LINK_ACTIVE;
1593eef4f27bSRobert Mustacchi pdev->vars.cable_is_attached = TRUE;
1594eef4f27bSRobert Mustacchi }
1595eef4f27bSRobert Mustacchi else
1596eef4f27bSRobert Mustacchi {
1597eef4f27bSRobert Mustacchi pdev->vars.link_status = LM_STATUS_LINK_DOWN;
1598eef4f27bSRobert Mustacchi }
1599eef4f27bSRobert Mustacchi
1600eef4f27bSRobert Mustacchi return LM_STATUS_SUCCESS;
1601eef4f27bSRobert Mustacchi } /* init_5709_serdes */
1602eef4f27bSRobert Mustacchi
1603eef4f27bSRobert Mustacchi
1604eef4f27bSRobert Mustacchi
1605eef4f27bSRobert Mustacchi /*******************************************************************************
1606eef4f27bSRobert Mustacchi * Description:
1607eef4f27bSRobert Mustacchi *
1608eef4f27bSRobert Mustacchi * Return:
1609eef4f27bSRobert Mustacchi ******************************************************************************/
1610eef4f27bSRobert Mustacchi STATIC lm_status_t
init_5706_serdes(lm_device_t * pdev,lm_medium_t req_medium,lm_flow_control_t flow_ctrl,u32_t wait_link_timeout_us)1611eef4f27bSRobert Mustacchi init_5706_serdes(
1612eef4f27bSRobert Mustacchi lm_device_t *pdev,
1613eef4f27bSRobert Mustacchi lm_medium_t req_medium,
1614eef4f27bSRobert Mustacchi lm_flow_control_t flow_ctrl,
1615eef4f27bSRobert Mustacchi u32_t wait_link_timeout_us)
1616eef4f27bSRobert Mustacchi {
1617eef4f27bSRobert Mustacchi lm_medium_t duplex;
1618eef4f27bSRobert Mustacchi lm_medium_t speed;
1619eef4f27bSRobert Mustacchi u32_t val;
1620eef4f27bSRobert Mustacchi u32_t cnt;
1621eef4f27bSRobert Mustacchi
1622eef4f27bSRobert Mustacchi speed = GET_MEDIUM_SPEED(req_medium);
1623eef4f27bSRobert Mustacchi duplex = GET_MEDIUM_DUPLEX(req_medium);
1624eef4f27bSRobert Mustacchi
1625eef4f27bSRobert Mustacchi if(speed == LM_MEDIUM_SPEED_HARDWARE_DEFAULT)
1626eef4f27bSRobert Mustacchi {
1627eef4f27bSRobert Mustacchi REG_RD_IND(
1628eef4f27bSRobert Mustacchi pdev,
1629eef4f27bSRobert Mustacchi pdev->hw_info.shmem_base +
1630eef4f27bSRobert Mustacchi OFFSETOF(shmem_region_t, dev_info.port_hw_config.config),
1631eef4f27bSRobert Mustacchi &val);
1632eef4f27bSRobert Mustacchi switch(val & PORT_HW_CFG_DEFAULT_LINK_MASK)
1633eef4f27bSRobert Mustacchi {
1634eef4f27bSRobert Mustacchi case PORT_HW_CFG_DEFAULT_LINK_1G:
1635eef4f27bSRobert Mustacchi speed = LM_MEDIUM_SPEED_1000MBPS;
1636eef4f27bSRobert Mustacchi break;
1637eef4f27bSRobert Mustacchi
1638eef4f27bSRobert Mustacchi case PORT_HW_CFG_DEFAULT_LINK_2_5G:
1639eef4f27bSRobert Mustacchi speed = LM_MEDIUM_SPEED_2500MBPS;
1640eef4f27bSRobert Mustacchi break;
1641eef4f27bSRobert Mustacchi
1642eef4f27bSRobert Mustacchi case PORT_HW_CFG_DEFAULT_LINK_AN_1G_FALLBACK:
1643eef4f27bSRobert Mustacchi speed = LM_MEDIUM_SPEED_AUTONEG_1G_FALLBACK;
1644eef4f27bSRobert Mustacchi break;
1645eef4f27bSRobert Mustacchi
1646eef4f27bSRobert Mustacchi case PORT_HW_CFG_DEFAULT_LINK_AN_2_5G_FALLBACK:
1647eef4f27bSRobert Mustacchi speed = LM_MEDIUM_SPEED_AUTONEG_2_5G_FALLBACK;
1648eef4f27bSRobert Mustacchi break;
1649eef4f27bSRobert Mustacchi
1650eef4f27bSRobert Mustacchi default:
1651eef4f27bSRobert Mustacchi speed = LM_MEDIUM_SPEED_UNKNOWN;
1652eef4f27bSRobert Mustacchi }
1653eef4f27bSRobert Mustacchi }
1654eef4f27bSRobert Mustacchi
1655eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, PHY_CTRL_REG, PHY_CTRL_PHY_RESET);
1656eef4f27bSRobert Mustacchi for(cnt = 0; cnt < 1000; cnt++)
1657eef4f27bSRobert Mustacchi {
1658eef4f27bSRobert Mustacchi mm_wait(pdev, 5);
1659*55fea89dSDan Cross
1660eef4f27bSRobert Mustacchi (void) lm_mread(pdev, pdev->params.phy_addr, PHY_CTRL_REG, &val);
1661eef4f27bSRobert Mustacchi
1662eef4f27bSRobert Mustacchi if(!(val & PHY_CTRL_PHY_RESET))
1663eef4f27bSRobert Mustacchi {
1664eef4f27bSRobert Mustacchi mm_wait(pdev, 5);
1665eef4f27bSRobert Mustacchi
1666eef4f27bSRobert Mustacchi break;
1667eef4f27bSRobert Mustacchi }
1668eef4f27bSRobert Mustacchi }
1669eef4f27bSRobert Mustacchi
1670eef4f27bSRobert Mustacchi DbgBreakIf(val & PHY_CTRL_PHY_RESET);
1671eef4f27bSRobert Mustacchi
1672eef4f27bSRobert Mustacchi /* Get the PHY id. */
1673eef4f27bSRobert Mustacchi (void) lm_mread(pdev, pdev->params.phy_addr, PHY_ID1_REG, &val);
1674eef4f27bSRobert Mustacchi pdev->hw_info.phy_id = val << 16;
1675eef4f27bSRobert Mustacchi DbgMessage1(pdev, INFORM, "Phy Id1 0x%x\n", val);
1676eef4f27bSRobert Mustacchi
1677eef4f27bSRobert Mustacchi (void) lm_mread(pdev, pdev->params.phy_addr, PHY_ID2_REG, &val);
1678eef4f27bSRobert Mustacchi pdev->hw_info.phy_id |= val & 0xffff;
1679eef4f27bSRobert Mustacchi DbgMessage1(pdev, INFORM, "Phy Id2 0x%x\n", val);
1680eef4f27bSRobert Mustacchi
1681eef4f27bSRobert Mustacchi DbgBreakIf((pdev->hw_info.phy_id & 0x0fffffff) == 0x0fffffff ||
1682eef4f27bSRobert Mustacchi pdev->hw_info.phy_id == 0);
1683eef4f27bSRobert Mustacchi
1684eef4f27bSRobert Mustacchi /* The 5706S has problem determining link so getting link from
1685eef4f27bSRobert Mustacchi * the MII status register is not reliable. This will force
1686eef4f27bSRobert Mustacchi * the MAC to qualify the link ready signal with signal detect.
1687eef4f27bSRobert Mustacchi * We will need to get the link status from the MAC instead of
1688eef4f27bSRobert Mustacchi * the SERDES (MII status register). */
1689eef4f27bSRobert Mustacchi if(CHIP_NUM(pdev) == CHIP_NUM_5706 &&
1690eef4f27bSRobert Mustacchi lm_get_medium(pdev) == LM_MEDIUM_TYPE_FIBER)
1691eef4f27bSRobert Mustacchi {
1692*55fea89dSDan Cross REG_WR(pdev, misc.misc_gp_hw_ctl0,
1693eef4f27bSRobert Mustacchi MISC_GP_HW_CTL0_ENA_SEL_VAUX_B_IN_L2_TE |
1694eef4f27bSRobert Mustacchi MISC_GP_HW_CTL0_GRC_BNK_FREE_FIX_TE);
1695eef4f27bSRobert Mustacchi }
1696eef4f27bSRobert Mustacchi
1697eef4f27bSRobert Mustacchi /* Setup flow control capabilities advertisement. */
1698eef4f27bSRobert Mustacchi val = PHY_AN_AD_1000X_HALF_DUPLEX;
1699eef4f27bSRobert Mustacchi if(duplex == LM_MEDIUM_FULL_DUPLEX)
1700eef4f27bSRobert Mustacchi {
1701eef4f27bSRobert Mustacchi val |= PHY_AN_AD_1000X_FULL_DUPLEX;
1702eef4f27bSRobert Mustacchi }
1703eef4f27bSRobert Mustacchi val |= phy_ad_settings(pdev, req_medium, flow_ctrl);
1704eef4f27bSRobert Mustacchi
1705eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, PHY_AN_AD_REG, val);
1706eef4f27bSRobert Mustacchi
1707eef4f27bSRobert Mustacchi /* Determine the fallback selection. */
1708eef4f27bSRobert Mustacchi switch(speed)
1709eef4f27bSRobert Mustacchi {
1710eef4f27bSRobert Mustacchi case LM_MEDIUM_SPEED_AUTONEG_1G_FALLBACK:
1711eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, "enable serdes_fallback_1g\n");
1712eef4f27bSRobert Mustacchi pdev->vars.serdes_fallback_select = SERDES_FALLBACK_1G;
1713eef4f27bSRobert Mustacchi break;
1714eef4f27bSRobert Mustacchi
1715eef4f27bSRobert Mustacchi case LM_MEDIUM_SPEED_AUTONEG_2_5G_FALLBACK:
1716eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, "enable serdes_fallback_2.5g\n");
1717eef4f27bSRobert Mustacchi pdev->vars.serdes_fallback_select = SERDES_FALLBACK_2_5G;
1718eef4f27bSRobert Mustacchi break;
1719eef4f27bSRobert Mustacchi
1720eef4f27bSRobert Mustacchi default:
1721eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, "disable serdes_fallback.\n");
1722eef4f27bSRobert Mustacchi pdev->vars.serdes_fallback_select = SERDES_FALLBACK_NONE;
1723eef4f27bSRobert Mustacchi pdev->vars.serdes_fallback_status = SERDES_FALLBACK_NONE;
1724eef4f27bSRobert Mustacchi break;
1725eef4f27bSRobert Mustacchi }
1726eef4f27bSRobert Mustacchi
1727eef4f27bSRobert Mustacchi /* This routine could be called anytime. So if has not gone down
1728eef4f27bSRobert Mustacchi * yet, we want to perserve the fallback setting. */
1729eef4f27bSRobert Mustacchi if(pdev->vars.serdes_fallback_select != SERDES_FALLBACK_NONE)
1730eef4f27bSRobert Mustacchi {
1731eef4f27bSRobert Mustacchi speed = LM_MEDIUM_SPEED_AUTONEG;
1732eef4f27bSRobert Mustacchi
1733eef4f27bSRobert Mustacchi if(pdev->vars.link_status == LM_STATUS_LINK_ACTIVE)
1734eef4f27bSRobert Mustacchi {
1735eef4f27bSRobert Mustacchi if(pdev->vars.serdes_fallback_status == SERDES_FALLBACK_1G)
1736eef4f27bSRobert Mustacchi {
1737eef4f27bSRobert Mustacchi speed = LM_MEDIUM_SPEED_1000MBPS;
1738eef4f27bSRobert Mustacchi }
1739eef4f27bSRobert Mustacchi else if(pdev->vars.serdes_fallback_status == SERDES_FALLBACK_2_5G)
1740eef4f27bSRobert Mustacchi {
1741eef4f27bSRobert Mustacchi speed = LM_MEDIUM_SPEED_2500MBPS;
1742eef4f27bSRobert Mustacchi }
1743eef4f27bSRobert Mustacchi }
1744eef4f27bSRobert Mustacchi }
1745eef4f27bSRobert Mustacchi
1746eef4f27bSRobert Mustacchi if(speed == LM_MEDIUM_SPEED_1000MBPS)
1747eef4f27bSRobert Mustacchi {
1748eef4f27bSRobert Mustacchi val = PHY_CTRL_SPEED_SELECT_1000MBPS;
1749eef4f27bSRobert Mustacchi if(duplex == LM_MEDIUM_FULL_DUPLEX)
1750eef4f27bSRobert Mustacchi {
1751eef4f27bSRobert Mustacchi val |= PHY_CTRL_FULL_DUPLEX_MODE;
1752eef4f27bSRobert Mustacchi }
1753eef4f27bSRobert Mustacchi
1754eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, PHY_CTRL_REG, val);
1755eef4f27bSRobert Mustacchi }
1756eef4f27bSRobert Mustacchi else
1757eef4f27bSRobert Mustacchi {
1758eef4f27bSRobert Mustacchi val = PHY_CTRL_AUTO_NEG_ENABLE | PHY_CTRL_RESTART_AUTO_NEG;
1759eef4f27bSRobert Mustacchi
1760eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, PHY_CTRL_REG, val);
1761eef4f27bSRobert Mustacchi
1762eef4f27bSRobert Mustacchi speed = LM_MEDIUM_SPEED_AUTONEG;
1763eef4f27bSRobert Mustacchi }
1764eef4f27bSRobert Mustacchi
1765eef4f27bSRobert Mustacchi /* exit mac loopback. we could be in mac loopback mode if previously
1766eef4f27bSRobert Mustacchi * the upper module calls lm_init_phy with LM_MEDIUM_TYPE_MAC_LOOPBACK
1767eef4f27bSRobert Mustacchi * medium type for diagnostic. */
1768eef4f27bSRobert Mustacchi REG_RD(pdev, emac.emac_mode, &val);
1769eef4f27bSRobert Mustacchi val &= ~(EMAC_MODE_MAC_LOOP | EMAC_MODE_FORCE_LINK);
1770eef4f27bSRobert Mustacchi REG_WR(pdev, emac.emac_mode, val);
1771eef4f27bSRobert Mustacchi
1772eef4f27bSRobert Mustacchi /* Configure the PHY for jumbo frame. */
1773eef4f27bSRobert Mustacchi if(pdev->params.mtu > MAX_ETHERNET_PACKET_SIZE)
1774eef4f27bSRobert Mustacchi {
1775eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x18, 0x4400);
1776eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1c, 0xec87);
1777eef4f27bSRobert Mustacchi }
1778eef4f27bSRobert Mustacchi else
1779eef4f27bSRobert Mustacchi {
1780eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x18, 0x0400);
1781eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1c, 0xec85);
1782eef4f27bSRobert Mustacchi }
1783eef4f27bSRobert Mustacchi
1784eef4f27bSRobert Mustacchi SET_MEDIUM_TYPE(pdev->vars.medium, LM_MEDIUM_TYPE_FIBER);
1785eef4f27bSRobert Mustacchi SET_MEDIUM_SPEED(pdev->vars.medium, speed);
1786eef4f27bSRobert Mustacchi SET_MEDIUM_DUPLEX(pdev->vars.medium, duplex);
1787eef4f27bSRobert Mustacchi
1788eef4f27bSRobert Mustacchi pdev->vars.cable_is_attached = FALSE;
1789eef4f27bSRobert Mustacchi
1790eef4f27bSRobert Mustacchi /* Clear the latch bits. The second read below will get the
1791eef4f27bSRobert Mustacchi * current status. */
1792eef4f27bSRobert Mustacchi val = mii_get_serdes_link_status(pdev);
1793eef4f27bSRobert Mustacchi
1794eef4f27bSRobert Mustacchi /* Wait for link only if the cable is connected. */
1795eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1c, 0x7c00);
1796eef4f27bSRobert Mustacchi (void) lm_mread(pdev, pdev->params.phy_addr, 0x1c, &val);
1797eef4f27bSRobert Mustacchi if(val & 0x10)
1798eef4f27bSRobert Mustacchi {
1799eef4f27bSRobert Mustacchi for(; ;)
1800eef4f27bSRobert Mustacchi {
1801eef4f27bSRobert Mustacchi val = mii_get_serdes_link_status(pdev);
1802eef4f27bSRobert Mustacchi
1803eef4f27bSRobert Mustacchi if(val & PHY_STATUS_LINK_PASS)
1804eef4f27bSRobert Mustacchi {
1805eef4f27bSRobert Mustacchi break;
1806eef4f27bSRobert Mustacchi }
1807eef4f27bSRobert Mustacchi
1808eef4f27bSRobert Mustacchi mm_wait(pdev, 10);
1809eef4f27bSRobert Mustacchi
1810eef4f27bSRobert Mustacchi if(wait_link_timeout_us <= 10)
1811eef4f27bSRobert Mustacchi {
1812eef4f27bSRobert Mustacchi break;
1813eef4f27bSRobert Mustacchi }
1814eef4f27bSRobert Mustacchi
1815eef4f27bSRobert Mustacchi wait_link_timeout_us -= 10;
1816eef4f27bSRobert Mustacchi }
1817eef4f27bSRobert Mustacchi
1818eef4f27bSRobert Mustacchi pdev->vars.cable_is_attached = TRUE;
1819eef4f27bSRobert Mustacchi }
1820eef4f27bSRobert Mustacchi
1821eef4f27bSRobert Mustacchi /* Need to read a second time to get the current link status. */
1822eef4f27bSRobert Mustacchi val = mii_get_serdes_link_status(pdev);
1823eef4f27bSRobert Mustacchi
1824eef4f27bSRobert Mustacchi if(val & PHY_STATUS_LINK_PASS)
1825eef4f27bSRobert Mustacchi {
1826eef4f27bSRobert Mustacchi pdev->vars.link_status = LM_STATUS_LINK_ACTIVE;
1827eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, "phy init link up\n");
1828eef4f27bSRobert Mustacchi }
1829eef4f27bSRobert Mustacchi else
1830eef4f27bSRobert Mustacchi {
1831eef4f27bSRobert Mustacchi pdev->vars.link_status = LM_STATUS_LINK_DOWN;
1832eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, "phy init link down\n");
1833eef4f27bSRobert Mustacchi }
1834eef4f27bSRobert Mustacchi
1835eef4f27bSRobert Mustacchi return LM_STATUS_SUCCESS;
1836eef4f27bSRobert Mustacchi } /* init_5706_serdes */
1837eef4f27bSRobert Mustacchi
1838eef4f27bSRobert Mustacchi
1839eef4f27bSRobert Mustacchi
1840eef4f27bSRobert Mustacchi /*******************************************************************************
1841eef4f27bSRobert Mustacchi * Description:
1842eef4f27bSRobert Mustacchi *
1843eef4f27bSRobert Mustacchi * Return:
1844eef4f27bSRobert Mustacchi ******************************************************************************/
1845eef4f27bSRobert Mustacchi STATIC void
init_serdes_or_phy_loopback(lm_device_t * pdev)1846eef4f27bSRobert Mustacchi init_serdes_or_phy_loopback(
1847eef4f27bSRobert Mustacchi lm_device_t *pdev)
1848eef4f27bSRobert Mustacchi {
1849eef4f27bSRobert Mustacchi u32_t cnt;
1850eef4f27bSRobert Mustacchi u32_t val;
1851eef4f27bSRobert Mustacchi
1852eef4f27bSRobert Mustacchi (void) lm_mwrite(
1853*55fea89dSDan Cross pdev,
1854*55fea89dSDan Cross pdev->params.phy_addr,
1855*55fea89dSDan Cross PHY_CTRL_REG,
1856eef4f27bSRobert Mustacchi PHY_CTRL_PHY_RESET);
1857eef4f27bSRobert Mustacchi for(cnt = 0; cnt < 1000; cnt++)
1858eef4f27bSRobert Mustacchi {
1859eef4f27bSRobert Mustacchi mm_wait(pdev, 5);
1860*55fea89dSDan Cross
1861eef4f27bSRobert Mustacchi (void) lm_mread(pdev, pdev->params.phy_addr, PHY_CTRL_REG, &val);
1862eef4f27bSRobert Mustacchi
1863eef4f27bSRobert Mustacchi if(!(val & PHY_CTRL_PHY_RESET))
1864eef4f27bSRobert Mustacchi {
1865eef4f27bSRobert Mustacchi mm_wait(pdev, 5);
1866eef4f27bSRobert Mustacchi break;
1867eef4f27bSRobert Mustacchi }
1868eef4f27bSRobert Mustacchi }
1869eef4f27bSRobert Mustacchi
1870eef4f27bSRobert Mustacchi DbgBreakIf(val & PHY_CTRL_PHY_RESET);
1871eef4f27bSRobert Mustacchi
1872eef4f27bSRobert Mustacchi /* Get the PHY id. */
1873eef4f27bSRobert Mustacchi (void) lm_mread(pdev, pdev->params.phy_addr, PHY_ID1_REG, &val);
1874eef4f27bSRobert Mustacchi pdev->hw_info.phy_id = val << 16;
1875eef4f27bSRobert Mustacchi DbgMessage1(pdev, INFORM, "Phy Id1 0x%x\n", val);
1876eef4f27bSRobert Mustacchi
1877eef4f27bSRobert Mustacchi (void) lm_mread(pdev, pdev->params.phy_addr, PHY_ID2_REG, &val);
1878eef4f27bSRobert Mustacchi pdev->hw_info.phy_id |= val & 0xffff;
1879eef4f27bSRobert Mustacchi DbgMessage1(pdev, INFORM, "Phy Id2 0x%x\n", val);
1880eef4f27bSRobert Mustacchi
1881eef4f27bSRobert Mustacchi DbgBreakIf((pdev->hw_info.phy_id & 0x0fffffff) == 0x0fffffff ||
1882eef4f27bSRobert Mustacchi pdev->hw_info.phy_id == 0);
1883eef4f27bSRobert Mustacchi
1884eef4f27bSRobert Mustacchi REG_WR(pdev, emac.emac_tx_lengths, 0x26ff);
1885eef4f27bSRobert Mustacchi
1886eef4f27bSRobert Mustacchi /* Set the phy into loopback mode. */
1887eef4f27bSRobert Mustacchi (void) lm_mwrite(
1888*55fea89dSDan Cross pdev,
1889eef4f27bSRobert Mustacchi pdev->params.phy_addr,
1890eef4f27bSRobert Mustacchi PHY_CTRL_REG,
1891*55fea89dSDan Cross PHY_CTRL_LOOPBACK_MODE |
1892eef4f27bSRobert Mustacchi PHY_CTRL_FULL_DUPLEX_MODE |
1893eef4f27bSRobert Mustacchi PHY_CTRL_SPEED_SELECT_1000MBPS);
1894eef4f27bSRobert Mustacchi } /* init_serdes_or_phy_loopback */
1895eef4f27bSRobert Mustacchi
1896eef4f27bSRobert Mustacchi
1897eef4f27bSRobert Mustacchi
1898eef4f27bSRobert Mustacchi /*******************************************************************************
1899eef4f27bSRobert Mustacchi * Description:
1900eef4f27bSRobert Mustacchi *
1901eef4f27bSRobert Mustacchi * Return:
1902eef4f27bSRobert Mustacchi ******************************************************************************/
1903eef4f27bSRobert Mustacchi STATIC void
init_5709_serdes_loopback(lm_device_t * pdev)1904eef4f27bSRobert Mustacchi init_5709_serdes_loopback(
1905eef4f27bSRobert Mustacchi lm_device_t *pdev)
1906eef4f27bSRobert Mustacchi {
1907eef4f27bSRobert Mustacchi u32_t val;
1908eef4f27bSRobert Mustacchi
1909eef4f27bSRobert Mustacchi /*
1910eef4f27bSRobert Mustacchi * reset causes the speed not be back to 2.5g intermittently
1911eef4f27bSRobert Mustacchi * after phy lookback test when connecting to a switch.
1912eef4f27bSRobert Mustacchi */
1913eef4f27bSRobert Mustacchi #if 0
1914eef4f27bSRobert Mustacchi /* select combo_ieee0 block. */
1915eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1f, 0xffe0);
1916eef4f27bSRobert Mustacchi
1917eef4f27bSRobert Mustacchi /* reset. */
1918eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x10, MII_CTRL_RESET);
1919eef4f27bSRobert Mustacchi for(idx = 0; idx < 1000; idx++)
1920eef4f27bSRobert Mustacchi {
1921eef4f27bSRobert Mustacchi mm_wait(pdev, 5);
1922*55fea89dSDan Cross
1923eef4f27bSRobert Mustacchi (void) lm_mread(pdev, pdev->params.phy_addr, 0x10, &val);
1924eef4f27bSRobert Mustacchi if(!(val & MII_CTRL_RESET))
1925eef4f27bSRobert Mustacchi {
1926eef4f27bSRobert Mustacchi mm_wait(pdev, 5);
1927eef4f27bSRobert Mustacchi break;
1928eef4f27bSRobert Mustacchi }
1929eef4f27bSRobert Mustacchi }
1930eef4f27bSRobert Mustacchi DbgBreakIf(val & MII_CTRL_RESET);
1931eef4f27bSRobert Mustacchi #endif
1932eef4f27bSRobert Mustacchi
1933eef4f27bSRobert Mustacchi /* set an_mmd. an_mmd is the only register set we need for
1934eef4f27bSRobert Mustacchi * programming xinan serdes. all other registers are can
1935eef4f27bSRobert Mustacchi * be access through an_mmd. */
1936eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1f, 0xffd0);
1937eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1e, 0x3800);
1938eef4f27bSRobert Mustacchi
1939eef4f27bSRobert Mustacchi /* get phy id. */
1940eef4f27bSRobert Mustacchi (void) lm_mread(pdev, pdev->params.phy_addr, 0x12, &val);
1941eef4f27bSRobert Mustacchi pdev->hw_info.phy_id = val << 16;
1942eef4f27bSRobert Mustacchi (void) lm_mread(pdev, pdev->params.phy_addr, 0x13, &val);
1943eef4f27bSRobert Mustacchi pdev->hw_info.phy_id |= val & 0xffff;
1944eef4f27bSRobert Mustacchi
1945eef4f27bSRobert Mustacchi /* select combo_ieee0 block. */
1946eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1f, 0xffe0);
1947eef4f27bSRobert Mustacchi
1948eef4f27bSRobert Mustacchi /*CQ31687:set autoneg_enable bit too.*/
1949*55fea89dSDan Cross /* Set the phy into loopback mode. */
1950eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x10, 0x5140);
1951eef4f27bSRobert Mustacchi
1952eef4f27bSRobert Mustacchi } /* init_5709_serdes_loopback */
1953eef4f27bSRobert Mustacchi
1954eef4f27bSRobert Mustacchi
1955eef4f27bSRobert Mustacchi
1956eef4f27bSRobert Mustacchi /*******************************************************************************
1957eef4f27bSRobert Mustacchi * Description:
1958eef4f27bSRobert Mustacchi *
1959eef4f27bSRobert Mustacchi * Return:
1960eef4f27bSRobert Mustacchi ******************************************************************************/
1961eef4f27bSRobert Mustacchi STATIC lm_status_t
init_loopback_mac_link(lm_device_t * pdev,lm_medium_t req_medium,lm_flow_control_t flow_ctrl)1962eef4f27bSRobert Mustacchi init_loopback_mac_link(
1963eef4f27bSRobert Mustacchi lm_device_t *pdev,
1964eef4f27bSRobert Mustacchi lm_medium_t req_medium,
1965eef4f27bSRobert Mustacchi lm_flow_control_t flow_ctrl)
1966eef4f27bSRobert Mustacchi {
1967eef4f27bSRobert Mustacchi lm_status_t lm_status;
1968eef4f27bSRobert Mustacchi u32_t val;
1969eef4f27bSRobert Mustacchi
1970eef4f27bSRobert Mustacchi lm_status = LM_STATUS_SUCCESS;
1971eef4f27bSRobert Mustacchi
1972eef4f27bSRobert Mustacchi if(GET_MEDIUM_TYPE(req_medium) == LM_MEDIUM_TYPE_PHY_LOOPBACK)
1973eef4f27bSRobert Mustacchi {
1974*55fea89dSDan Cross if(CHIP_NUM(pdev) == CHIP_NUM_5709 &&
1975eef4f27bSRobert Mustacchi lm_get_medium(pdev) == LM_MEDIUM_TYPE_FIBER)
1976eef4f27bSRobert Mustacchi {
1977eef4f27bSRobert Mustacchi init_5709_serdes_loopback(pdev);
1978eef4f27bSRobert Mustacchi }
1979eef4f27bSRobert Mustacchi else
1980eef4f27bSRobert Mustacchi {
1981eef4f27bSRobert Mustacchi init_serdes_or_phy_loopback(pdev);
1982eef4f27bSRobert Mustacchi }
1983eef4f27bSRobert Mustacchi
1984eef4f27bSRobert Mustacchi REG_WR(pdev, emac.emac_tx_lengths, 0x26ff);
1985eef4f27bSRobert Mustacchi
1986eef4f27bSRobert Mustacchi REG_RD(pdev, emac.emac_mode, &val);
1987eef4f27bSRobert Mustacchi val &= ~(EMAC_MODE_MAC_LOOP | EMAC_MODE_PORT);
1988eef4f27bSRobert Mustacchi val |= EMAC_MODE_FORCE_LINK | EMAC_MODE_PORT_GMII;
1989eef4f27bSRobert Mustacchi REG_WR(pdev, emac.emac_mode, val);
1990eef4f27bSRobert Mustacchi
1991eef4f27bSRobert Mustacchi SET_MEDIUM_TYPE(pdev->vars.medium, LM_MEDIUM_TYPE_PHY_LOOPBACK);
1992eef4f27bSRobert Mustacchi SET_MEDIUM_SPEED(pdev->vars.medium, LM_MEDIUM_SPEED_UNKNOWN);
1993eef4f27bSRobert Mustacchi SET_MEDIUM_DUPLEX(pdev->vars.medium, LM_MEDIUM_FULL_DUPLEX);
1994eef4f27bSRobert Mustacchi
1995eef4f27bSRobert Mustacchi /* Save current link status. */
1996eef4f27bSRobert Mustacchi pdev->vars.link_status = LM_STATUS_LINK_ACTIVE;
1997eef4f27bSRobert Mustacchi
1998eef4f27bSRobert Mustacchi pdev->vars.cable_is_attached = TRUE;
1999eef4f27bSRobert Mustacchi }
2000eef4f27bSRobert Mustacchi else if(GET_MEDIUM_TYPE(req_medium) == LM_MEDIUM_TYPE_MAC_LOOPBACK)
2001eef4f27bSRobert Mustacchi {
2002eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, "Set up MAC loopback mode.\n");
2003eef4f27bSRobert Mustacchi
2004eef4f27bSRobert Mustacchi /* Set the MAC into loopback mode. Mac loopback will intermittenly
2005eef4f27bSRobert Mustacchi * fail if half_duplex bit is set. CQ#24594. */
2006eef4f27bSRobert Mustacchi REG_RD(pdev, emac.emac_mode, &val);
2007eef4f27bSRobert Mustacchi val &= ~(EMAC_MODE_PORT | EMAC_MODE_HALF_DUPLEX);
2008eef4f27bSRobert Mustacchi val |= EMAC_MODE_MAC_LOOP | EMAC_MODE_FORCE_LINK;
2009eef4f27bSRobert Mustacchi
2010eef4f27bSRobert Mustacchi /* The port mode must be set to none on the real chip. */
2011eef4f27bSRobert Mustacchi if(CHIP_REV(pdev) == CHIP_REV_FPGA)
2012eef4f27bSRobert Mustacchi {
2013eef4f27bSRobert Mustacchi val |= EMAC_MODE_PORT_GMII;
2014eef4f27bSRobert Mustacchi }
2015eef4f27bSRobert Mustacchi
2016eef4f27bSRobert Mustacchi REG_WR(pdev, emac.emac_mode, val);
2017eef4f27bSRobert Mustacchi
2018eef4f27bSRobert Mustacchi SET_MEDIUM_TYPE(pdev->vars.medium, LM_MEDIUM_TYPE_MAC_LOOPBACK);
2019eef4f27bSRobert Mustacchi SET_MEDIUM_SPEED(pdev->vars.medium, LM_MEDIUM_SPEED_UNKNOWN);
2020eef4f27bSRobert Mustacchi SET_MEDIUM_DUPLEX(pdev->vars.medium, LM_MEDIUM_FULL_DUPLEX);
2021eef4f27bSRobert Mustacchi
2022eef4f27bSRobert Mustacchi /* Save current link status. */
2023eef4f27bSRobert Mustacchi pdev->vars.link_status = LM_STATUS_LINK_ACTIVE;
2024eef4f27bSRobert Mustacchi
2025eef4f27bSRobert Mustacchi pdev->vars.cable_is_attached = TRUE;
2026eef4f27bSRobert Mustacchi }
2027eef4f27bSRobert Mustacchi else
2028eef4f27bSRobert Mustacchi {
2029eef4f27bSRobert Mustacchi DbgBreakMsg("Not loopback medium type.\n");
2030eef4f27bSRobert Mustacchi
2031eef4f27bSRobert Mustacchi lm_status = LM_STATUS_FAILURE;
2032eef4f27bSRobert Mustacchi
2033eef4f27bSRobert Mustacchi /* Save current link status. */
2034eef4f27bSRobert Mustacchi pdev->vars.link_status = LM_STATUS_LINK_DOWN;
2035eef4f27bSRobert Mustacchi
2036eef4f27bSRobert Mustacchi pdev->vars.cable_is_attached = FALSE;
2037eef4f27bSRobert Mustacchi }
2038eef4f27bSRobert Mustacchi
2039eef4f27bSRobert Mustacchi /* Enable status block link attention. */
2040eef4f27bSRobert Mustacchi REG_RD(pdev, hc.hc_attn_bits_enable, &val);
2041eef4f27bSRobert Mustacchi val |= STATUS_ATTN_BITS_LINK_STATE;
2042eef4f27bSRobert Mustacchi REG_WR(pdev, hc.hc_attn_bits_enable, val);
2043eef4f27bSRobert Mustacchi
2044eef4f27bSRobert Mustacchi return lm_status;
2045eef4f27bSRobert Mustacchi } /* init_loopback_mac_link */
2046eef4f27bSRobert Mustacchi
2047eef4f27bSRobert Mustacchi
2048eef4f27bSRobert Mustacchi
2049eef4f27bSRobert Mustacchi /*******************************************************************************
2050eef4f27bSRobert Mustacchi * Description:
2051eef4f27bSRobert Mustacchi *
2052eef4f27bSRobert Mustacchi * Return:
2053eef4f27bSRobert Mustacchi ******************************************************************************/
2054eef4f27bSRobert Mustacchi STATIC lm_status_t
init_null_phy(lm_device_t * pdev,lm_medium_t req_medium,lm_flow_control_t flow_ctrl,u32_t wait_link_timeout_us)2055eef4f27bSRobert Mustacchi init_null_phy(
2056eef4f27bSRobert Mustacchi lm_device_t *pdev,
2057eef4f27bSRobert Mustacchi lm_medium_t req_medium,
2058eef4f27bSRobert Mustacchi lm_flow_control_t flow_ctrl,
2059eef4f27bSRobert Mustacchi u32_t wait_link_timeout_us)
2060eef4f27bSRobert Mustacchi {
2061eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, "### init_null_phy\n");
2062eef4f27bSRobert Mustacchi
2063eef4f27bSRobert Mustacchi if(GET_MEDIUM_TYPE(req_medium) != LM_MEDIUM_TYPE_NULL)
2064eef4f27bSRobert Mustacchi {
2065eef4f27bSRobert Mustacchi return LM_STATUS_INVALID_PARAMETER;
2066eef4f27bSRobert Mustacchi }
2067eef4f27bSRobert Mustacchi
2068eef4f27bSRobert Mustacchi /* Save current medium settings. */
2069eef4f27bSRobert Mustacchi SET_MEDIUM_TYPE(pdev->vars.medium, LM_MEDIUM_TYPE_NULL);
2070eef4f27bSRobert Mustacchi SET_MEDIUM_SPEED(pdev->vars.medium, LM_MEDIUM_SPEED_1000MBPS);
2071eef4f27bSRobert Mustacchi SET_MEDIUM_DUPLEX(pdev->vars.medium, LM_MEDIUM_FULL_DUPLEX);
2072eef4f27bSRobert Mustacchi
2073eef4f27bSRobert Mustacchi pdev->vars.cable_is_attached = TRUE;
2074eef4f27bSRobert Mustacchi
2075eef4f27bSRobert Mustacchi return LM_STATUS_SUCCESS;
2076eef4f27bSRobert Mustacchi } /* init_null_phy */
2077eef4f27bSRobert Mustacchi
2078eef4f27bSRobert Mustacchi
2079eef4f27bSRobert Mustacchi
2080eef4f27bSRobert Mustacchi /*******************************************************************************
2081eef4f27bSRobert Mustacchi * Description:
2082eef4f27bSRobert Mustacchi *
2083eef4f27bSRobert Mustacchi * Return:
2084eef4f27bSRobert Mustacchi ******************************************************************************/
2085eef4f27bSRobert Mustacchi STATIC u32_t
netlink_pause_ad(lm_flow_control_t flow_ctrl)2086eef4f27bSRobert Mustacchi netlink_pause_ad(
2087eef4f27bSRobert Mustacchi lm_flow_control_t flow_ctrl)
2088eef4f27bSRobert Mustacchi {
2089eef4f27bSRobert Mustacchi u32_t pause_ad;
2090eef4f27bSRobert Mustacchi
2091eef4f27bSRobert Mustacchi pause_ad = 0;
2092eef4f27bSRobert Mustacchi
2093eef4f27bSRobert Mustacchi if((flow_ctrl == LM_FLOW_CONTROL_AUTO_PAUSE) ||
2094eef4f27bSRobert Mustacchi ((flow_ctrl & LM_FLOW_CONTROL_RECEIVE_PAUSE) &&
2095eef4f27bSRobert Mustacchi (flow_ctrl & LM_FLOW_CONTROL_TRANSMIT_PAUSE)))
2096eef4f27bSRobert Mustacchi {
2097eef4f27bSRobert Mustacchi pause_ad |= NETLINK_DRV_SET_LINK_FC_SYM_PAUSE |
2098eef4f27bSRobert Mustacchi NETLINK_DRV_SET_LINK_FC_ASYM_PAUSE;
2099eef4f27bSRobert Mustacchi }
2100eef4f27bSRobert Mustacchi else if(flow_ctrl & LM_FLOW_CONTROL_TRANSMIT_PAUSE)
2101eef4f27bSRobert Mustacchi {
2102eef4f27bSRobert Mustacchi pause_ad |= NETLINK_DRV_SET_LINK_FC_ASYM_PAUSE;
2103eef4f27bSRobert Mustacchi }
2104eef4f27bSRobert Mustacchi else if(flow_ctrl & LM_FLOW_CONTROL_RECEIVE_PAUSE)
2105eef4f27bSRobert Mustacchi {
2106eef4f27bSRobert Mustacchi pause_ad |= NETLINK_DRV_SET_LINK_FC_SYM_PAUSE |
2107eef4f27bSRobert Mustacchi NETLINK_DRV_SET_LINK_FC_ASYM_PAUSE;
2108eef4f27bSRobert Mustacchi }
2109eef4f27bSRobert Mustacchi
2110eef4f27bSRobert Mustacchi return pause_ad;
2111eef4f27bSRobert Mustacchi } /* netlink_pause_ad */
2112eef4f27bSRobert Mustacchi
2113eef4f27bSRobert Mustacchi
2114eef4f27bSRobert Mustacchi
2115eef4f27bSRobert Mustacchi /*******************************************************************************
2116eef4f27bSRobert Mustacchi * Description:
2117eef4f27bSRobert Mustacchi *
2118eef4f27bSRobert Mustacchi * Return:
2119eef4f27bSRobert Mustacchi ******************************************************************************/
2120eef4f27bSRobert Mustacchi STATIC u32_t
link_setting_to_netlink(lm_link_settings_t * link_settings,u32_t serdes)2121eef4f27bSRobert Mustacchi link_setting_to_netlink(
2122eef4f27bSRobert Mustacchi lm_link_settings_t *link_settings,
2123eef4f27bSRobert Mustacchi u32_t serdes)
2124eef4f27bSRobert Mustacchi {
2125eef4f27bSRobert Mustacchi lm_medium_t duplex;
2126eef4f27bSRobert Mustacchi lm_medium_t speed;
2127eef4f27bSRobert Mustacchi u32_t netlink;
2128eef4f27bSRobert Mustacchi
2129eef4f27bSRobert Mustacchi speed = GET_MEDIUM_SPEED(link_settings->req_medium);
2130eef4f27bSRobert Mustacchi duplex = GET_MEDIUM_DUPLEX(link_settings->req_medium);
2131eef4f27bSRobert Mustacchi netlink = 0;
2132eef4f27bSRobert Mustacchi
2133eef4f27bSRobert Mustacchi switch(speed)
2134eef4f27bSRobert Mustacchi {
2135eef4f27bSRobert Mustacchi case LM_MEDIUM_SPEED_10MBPS:
2136eef4f27bSRobert Mustacchi if(duplex == LM_MEDIUM_FULL_DUPLEX)
2137eef4f27bSRobert Mustacchi {
2138eef4f27bSRobert Mustacchi netlink |= NETLINK_DRV_SET_LINK_SPEED_10FULL;
2139eef4f27bSRobert Mustacchi
2140eef4f27bSRobert Mustacchi if((link_settings->flag & LINK_FLAG_SELECTIVE_AUTONEG_MASK) ==
2141eef4f27bSRobert Mustacchi LINK_FLAG_SELECTIVE_AUTONEG_ENABLE_SLOWER_SPEEDS)
2142eef4f27bSRobert Mustacchi {
2143eef4f27bSRobert Mustacchi netlink |= NETLINK_DRV_SET_LINK_SPEED_10HALF;
2144eef4f27bSRobert Mustacchi }
2145eef4f27bSRobert Mustacchi }
2146eef4f27bSRobert Mustacchi else
2147eef4f27bSRobert Mustacchi {
2148eef4f27bSRobert Mustacchi netlink |= NETLINK_DRV_SET_LINK_SPEED_10HALF;
2149eef4f27bSRobert Mustacchi }
2150eef4f27bSRobert Mustacchi break;
2151eef4f27bSRobert Mustacchi
2152eef4f27bSRobert Mustacchi case LM_MEDIUM_SPEED_100MBPS:
2153eef4f27bSRobert Mustacchi if((link_settings->flag & LINK_FLAG_SELECTIVE_AUTONEG_MASK) ==
2154eef4f27bSRobert Mustacchi LINK_FLAG_SELECTIVE_AUTONEG_ENABLE_SLOWER_SPEEDS)
2155eef4f27bSRobert Mustacchi {
2156eef4f27bSRobert Mustacchi netlink |= NETLINK_DRV_SET_LINK_SPEED_10FULL;
2157eef4f27bSRobert Mustacchi netlink |= NETLINK_DRV_SET_LINK_SPEED_10HALF;
2158eef4f27bSRobert Mustacchi }
2159eef4f27bSRobert Mustacchi
2160eef4f27bSRobert Mustacchi if(duplex == LM_MEDIUM_FULL_DUPLEX)
2161eef4f27bSRobert Mustacchi {
2162eef4f27bSRobert Mustacchi netlink |= NETLINK_DRV_SET_LINK_SPEED_100FULL;
2163eef4f27bSRobert Mustacchi
2164eef4f27bSRobert Mustacchi if((link_settings->flag & LINK_FLAG_SELECTIVE_AUTONEG_MASK) ==
2165eef4f27bSRobert Mustacchi LINK_FLAG_SELECTIVE_AUTONEG_ENABLE_SLOWER_SPEEDS)
2166eef4f27bSRobert Mustacchi {
2167eef4f27bSRobert Mustacchi netlink |= NETLINK_DRV_SET_LINK_SPEED_100HALF;
2168eef4f27bSRobert Mustacchi }
2169eef4f27bSRobert Mustacchi }
2170eef4f27bSRobert Mustacchi else
2171eef4f27bSRobert Mustacchi {
2172eef4f27bSRobert Mustacchi netlink |= NETLINK_DRV_SET_LINK_SPEED_100HALF;
2173eef4f27bSRobert Mustacchi }
2174eef4f27bSRobert Mustacchi break;
2175eef4f27bSRobert Mustacchi
2176eef4f27bSRobert Mustacchi case LM_MEDIUM_SPEED_1000MBPS:
2177eef4f27bSRobert Mustacchi if((link_settings->flag & LINK_FLAG_SELECTIVE_AUTONEG_MASK) ==
2178eef4f27bSRobert Mustacchi LINK_FLAG_SELECTIVE_AUTONEG_ENABLE_SLOWER_SPEEDS)
2179eef4f27bSRobert Mustacchi {
2180eef4f27bSRobert Mustacchi netlink |= NETLINK_DRV_SET_LINK_SPEED_10FULL;
2181eef4f27bSRobert Mustacchi netlink |= NETLINK_DRV_SET_LINK_SPEED_10HALF;
2182eef4f27bSRobert Mustacchi netlink |= NETLINK_DRV_SET_LINK_SPEED_100FULL;
2183eef4f27bSRobert Mustacchi netlink |= NETLINK_DRV_SET_LINK_SPEED_100HALF;
2184eef4f27bSRobert Mustacchi }
2185eef4f27bSRobert Mustacchi
2186eef4f27bSRobert Mustacchi if(duplex == LM_MEDIUM_FULL_DUPLEX)
2187eef4f27bSRobert Mustacchi {
2188eef4f27bSRobert Mustacchi netlink |= NETLINK_DRV_SET_LINK_SPEED_1GFULL;
2189eef4f27bSRobert Mustacchi
2190eef4f27bSRobert Mustacchi if((link_settings->flag & LINK_FLAG_SELECTIVE_AUTONEG_MASK) ==
2191eef4f27bSRobert Mustacchi LINK_FLAG_SELECTIVE_AUTONEG_ENABLE_SLOWER_SPEEDS)
2192eef4f27bSRobert Mustacchi {
2193eef4f27bSRobert Mustacchi netlink |= NETLINK_DRV_SET_LINK_SPEED_1GHALF;
2194eef4f27bSRobert Mustacchi }
2195eef4f27bSRobert Mustacchi }
2196eef4f27bSRobert Mustacchi else
2197eef4f27bSRobert Mustacchi {
2198eef4f27bSRobert Mustacchi netlink |= NETLINK_DRV_SET_LINK_SPEED_1GHALF;
2199eef4f27bSRobert Mustacchi }
2200eef4f27bSRobert Mustacchi break;
2201eef4f27bSRobert Mustacchi
2202eef4f27bSRobert Mustacchi default:
2203eef4f27bSRobert Mustacchi if (serdes)
2204eef4f27bSRobert Mustacchi {
2205eef4f27bSRobert Mustacchi netlink |= NETLINK_DRV_SET_LINK_ENABLE_AUTONEG |
2206eef4f27bSRobert Mustacchi NETLINK_DRV_SET_LINK_SPEED_1GHALF |
2207eef4f27bSRobert Mustacchi NETLINK_DRV_SET_LINK_SPEED_1GFULL;
2208eef4f27bSRobert Mustacchi }
2209eef4f27bSRobert Mustacchi else
2210eef4f27bSRobert Mustacchi {
2211eef4f27bSRobert Mustacchi netlink |= NETLINK_DRV_SET_LINK_ENABLE_AUTONEG |
2212eef4f27bSRobert Mustacchi NETLINK_DRV_SET_LINK_SPEED_10HALF |
2213eef4f27bSRobert Mustacchi NETLINK_DRV_SET_LINK_SPEED_10FULL |
2214eef4f27bSRobert Mustacchi NETLINK_DRV_SET_LINK_SPEED_100HALF |
2215eef4f27bSRobert Mustacchi NETLINK_DRV_SET_LINK_SPEED_100FULL |
2216eef4f27bSRobert Mustacchi NETLINK_DRV_SET_LINK_SPEED_1GHALF |
2217eef4f27bSRobert Mustacchi NETLINK_DRV_SET_LINK_SPEED_1GFULL;
2218eef4f27bSRobert Mustacchi }
2219eef4f27bSRobert Mustacchi break;
2220eef4f27bSRobert Mustacchi }
2221eef4f27bSRobert Mustacchi
2222eef4f27bSRobert Mustacchi netlink |= NETLINK_DRV_SET_LINK_PHY_RESET;
2223eef4f27bSRobert Mustacchi
2224eef4f27bSRobert Mustacchi if(link_settings->flag & LINK_FLAG_SELECTIVE_AUTONEG_MASK)
2225eef4f27bSRobert Mustacchi {
2226eef4f27bSRobert Mustacchi netlink |= NETLINK_DRV_SET_LINK_ENABLE_AUTONEG;
2227eef4f27bSRobert Mustacchi }
2228eef4f27bSRobert Mustacchi
2229eef4f27bSRobert Mustacchi if(link_settings->flag & LINK_FLAG_WIRE_SPEED)
2230eef4f27bSRobert Mustacchi {
2231eef4f27bSRobert Mustacchi netlink |= NETLINK_DRV_SET_LINK_ETH_AT_WIRESPEED_ENABLE;
2232eef4f27bSRobert Mustacchi }
2233eef4f27bSRobert Mustacchi
2234eef4f27bSRobert Mustacchi netlink |= netlink_pause_ad(link_settings->flow_ctrl);
2235eef4f27bSRobert Mustacchi
2236eef4f27bSRobert Mustacchi return netlink;
2237eef4f27bSRobert Mustacchi } /* link_settings_to_netlink */
2238eef4f27bSRobert Mustacchi
2239eef4f27bSRobert Mustacchi
2240eef4f27bSRobert Mustacchi
2241eef4f27bSRobert Mustacchi /*******************************************************************************
2242eef4f27bSRobert Mustacchi * Description:
2243eef4f27bSRobert Mustacchi *
2244eef4f27bSRobert Mustacchi * Return:
2245eef4f27bSRobert Mustacchi ******************************************************************************/
2246eef4f27bSRobert Mustacchi lm_status_t
lm_init_remote_phy(lm_device_t * pdev,lm_link_settings_t * serdes_link,lm_link_settings_t * rphy_link)2247eef4f27bSRobert Mustacchi lm_init_remote_phy(
2248eef4f27bSRobert Mustacchi lm_device_t *pdev,
2249eef4f27bSRobert Mustacchi lm_link_settings_t *serdes_link,
2250eef4f27bSRobert Mustacchi lm_link_settings_t *rphy_link)
2251eef4f27bSRobert Mustacchi {
2252eef4f27bSRobert Mustacchi u32_t serdes_netlink;
2253eef4f27bSRobert Mustacchi u32_t rphy_netlink;
2254eef4f27bSRobert Mustacchi u32_t set_link_arg;
2255eef4f27bSRobert Mustacchi u32_t val;
2256eef4f27bSRobert Mustacchi
2257eef4f27bSRobert Mustacchi DbgBreakIf(pdev->params.enable_remote_phy == FALSE);
2258eef4f27bSRobert Mustacchi
2259eef4f27bSRobert Mustacchi serdes_netlink = link_setting_to_netlink(serdes_link, TRUE);
2260eef4f27bSRobert Mustacchi rphy_netlink = link_setting_to_netlink(rphy_link, FALSE);
2261eef4f27bSRobert Mustacchi
2262eef4f27bSRobert Mustacchi REG_WR_IND(
2263eef4f27bSRobert Mustacchi pdev,
2264eef4f27bSRobert Mustacchi pdev->hw_info.shmem_base +
2265eef4f27bSRobert Mustacchi OFFSETOF(shmem_region_t, remotephy.serdes_link_pref),
2266eef4f27bSRobert Mustacchi serdes_netlink);
2267eef4f27bSRobert Mustacchi
2268eef4f27bSRobert Mustacchi REG_WR_IND(
2269eef4f27bSRobert Mustacchi pdev,
2270eef4f27bSRobert Mustacchi pdev->hw_info.shmem_base +
2271eef4f27bSRobert Mustacchi OFFSETOF(shmem_region_t, remotephy.copper_phy_link_pref),
2272eef4f27bSRobert Mustacchi rphy_netlink | NETLINK_DRV_SET_LINK_PHY_APP_REMOTE);
2273eef4f27bSRobert Mustacchi
2274eef4f27bSRobert Mustacchi REG_RD_IND(
2275eef4f27bSRobert Mustacchi pdev,
2276eef4f27bSRobert Mustacchi pdev->hw_info.shmem_base +
2277eef4f27bSRobert Mustacchi OFFSETOF(shmem_region_t, drv_fw_mb.link_status),
2278eef4f27bSRobert Mustacchi &val);
2279eef4f27bSRobert Mustacchi if(val & NETLINK_GET_LINK_STATUS_SERDES_LINK)
2280eef4f27bSRobert Mustacchi {
2281eef4f27bSRobert Mustacchi set_link_arg = serdes_netlink;
2282eef4f27bSRobert Mustacchi }
2283eef4f27bSRobert Mustacchi else
2284eef4f27bSRobert Mustacchi {
2285eef4f27bSRobert Mustacchi set_link_arg = rphy_netlink | NETLINK_DRV_SET_LINK_PHY_APP_REMOTE;
2286eef4f27bSRobert Mustacchi }
2287eef4f27bSRobert Mustacchi
2288eef4f27bSRobert Mustacchi REG_WR_IND(
2289eef4f27bSRobert Mustacchi pdev,
2290eef4f27bSRobert Mustacchi pdev->hw_info.shmem_base +
2291eef4f27bSRobert Mustacchi OFFSETOF(shmem_region_t, drv_fw_mb.mb_args[0]),
2292eef4f27bSRobert Mustacchi set_link_arg);
2293eef4f27bSRobert Mustacchi
2294eef4f27bSRobert Mustacchi (void) lm_submit_fw_cmd(pdev, DRV_MSG_CODE_CMD_SET_LINK);
2295eef4f27bSRobert Mustacchi
2296eef4f27bSRobert Mustacchi return LM_STATUS_SUCCESS;
2297eef4f27bSRobert Mustacchi } /* lm_init_remote_phy */
2298eef4f27bSRobert Mustacchi
2299eef4f27bSRobert Mustacchi
2300eef4f27bSRobert Mustacchi
2301eef4f27bSRobert Mustacchi /*******************************************************************************
2302eef4f27bSRobert Mustacchi * Description:
2303eef4f27bSRobert Mustacchi *
2304eef4f27bSRobert Mustacchi * Return:
2305eef4f27bSRobert Mustacchi ******************************************************************************/
2306eef4f27bSRobert Mustacchi lm_status_t
lm_init_phy(lm_device_t * pdev,lm_medium_t req_medium,lm_flow_control_t flow_ctrl,u32_t selective_autoneg,u32_t wire_speed,u32_t wait_link_timeout_us)2307eef4f27bSRobert Mustacchi lm_init_phy(
2308eef4f27bSRobert Mustacchi lm_device_t *pdev,
2309eef4f27bSRobert Mustacchi lm_medium_t req_medium,
2310eef4f27bSRobert Mustacchi lm_flow_control_t flow_ctrl,
2311eef4f27bSRobert Mustacchi u32_t selective_autoneg,
2312eef4f27bSRobert Mustacchi u32_t wire_speed,
2313eef4f27bSRobert Mustacchi u32_t wait_link_timeout_us)
2314eef4f27bSRobert Mustacchi {
2315eef4f27bSRobert Mustacchi lm_status_t lm_status;
2316eef4f27bSRobert Mustacchi
2317eef4f27bSRobert Mustacchi DbgBreakIf(pdev->params.enable_remote_phy);
2318eef4f27bSRobert Mustacchi
2319eef4f27bSRobert Mustacchi if(GET_MEDIUM_AUTONEG_MODE(req_medium) == LM_MEDIUM_SELECTIVE_AUTONEG)
2320eef4f27bSRobert Mustacchi {
2321eef4f27bSRobert Mustacchi selective_autoneg = TRUE;
2322eef4f27bSRobert Mustacchi }
2323eef4f27bSRobert Mustacchi
2324eef4f27bSRobert Mustacchi if(GET_MEDIUM_TYPE(req_medium) == LM_MEDIUM_AUTO_DETECT)
2325eef4f27bSRobert Mustacchi {
2326eef4f27bSRobert Mustacchi if(CHIP_REV(pdev) == CHIP_REV_IKOS)
2327eef4f27bSRobert Mustacchi {
2328eef4f27bSRobert Mustacchi req_medium = LM_MEDIUM_TYPE_NULL;
2329eef4f27bSRobert Mustacchi }
2330eef4f27bSRobert Mustacchi else if(CHIP_REV(pdev) == CHIP_REV_FPGA)
2331eef4f27bSRobert Mustacchi {
2332eef4f27bSRobert Mustacchi selective_autoneg = TRUE;
2333eef4f27bSRobert Mustacchi req_medium = LM_MEDIUM_TYPE_UTP |
2334eef4f27bSRobert Mustacchi LM_MEDIUM_SPEED_10MBPS |
2335eef4f27bSRobert Mustacchi LM_MEDIUM_FULL_DUPLEX;
2336eef4f27bSRobert Mustacchi }
2337eef4f27bSRobert Mustacchi else if(lm_get_medium(pdev) == LM_MEDIUM_TYPE_FIBER)
2338eef4f27bSRobert Mustacchi {
2339eef4f27bSRobert Mustacchi if(req_medium == LM_MEDIUM_AUTO_DETECT)
2340eef4f27bSRobert Mustacchi {
2341eef4f27bSRobert Mustacchi req_medium = LM_MEDIUM_TYPE_FIBER;
2342eef4f27bSRobert Mustacchi }
2343eef4f27bSRobert Mustacchi else
2344eef4f27bSRobert Mustacchi {
2345eef4f27bSRobert Mustacchi SET_MEDIUM_TYPE(req_medium, LM_MEDIUM_TYPE_FIBER);
2346eef4f27bSRobert Mustacchi }
2347eef4f27bSRobert Mustacchi }
2348eef4f27bSRobert Mustacchi else
2349eef4f27bSRobert Mustacchi {
2350eef4f27bSRobert Mustacchi if(req_medium == LM_MEDIUM_AUTO_DETECT)
2351eef4f27bSRobert Mustacchi {
2352eef4f27bSRobert Mustacchi req_medium = LM_MEDIUM_TYPE_UTP;
2353eef4f27bSRobert Mustacchi }
2354eef4f27bSRobert Mustacchi else
2355eef4f27bSRobert Mustacchi {
2356eef4f27bSRobert Mustacchi SET_MEDIUM_TYPE(req_medium, LM_MEDIUM_TYPE_UTP);
2357eef4f27bSRobert Mustacchi }
2358eef4f27bSRobert Mustacchi }
2359eef4f27bSRobert Mustacchi }
2360eef4f27bSRobert Mustacchi
2361eef4f27bSRobert Mustacchi switch(GET_MEDIUM_TYPE(req_medium))
2362eef4f27bSRobert Mustacchi {
2363eef4f27bSRobert Mustacchi case LM_MEDIUM_TYPE_UTP:
2364eef4f27bSRobert Mustacchi lm_status = init_utp(
2365eef4f27bSRobert Mustacchi pdev,
2366eef4f27bSRobert Mustacchi req_medium,
2367*55fea89dSDan Cross flow_ctrl,
2368eef4f27bSRobert Mustacchi selective_autoneg,
2369eef4f27bSRobert Mustacchi wire_speed,
2370eef4f27bSRobert Mustacchi wait_link_timeout_us);
2371eef4f27bSRobert Mustacchi break;
2372eef4f27bSRobert Mustacchi
2373eef4f27bSRobert Mustacchi case LM_MEDIUM_TYPE_FIBER:
2374eef4f27bSRobert Mustacchi DbgBreakIf(CHIP_NUM(pdev) != CHIP_NUM_5706 &&
2375eef4f27bSRobert Mustacchi CHIP_NUM(pdev) != CHIP_NUM_5708 &&
2376eef4f27bSRobert Mustacchi CHIP_NUM(pdev) != CHIP_NUM_5709);
2377eef4f27bSRobert Mustacchi
2378eef4f27bSRobert Mustacchi if(CHIP_NUM(pdev) == CHIP_NUM_5706)
2379eef4f27bSRobert Mustacchi {
2380eef4f27bSRobert Mustacchi lm_status = init_5706_serdes(
2381eef4f27bSRobert Mustacchi pdev,
2382eef4f27bSRobert Mustacchi req_medium,
2383eef4f27bSRobert Mustacchi flow_ctrl,
2384eef4f27bSRobert Mustacchi wait_link_timeout_us);
2385eef4f27bSRobert Mustacchi }
2386eef4f27bSRobert Mustacchi else if(CHIP_NUM(pdev) == CHIP_NUM_5708)
2387eef4f27bSRobert Mustacchi {
2388eef4f27bSRobert Mustacchi lm_status = init_5708_serdes(
2389eef4f27bSRobert Mustacchi pdev,
2390eef4f27bSRobert Mustacchi req_medium,
2391eef4f27bSRobert Mustacchi flow_ctrl,
2392eef4f27bSRobert Mustacchi selective_autoneg,
2393eef4f27bSRobert Mustacchi wait_link_timeout_us);
2394eef4f27bSRobert Mustacchi }
2395eef4f27bSRobert Mustacchi else
2396eef4f27bSRobert Mustacchi {
2397eef4f27bSRobert Mustacchi lm_status = init_5709_serdes(
2398eef4f27bSRobert Mustacchi pdev,
2399eef4f27bSRobert Mustacchi req_medium,
2400eef4f27bSRobert Mustacchi flow_ctrl,
2401eef4f27bSRobert Mustacchi selective_autoneg,
2402eef4f27bSRobert Mustacchi wait_link_timeout_us);
2403eef4f27bSRobert Mustacchi }
2404eef4f27bSRobert Mustacchi
2405eef4f27bSRobert Mustacchi break;
2406eef4f27bSRobert Mustacchi
2407eef4f27bSRobert Mustacchi case LM_MEDIUM_TYPE_NULL:
2408eef4f27bSRobert Mustacchi lm_status = init_null_phy(
2409eef4f27bSRobert Mustacchi pdev,
2410eef4f27bSRobert Mustacchi req_medium,
2411eef4f27bSRobert Mustacchi flow_ctrl,
2412eef4f27bSRobert Mustacchi wait_link_timeout_us);
2413eef4f27bSRobert Mustacchi break;
2414eef4f27bSRobert Mustacchi
2415eef4f27bSRobert Mustacchi case LM_MEDIUM_TYPE_PHY_LOOPBACK:
2416eef4f27bSRobert Mustacchi case LM_MEDIUM_TYPE_MAC_LOOPBACK:
2417eef4f27bSRobert Mustacchi lm_status = init_loopback_mac_link(
2418eef4f27bSRobert Mustacchi pdev,
2419eef4f27bSRobert Mustacchi req_medium,
2420eef4f27bSRobert Mustacchi flow_ctrl);
2421eef4f27bSRobert Mustacchi break;
2422eef4f27bSRobert Mustacchi
2423eef4f27bSRobert Mustacchi default:
2424eef4f27bSRobert Mustacchi lm_status = LM_STATUS_UNKNOWN_MEDIUM;
2425eef4f27bSRobert Mustacchi break;
2426eef4f27bSRobert Mustacchi }
2427eef4f27bSRobert Mustacchi
2428eef4f27bSRobert Mustacchi return lm_status;
2429eef4f27bSRobert Mustacchi } /* lm_init_phy */
2430eef4f27bSRobert Mustacchi
2431eef4f27bSRobert Mustacchi
2432eef4f27bSRobert Mustacchi
2433eef4f27bSRobert Mustacchi /*******************************************************************************
2434eef4f27bSRobert Mustacchi * Description:
2435eef4f27bSRobert Mustacchi *
2436eef4f27bSRobert Mustacchi * Return:
2437eef4f27bSRobert Mustacchi ******************************************************************************/
2438eef4f27bSRobert Mustacchi STATIC void
get_serdes_phy_ad(lm_device_t * pdev,u32_t * local_phy_ad,u32_t * remote_phy_ad)2439eef4f27bSRobert Mustacchi get_serdes_phy_ad(
2440eef4f27bSRobert Mustacchi lm_device_t *pdev,
2441eef4f27bSRobert Mustacchi u32_t *local_phy_ad,
2442eef4f27bSRobert Mustacchi u32_t *remote_phy_ad)
2443eef4f27bSRobert Mustacchi {
2444eef4f27bSRobert Mustacchi u32_t val;
2445eef4f27bSRobert Mustacchi
2446eef4f27bSRobert Mustacchi *local_phy_ad = 0;
2447eef4f27bSRobert Mustacchi *remote_phy_ad = 0;
2448eef4f27bSRobert Mustacchi
2449eef4f27bSRobert Mustacchi if(CHIP_NUM(pdev) == CHIP_NUM_5706 || CHIP_NUM(pdev) == CHIP_NUM_5708)
2450eef4f27bSRobert Mustacchi {
2451eef4f27bSRobert Mustacchi (void) lm_mread(pdev, pdev->params.phy_addr, PHY_AN_AD_REG, &val);
2452eef4f27bSRobert Mustacchi
2453eef4f27bSRobert Mustacchi if(val & PHY_AN_AD_1000X_PAUSE_CAPABLE)
2454eef4f27bSRobert Mustacchi {
2455eef4f27bSRobert Mustacchi *local_phy_ad |= PHY_AN_AD_PAUSE_CAPABLE;
2456eef4f27bSRobert Mustacchi }
2457eef4f27bSRobert Mustacchi
2458eef4f27bSRobert Mustacchi if(val & PHY_AN_AD_1000X_ASYM_PAUSE)
2459eef4f27bSRobert Mustacchi {
2460eef4f27bSRobert Mustacchi *local_phy_ad |= PHY_AN_AD_ASYM_PAUSE;
2461eef4f27bSRobert Mustacchi }
2462eef4f27bSRobert Mustacchi
2463eef4f27bSRobert Mustacchi (void) lm_mread(pdev,pdev->params.phy_addr,PHY_LINK_PARTNER_ABILITY_REG,&val);
2464eef4f27bSRobert Mustacchi
2465eef4f27bSRobert Mustacchi if(val & PHY_AN_AD_1000X_PAUSE_CAPABLE)
2466eef4f27bSRobert Mustacchi {
2467eef4f27bSRobert Mustacchi *remote_phy_ad |= PHY_AN_AD_PAUSE_CAPABLE;
2468eef4f27bSRobert Mustacchi }
2469eef4f27bSRobert Mustacchi
2470eef4f27bSRobert Mustacchi if(val & PHY_AN_AD_1000X_ASYM_PAUSE)
2471eef4f27bSRobert Mustacchi {
2472eef4f27bSRobert Mustacchi *remote_phy_ad |= PHY_AN_AD_ASYM_PAUSE;
2473eef4f27bSRobert Mustacchi }
2474eef4f27bSRobert Mustacchi }
2475eef4f27bSRobert Mustacchi else
2476eef4f27bSRobert Mustacchi {
2477eef4f27bSRobert Mustacchi /* select combo ieee0 block. */
2478eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1f, 0xffe0);
2479eef4f27bSRobert Mustacchi
2480eef4f27bSRobert Mustacchi /* local advertisement. */
2481eef4f27bSRobert Mustacchi (void) lm_mread(pdev, pdev->params.phy_addr, 0x14, &val);
2482eef4f27bSRobert Mustacchi
2483eef4f27bSRobert Mustacchi if(val & 0x80)
2484eef4f27bSRobert Mustacchi {
2485eef4f27bSRobert Mustacchi *local_phy_ad |= PHY_AN_AD_PAUSE_CAPABLE;
2486eef4f27bSRobert Mustacchi }
2487eef4f27bSRobert Mustacchi
2488eef4f27bSRobert Mustacchi if(val & 0x100)
2489eef4f27bSRobert Mustacchi {
2490eef4f27bSRobert Mustacchi *local_phy_ad |= PHY_AN_AD_ASYM_PAUSE;
2491eef4f27bSRobert Mustacchi }
2492eef4f27bSRobert Mustacchi
2493eef4f27bSRobert Mustacchi /* remote advertisement. */
2494eef4f27bSRobert Mustacchi (void) lm_mread(pdev, pdev->params.phy_addr, 0x15, &val);
2495eef4f27bSRobert Mustacchi
2496eef4f27bSRobert Mustacchi if(val & 0x80)
2497eef4f27bSRobert Mustacchi {
2498eef4f27bSRobert Mustacchi *remote_phy_ad |= PHY_AN_AD_PAUSE_CAPABLE;
2499eef4f27bSRobert Mustacchi }
2500eef4f27bSRobert Mustacchi
2501eef4f27bSRobert Mustacchi if(val & 0x100)
2502eef4f27bSRobert Mustacchi {
2503eef4f27bSRobert Mustacchi *remote_phy_ad |= PHY_AN_AD_ASYM_PAUSE;
2504eef4f27bSRobert Mustacchi }
2505eef4f27bSRobert Mustacchi }
2506eef4f27bSRobert Mustacchi } /* get_serdes_phy_ad */
2507eef4f27bSRobert Mustacchi
2508eef4f27bSRobert Mustacchi
2509eef4f27bSRobert Mustacchi
2510eef4f27bSRobert Mustacchi /*******************************************************************************
2511eef4f27bSRobert Mustacchi * Description:
2512eef4f27bSRobert Mustacchi *
2513eef4f27bSRobert Mustacchi * Return:
2514eef4f27bSRobert Mustacchi ******************************************************************************/
2515eef4f27bSRobert Mustacchi STATIC lm_flow_control_t
set_mac_flow_control(lm_device_t * pdev,lm_medium_t medium,lm_flow_control_t flow_control_cap)2516eef4f27bSRobert Mustacchi set_mac_flow_control(
2517eef4f27bSRobert Mustacchi lm_device_t *pdev,
2518eef4f27bSRobert Mustacchi lm_medium_t medium,
2519eef4f27bSRobert Mustacchi lm_flow_control_t flow_control_cap)
2520eef4f27bSRobert Mustacchi {
2521eef4f27bSRobert Mustacchi lm_flow_control_t flow_ctrl;
2522eef4f27bSRobert Mustacchi u32_t remote_phy_link;
2523eef4f27bSRobert Mustacchi u32_t remote_phy_ad;
2524eef4f27bSRobert Mustacchi u32_t local_phy_ad;
2525eef4f27bSRobert Mustacchi u32_t val;
2526eef4f27bSRobert Mustacchi lm_rx_chain_t *rxq;
2527eef4f27bSRobert Mustacchi u32_t idx;
2528eef4f27bSRobert Mustacchi
2529eef4f27bSRobert Mustacchi if(pdev->params.enable_remote_phy)
2530eef4f27bSRobert Mustacchi {
2531eef4f27bSRobert Mustacchi local_phy_ad = 0;
2532eef4f27bSRobert Mustacchi
2533eef4f27bSRobert Mustacchi if((flow_control_cap == LM_FLOW_CONTROL_AUTO_PAUSE) ||
2534eef4f27bSRobert Mustacchi ((flow_control_cap & LM_FLOW_CONTROL_RECEIVE_PAUSE) &&
2535eef4f27bSRobert Mustacchi (flow_control_cap & LM_FLOW_CONTROL_TRANSMIT_PAUSE)) ||
2536eef4f27bSRobert Mustacchi (flow_control_cap & LM_FLOW_CONTROL_RECEIVE_PAUSE))
2537eef4f27bSRobert Mustacchi {
2538eef4f27bSRobert Mustacchi local_phy_ad |= (PHY_AN_AD_PAUSE_CAPABLE | PHY_AN_AD_ASYM_PAUSE);
2539eef4f27bSRobert Mustacchi }
2540eef4f27bSRobert Mustacchi else if(flow_control_cap & LM_FLOW_CONTROL_TRANSMIT_PAUSE)
2541eef4f27bSRobert Mustacchi {
2542eef4f27bSRobert Mustacchi local_phy_ad |= PHY_AN_AD_ASYM_PAUSE;
2543eef4f27bSRobert Mustacchi }
2544eef4f27bSRobert Mustacchi
2545eef4f27bSRobert Mustacchi remote_phy_ad = 0;
2546eef4f27bSRobert Mustacchi
2547eef4f27bSRobert Mustacchi REG_RD_IND(
2548eef4f27bSRobert Mustacchi pdev,
2549eef4f27bSRobert Mustacchi pdev->hw_info.shmem_base +
2550eef4f27bSRobert Mustacchi OFFSETOF(shmem_region_t, drv_fw_mb.link_status),
2551eef4f27bSRobert Mustacchi &remote_phy_link);
2552eef4f27bSRobert Mustacchi
2553eef4f27bSRobert Mustacchi if(remote_phy_link & NETLINK_GET_LINK_STATUS_PARTNER_SYM_PAUSE_CAP)
2554eef4f27bSRobert Mustacchi {
2555eef4f27bSRobert Mustacchi remote_phy_ad |= PHY_LINK_PARTNER_PAUSE_CAPABLE;
2556eef4f27bSRobert Mustacchi }
2557eef4f27bSRobert Mustacchi
2558eef4f27bSRobert Mustacchi if(remote_phy_link & NETLINK_GET_LINK_STATUS_PARTNER_ASYM_PAUSE_CAP)
2559eef4f27bSRobert Mustacchi {
2560eef4f27bSRobert Mustacchi remote_phy_ad |= PHY_LINK_PARTNER_ASYM_PAUSE;
2561eef4f27bSRobert Mustacchi }
2562eef4f27bSRobert Mustacchi }
2563eef4f27bSRobert Mustacchi else
2564eef4f27bSRobert Mustacchi {
2565eef4f27bSRobert Mustacchi if(GET_MEDIUM_TYPE(medium) == LM_MEDIUM_TYPE_FIBER)
2566eef4f27bSRobert Mustacchi {
2567eef4f27bSRobert Mustacchi get_serdes_phy_ad(pdev, &local_phy_ad, &remote_phy_ad);
2568eef4f27bSRobert Mustacchi }
2569eef4f27bSRobert Mustacchi else
2570eef4f27bSRobert Mustacchi {
2571eef4f27bSRobert Mustacchi (void) lm_mread(
2572*55fea89dSDan Cross pdev,
2573*55fea89dSDan Cross pdev->params.phy_addr,
2574*55fea89dSDan Cross PHY_AN_AD_REG,
2575eef4f27bSRobert Mustacchi &local_phy_ad);
2576eef4f27bSRobert Mustacchi
2577eef4f27bSRobert Mustacchi (void) lm_mread(
2578*55fea89dSDan Cross pdev,
2579*55fea89dSDan Cross pdev->params.phy_addr,
2580*55fea89dSDan Cross PHY_LINK_PARTNER_ABILITY_REG,
2581eef4f27bSRobert Mustacchi &remote_phy_ad);
2582eef4f27bSRobert Mustacchi }
2583eef4f27bSRobert Mustacchi }
2584eef4f27bSRobert Mustacchi
2585eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, "Local flow control settings.\n");
2586eef4f27bSRobert Mustacchi
2587eef4f27bSRobert Mustacchi if(local_phy_ad & PHY_AN_AD_PAUSE_CAPABLE)
2588eef4f27bSRobert Mustacchi {
2589eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, " PAUSE capable.\n");
2590eef4f27bSRobert Mustacchi }
2591eef4f27bSRobert Mustacchi
2592eef4f27bSRobert Mustacchi if(local_phy_ad & PHY_AN_AD_ASYM_PAUSE)
2593eef4f27bSRobert Mustacchi {
2594eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, " ASYM_PAUSE capable.\n");
2595eef4f27bSRobert Mustacchi }
2596*55fea89dSDan Cross
2597eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, "Remote flow control settings.\n");
2598eef4f27bSRobert Mustacchi
2599eef4f27bSRobert Mustacchi if(remote_phy_ad & PHY_LINK_PARTNER_PAUSE_CAPABLE)
2600eef4f27bSRobert Mustacchi {
2601eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, " PAUSE capable.\n");
2602eef4f27bSRobert Mustacchi }
2603eef4f27bSRobert Mustacchi
2604eef4f27bSRobert Mustacchi if(remote_phy_ad & PHY_LINK_PARTNER_ASYM_PAUSE)
2605eef4f27bSRobert Mustacchi {
2606eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, " ASYM_PAUSE capable.\n");
2607eef4f27bSRobert Mustacchi }
2608eef4f27bSRobert Mustacchi
2609eef4f27bSRobert Mustacchi /* Resultant flow control setting. */
2610eef4f27bSRobert Mustacchi flow_ctrl = LM_FLOW_CONTROL_NONE;
2611eef4f27bSRobert Mustacchi
2612eef4f27bSRobert Mustacchi if((flow_control_cap & LM_FLOW_CONTROL_AUTO_PAUSE) ||
2613eef4f27bSRobert Mustacchi pdev->params.flow_control_reporting_mode)
2614eef4f27bSRobert Mustacchi {
2615eef4f27bSRobert Mustacchi /* See Table 28B-3 of 802.3ab-1999 spec. */
2616eef4f27bSRobert Mustacchi if(local_phy_ad & PHY_AN_AD_PAUSE_CAPABLE)
2617eef4f27bSRobert Mustacchi {
2618eef4f27bSRobert Mustacchi if(local_phy_ad & PHY_AN_AD_ASYM_PAUSE)
2619eef4f27bSRobert Mustacchi {
2620eef4f27bSRobert Mustacchi if(remote_phy_ad & PHY_LINK_PARTNER_PAUSE_CAPABLE)
2621eef4f27bSRobert Mustacchi {
2622eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, "FlowCap: tx/rx\n");
2623eef4f27bSRobert Mustacchi
2624eef4f27bSRobert Mustacchi flow_ctrl =
2625eef4f27bSRobert Mustacchi LM_FLOW_CONTROL_TRANSMIT_PAUSE |
2626eef4f27bSRobert Mustacchi LM_FLOW_CONTROL_RECEIVE_PAUSE;
2627eef4f27bSRobert Mustacchi }
2628eef4f27bSRobert Mustacchi else if(remote_phy_ad & PHY_LINK_PARTNER_ASYM_PAUSE)
2629eef4f27bSRobert Mustacchi {
2630eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, "FlowCap: rx PAUSE\n");
2631eef4f27bSRobert Mustacchi
2632eef4f27bSRobert Mustacchi flow_ctrl = LM_FLOW_CONTROL_RECEIVE_PAUSE;
2633eef4f27bSRobert Mustacchi }
2634eef4f27bSRobert Mustacchi }
2635eef4f27bSRobert Mustacchi else
2636eef4f27bSRobert Mustacchi {
2637eef4f27bSRobert Mustacchi if(remote_phy_ad & PHY_LINK_PARTNER_PAUSE_CAPABLE)
2638eef4f27bSRobert Mustacchi {
2639eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, "FlowCap: tx/rx\n");
2640eef4f27bSRobert Mustacchi
2641eef4f27bSRobert Mustacchi flow_ctrl =
2642eef4f27bSRobert Mustacchi LM_FLOW_CONTROL_TRANSMIT_PAUSE |
2643eef4f27bSRobert Mustacchi LM_FLOW_CONTROL_RECEIVE_PAUSE;
2644eef4f27bSRobert Mustacchi }
2645eef4f27bSRobert Mustacchi }
2646eef4f27bSRobert Mustacchi }
2647eef4f27bSRobert Mustacchi else if(local_phy_ad & PHY_AN_AD_ASYM_PAUSE)
2648eef4f27bSRobert Mustacchi {
2649eef4f27bSRobert Mustacchi if((remote_phy_ad & PHY_LINK_PARTNER_PAUSE_CAPABLE) &&
2650eef4f27bSRobert Mustacchi (remote_phy_ad & PHY_LINK_PARTNER_ASYM_PAUSE))
2651eef4f27bSRobert Mustacchi {
2652eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, "FlowCap: tx PAUSE\n");
2653eef4f27bSRobert Mustacchi
2654eef4f27bSRobert Mustacchi flow_ctrl = LM_FLOW_CONTROL_TRANSMIT_PAUSE;
2655eef4f27bSRobert Mustacchi }
2656eef4f27bSRobert Mustacchi }
2657eef4f27bSRobert Mustacchi }
2658eef4f27bSRobert Mustacchi else
2659eef4f27bSRobert Mustacchi {
2660eef4f27bSRobert Mustacchi flow_ctrl = flow_control_cap;
2661eef4f27bSRobert Mustacchi }
2662eef4f27bSRobert Mustacchi
2663eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, "Flow control capabilities.\n");
2664eef4f27bSRobert Mustacchi
2665eef4f27bSRobert Mustacchi if(flow_ctrl & LM_FLOW_CONTROL_TRANSMIT_PAUSE)
2666eef4f27bSRobert Mustacchi {
2667eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, " tx PAUSE\n");
2668eef4f27bSRobert Mustacchi }
2669eef4f27bSRobert Mustacchi
2670eef4f27bSRobert Mustacchi if(flow_ctrl & LM_FLOW_CONTROL_RECEIVE_PAUSE)
2671eef4f27bSRobert Mustacchi {
2672eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, " rx PAUSE\n");
2673eef4f27bSRobert Mustacchi }
2674eef4f27bSRobert Mustacchi
2675eef4f27bSRobert Mustacchi if(flow_ctrl == LM_FLOW_CONTROL_NONE)
2676eef4f27bSRobert Mustacchi {
2677eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, " none.\n");
2678eef4f27bSRobert Mustacchi }
2679eef4f27bSRobert Mustacchi
2680eef4f27bSRobert Mustacchi /* Enable/disable rx PAUSE. */
2681eef4f27bSRobert Mustacchi REG_RD(pdev, emac.emac_rx_mode, &val);
2682eef4f27bSRobert Mustacchi val &= ~EMAC_RX_MODE_FLOW_EN;
2683eef4f27bSRobert Mustacchi
2684eef4f27bSRobert Mustacchi if(flow_ctrl & LM_FLOW_CONTROL_RECEIVE_PAUSE)
2685eef4f27bSRobert Mustacchi {
2686eef4f27bSRobert Mustacchi val |= EMAC_RX_MODE_FLOW_EN;
2687eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, "Enable rx PAUSE.\n");
2688eef4f27bSRobert Mustacchi }
2689eef4f27bSRobert Mustacchi REG_WR(pdev, emac.emac_rx_mode, val);
2690eef4f27bSRobert Mustacchi
2691eef4f27bSRobert Mustacchi /* Enable/disable tx PAUSE. */
2692eef4f27bSRobert Mustacchi REG_RD(pdev, emac.emac_tx_mode, &val);
2693eef4f27bSRobert Mustacchi val &= ~EMAC_TX_MODE_FLOW_EN;
2694eef4f27bSRobert Mustacchi
2695eef4f27bSRobert Mustacchi if(flow_ctrl & LM_FLOW_CONTROL_TRANSMIT_PAUSE)
2696eef4f27bSRobert Mustacchi {
2697eef4f27bSRobert Mustacchi val |= EMAC_TX_MODE_FLOW_EN;
2698eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, "Enable tx PAUSE.\n");
2699eef4f27bSRobert Mustacchi }
2700eef4f27bSRobert Mustacchi REG_WR(pdev, emac.emac_tx_mode, val);
2701eef4f27bSRobert Mustacchi
2702eef4f27bSRobert Mustacchi for(idx = 0; idx < pdev->rx_info.num_rxq; idx++)
2703eef4f27bSRobert Mustacchi {
2704eef4f27bSRobert Mustacchi rxq = &pdev->rx_info.chain[idx];
2705eef4f27bSRobert Mustacchi val = CTX_RD(
2706eef4f27bSRobert Mustacchi pdev,
2707eef4f27bSRobert Mustacchi rxq->cid_addr,
2708eef4f27bSRobert Mustacchi WORD_ALIGNED_OFFSETOF(l2_bd_chain_context_t, l2ctx_ctx_type));
2709eef4f27bSRobert Mustacchi
2710eef4f27bSRobert Mustacchi /* Enable/disable RV2P wait (i.e. watermark field) for buffer post based on flow control setting. */
2711eef4f27bSRobert Mustacchi if(flow_ctrl & LM_FLOW_CONTROL_TRANSMIT_PAUSE)
2712eef4f27bSRobert Mustacchi {
2713eef4f27bSRobert Mustacchi val |= 0xFF;
2714eef4f27bSRobert Mustacchi }
2715eef4f27bSRobert Mustacchi else
2716eef4f27bSRobert Mustacchi {
2717eef4f27bSRobert Mustacchi // RV2P is checking for non-zero in this byte field
2718*55fea89dSDan Cross val &= ~0xFF;
2719eef4f27bSRobert Mustacchi }
2720eef4f27bSRobert Mustacchi CTX_WR(
2721eef4f27bSRobert Mustacchi pdev,
2722eef4f27bSRobert Mustacchi rxq->cid_addr,
2723eef4f27bSRobert Mustacchi WORD_ALIGNED_OFFSETOF(l2_bd_chain_context_t, l2ctx_ctx_type),
2724eef4f27bSRobert Mustacchi val);
2725eef4f27bSRobert Mustacchi }
2726eef4f27bSRobert Mustacchi
2727eef4f27bSRobert Mustacchi return flow_ctrl;
2728eef4f27bSRobert Mustacchi } /* set_mac_flow_control */
2729eef4f27bSRobert Mustacchi
2730eef4f27bSRobert Mustacchi
2731eef4f27bSRobert Mustacchi
2732eef4f27bSRobert Mustacchi /*******************************************************************************
2733eef4f27bSRobert Mustacchi * Description:
2734eef4f27bSRobert Mustacchi *
2735eef4f27bSRobert Mustacchi * Return:
2736eef4f27bSRobert Mustacchi ******************************************************************************/
2737eef4f27bSRobert Mustacchi STATIC lm_status_t
get_copper_phy_link(lm_device_t * pdev,lm_medium_t * medium)2738eef4f27bSRobert Mustacchi get_copper_phy_link(
2739eef4f27bSRobert Mustacchi lm_device_t *pdev,
2740eef4f27bSRobert Mustacchi lm_medium_t *medium)
2741eef4f27bSRobert Mustacchi {
2742eef4f27bSRobert Mustacchi lm_medium_t duplex;
2743eef4f27bSRobert Mustacchi lm_medium_t speed;
2744eef4f27bSRobert Mustacchi lm_status_t link;
2745eef4f27bSRobert Mustacchi u32_t phy_status;
2746eef4f27bSRobert Mustacchi u32_t remote_adv;
2747eef4f27bSRobert Mustacchi u32_t local_adv;
2748eef4f27bSRobert Mustacchi u32_t phy_ctrl;
2749eef4f27bSRobert Mustacchi u32_t val;
2750eef4f27bSRobert Mustacchi
2751eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, "### get_copper_phy_link\n");
2752eef4f27bSRobert Mustacchi
2753eef4f27bSRobert Mustacchi *medium = LM_MEDIUM_TYPE_UTP |
2754eef4f27bSRobert Mustacchi LM_MEDIUM_SPEED_UNKNOWN |
2755eef4f27bSRobert Mustacchi LM_MEDIUM_FULL_DUPLEX;
2756eef4f27bSRobert Mustacchi
2757eef4f27bSRobert Mustacchi pdev->vars.cable_is_attached = FALSE;
2758eef4f27bSRobert Mustacchi
2759eef4f27bSRobert Mustacchi /* Check for link. The first read returns the latched value, the
2760eef4f27bSRobert Mustacchi * second read returns the current value. */
2761eef4f27bSRobert Mustacchi (void) lm_mread(pdev, pdev->params.phy_addr, PHY_STATUS_REG, &phy_status);
2762eef4f27bSRobert Mustacchi (void) lm_mread(pdev, pdev->params.phy_addr, PHY_STATUS_REG, &phy_status);
2763eef4f27bSRobert Mustacchi if((phy_status & PHY_STATUS_LINK_PASS) == 0)
2764eef4f27bSRobert Mustacchi {
2765eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, "link down.\n");
2766eef4f27bSRobert Mustacchi
2767eef4f27bSRobert Mustacchi if(CHIP_REV(pdev) != CHIP_REV_FPGA)
2768eef4f27bSRobert Mustacchi {
2769eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1c, 0x7c00);
2770eef4f27bSRobert Mustacchi (void) lm_mread(pdev, pdev->params.phy_addr, 0x1c, &val);
2771eef4f27bSRobert Mustacchi if(val & 0x20)
2772eef4f27bSRobert Mustacchi {
2773eef4f27bSRobert Mustacchi pdev->vars.cable_is_attached = TRUE;
2774eef4f27bSRobert Mustacchi }
2775eef4f27bSRobert Mustacchi }
2776eef4f27bSRobert Mustacchi
2777eef4f27bSRobert Mustacchi return LM_STATUS_LINK_DOWN;
2778eef4f27bSRobert Mustacchi }
2779eef4f27bSRobert Mustacchi
2780eef4f27bSRobert Mustacchi (void) lm_mread(pdev, pdev->params.phy_addr, PHY_CTRL_REG, &phy_ctrl);
2781eef4f27bSRobert Mustacchi
2782eef4f27bSRobert Mustacchi /* Make sure the PHY control register is valid. */
2783eef4f27bSRobert Mustacchi DbgBreakIf(phy_ctrl & (
2784eef4f27bSRobert Mustacchi PHY_CTRL_COLLISION_TEST_ENABLE |
2785eef4f27bSRobert Mustacchi PHY_CTRL_RESTART_AUTO_NEG |
2786eef4f27bSRobert Mustacchi PHY_CTRL_ISOLATE_PHY |
2787eef4f27bSRobert Mustacchi PHY_CTRL_LOOPBACK_MODE |
2788eef4f27bSRobert Mustacchi PHY_CTRL_PHY_RESET));
2789eef4f27bSRobert Mustacchi
2790eef4f27bSRobert Mustacchi link = LM_STATUS_LINK_ACTIVE;
2791eef4f27bSRobert Mustacchi pdev->vars.cable_is_attached = TRUE;
2792eef4f27bSRobert Mustacchi
2793eef4f27bSRobert Mustacchi /* Determine duplex mode. Link is present also means autoneg is done. */
2794eef4f27bSRobert Mustacchi if(phy_ctrl & PHY_CTRL_AUTO_NEG_ENABLE)
2795eef4f27bSRobert Mustacchi {
2796eef4f27bSRobert Mustacchi /* Autonegotiation is enabled. And since we have link, we know
2797eef4f27bSRobert Mustacchi * autonegotiation has completed.
2798eef4f27bSRobert Mustacchi *
2799eef4f27bSRobert Mustacchi * Infer the link speed by figuring out the highest common speed
2800eef4f27bSRobert Mustacchi * between us and our link partner. */
2801eef4f27bSRobert Mustacchi
2802eef4f27bSRobert Mustacchi /* Get local and remote 1000BASET advertisement. */
2803eef4f27bSRobert Mustacchi (void) lm_mread(
2804*55fea89dSDan Cross pdev,
2805*55fea89dSDan Cross pdev->params.phy_addr,
2806*55fea89dSDan Cross PHY_1000BASET_CTRL_REG,
2807eef4f27bSRobert Mustacchi &local_adv);
2808eef4f27bSRobert Mustacchi (void) lm_mread(
2809*55fea89dSDan Cross pdev,
2810*55fea89dSDan Cross pdev->params.phy_addr,
2811*55fea89dSDan Cross PHY_1000BASET_STATUS_REG,
2812eef4f27bSRobert Mustacchi &remote_adv);
2813eef4f27bSRobert Mustacchi
2814eef4f27bSRobert Mustacchi val = local_adv & (remote_adv >> 2);
2815eef4f27bSRobert Mustacchi if(val & PHY_AN_AD_1000BASET_FULL)
2816eef4f27bSRobert Mustacchi {
2817eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, "detected 1gb full autoneg.\n");
2818eef4f27bSRobert Mustacchi
2819eef4f27bSRobert Mustacchi speed = LM_MEDIUM_SPEED_1000MBPS;
2820eef4f27bSRobert Mustacchi duplex = LM_MEDIUM_FULL_DUPLEX;
2821eef4f27bSRobert Mustacchi }
2822eef4f27bSRobert Mustacchi else if(val & PHY_AN_AD_1000BASET_HALF)
2823eef4f27bSRobert Mustacchi {
2824eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, "detected 1gb half autoneg.\n");
2825eef4f27bSRobert Mustacchi
2826eef4f27bSRobert Mustacchi speed = LM_MEDIUM_SPEED_1000MBPS;
2827eef4f27bSRobert Mustacchi duplex = LM_MEDIUM_HALF_DUPLEX;
2828eef4f27bSRobert Mustacchi }
2829eef4f27bSRobert Mustacchi else
2830eef4f27bSRobert Mustacchi {
2831eef4f27bSRobert Mustacchi /* Get local and remote 10/100 mb advertisement. */
2832eef4f27bSRobert Mustacchi (void) lm_mread(
2833*55fea89dSDan Cross pdev,
2834*55fea89dSDan Cross pdev->params.phy_addr,
2835*55fea89dSDan Cross PHY_AN_AD_REG,
2836eef4f27bSRobert Mustacchi &local_adv);
2837eef4f27bSRobert Mustacchi
2838eef4f27bSRobert Mustacchi (void) lm_mread(
2839*55fea89dSDan Cross pdev,
2840*55fea89dSDan Cross pdev->params.phy_addr,
2841*55fea89dSDan Cross PHY_LINK_PARTNER_ABILITY_REG,
2842eef4f27bSRobert Mustacchi &remote_adv);
2843eef4f27bSRobert Mustacchi
2844eef4f27bSRobert Mustacchi val = local_adv & remote_adv;
2845eef4f27bSRobert Mustacchi if(val & PHY_AN_AD_100BASETX_FULL)
2846eef4f27bSRobert Mustacchi {
2847eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, "detected 100mb full autoneg.\n");
2848eef4f27bSRobert Mustacchi
2849eef4f27bSRobert Mustacchi speed = LM_MEDIUM_SPEED_100MBPS;
2850eef4f27bSRobert Mustacchi duplex = LM_MEDIUM_FULL_DUPLEX;
2851eef4f27bSRobert Mustacchi }
2852eef4f27bSRobert Mustacchi else if(val & PHY_AN_AD_100BASETX_HALF)
2853eef4f27bSRobert Mustacchi {
2854eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, "detected 100mb half autoneg.\n");
2855eef4f27bSRobert Mustacchi
2856eef4f27bSRobert Mustacchi speed = LM_MEDIUM_SPEED_100MBPS;
2857eef4f27bSRobert Mustacchi duplex = LM_MEDIUM_HALF_DUPLEX;
2858eef4f27bSRobert Mustacchi }
2859eef4f27bSRobert Mustacchi else if(val & PHY_AN_AD_10BASET_FULL)
2860eef4f27bSRobert Mustacchi {
2861eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, "detected 10mb full autoneg.\n");
2862eef4f27bSRobert Mustacchi
2863eef4f27bSRobert Mustacchi speed = LM_MEDIUM_SPEED_10MBPS;
2864eef4f27bSRobert Mustacchi duplex = LM_MEDIUM_FULL_DUPLEX;
2865eef4f27bSRobert Mustacchi }
2866eef4f27bSRobert Mustacchi else if(val & PHY_AN_AD_10BASET_HALF)
2867eef4f27bSRobert Mustacchi {
2868eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, "detected 10mb half autoneg.\n");
2869eef4f27bSRobert Mustacchi
2870eef4f27bSRobert Mustacchi speed = LM_MEDIUM_SPEED_10MBPS;
2871eef4f27bSRobert Mustacchi duplex = LM_MEDIUM_HALF_DUPLEX;
2872eef4f27bSRobert Mustacchi }
2873eef4f27bSRobert Mustacchi else
2874eef4f27bSRobert Mustacchi {
2875eef4f27bSRobert Mustacchi DbgBreakMsg("unable to determine autoneg speed.\n");
2876eef4f27bSRobert Mustacchi
2877eef4f27bSRobert Mustacchi speed = LM_MEDIUM_SPEED_UNKNOWN;
2878eef4f27bSRobert Mustacchi duplex = LM_MEDIUM_FULL_DUPLEX;
2879eef4f27bSRobert Mustacchi link = LM_STATUS_LINK_DOWN;
2880eef4f27bSRobert Mustacchi }
2881eef4f27bSRobert Mustacchi }
2882eef4f27bSRobert Mustacchi }
2883eef4f27bSRobert Mustacchi else
2884eef4f27bSRobert Mustacchi {
2885eef4f27bSRobert Mustacchi /* The link speed speed and duplex mode are forced. Get the forced
2886eef4f27bSRobert Mustacchi * line settings from the PHY control register. */
2887eef4f27bSRobert Mustacchi if(phy_ctrl & PHY_CTRL_SPEED_SELECT_100MBPS)
2888eef4f27bSRobert Mustacchi {
2889eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, "PHY forced to 100mb.\n");
2890eef4f27bSRobert Mustacchi speed = LM_MEDIUM_SPEED_100MBPS;
2891eef4f27bSRobert Mustacchi }
2892eef4f27bSRobert Mustacchi else if(phy_ctrl & PHY_CTRL_SPEED_SELECT_1000MBPS)
2893eef4f27bSRobert Mustacchi {
2894eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, "PHY forced to 1gb.\n");
2895eef4f27bSRobert Mustacchi
2896eef4f27bSRobert Mustacchi speed = LM_MEDIUM_SPEED_1000MBPS;
2897eef4f27bSRobert Mustacchi }
2898eef4f27bSRobert Mustacchi else
2899eef4f27bSRobert Mustacchi {
2900eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, "PHY forced to 10mb.\n");
2901eef4f27bSRobert Mustacchi
2902eef4f27bSRobert Mustacchi speed = LM_MEDIUM_SPEED_10MBPS;
2903eef4f27bSRobert Mustacchi }
2904eef4f27bSRobert Mustacchi
2905eef4f27bSRobert Mustacchi if(phy_ctrl & PHY_CTRL_FULL_DUPLEX_MODE)
2906eef4f27bSRobert Mustacchi {
2907eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, "PHY forced to full duplex.\n");
2908eef4f27bSRobert Mustacchi
2909eef4f27bSRobert Mustacchi duplex = LM_MEDIUM_FULL_DUPLEX;
2910eef4f27bSRobert Mustacchi }
2911eef4f27bSRobert Mustacchi else
2912eef4f27bSRobert Mustacchi {
2913eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, "PHY forced to half duplex.\n");
2914eef4f27bSRobert Mustacchi
2915eef4f27bSRobert Mustacchi duplex = LM_MEDIUM_HALF_DUPLEX;
2916eef4f27bSRobert Mustacchi }
2917eef4f27bSRobert Mustacchi }
2918eef4f27bSRobert Mustacchi
2919eef4f27bSRobert Mustacchi *medium = LM_MEDIUM_TYPE_UTP | speed | duplex;
2920eef4f27bSRobert Mustacchi
2921eef4f27bSRobert Mustacchi return link;
2922eef4f27bSRobert Mustacchi } /* get_copper_phy_link */
2923eef4f27bSRobert Mustacchi
2924eef4f27bSRobert Mustacchi
2925eef4f27bSRobert Mustacchi
2926eef4f27bSRobert Mustacchi /*******************************************************************************
2927eef4f27bSRobert Mustacchi * Description:
2928eef4f27bSRobert Mustacchi *
2929eef4f27bSRobert Mustacchi * Return:
2930eef4f27bSRobert Mustacchi ******************************************************************************/
2931eef4f27bSRobert Mustacchi STATIC void
init_mac_link(lm_device_t * pdev,lm_status_t link,lm_medium_t medium,lm_flow_control_t flow_ctrl)2932eef4f27bSRobert Mustacchi init_mac_link(
2933eef4f27bSRobert Mustacchi lm_device_t *pdev,
2934eef4f27bSRobert Mustacchi lm_status_t link,
2935eef4f27bSRobert Mustacchi lm_medium_t medium,
2936eef4f27bSRobert Mustacchi lm_flow_control_t flow_ctrl)
2937eef4f27bSRobert Mustacchi {
2938eef4f27bSRobert Mustacchi u32_t val;
2939eef4f27bSRobert Mustacchi
2940eef4f27bSRobert Mustacchi /* Configure slot time, IPG, and 802.3 flow control. */
2941eef4f27bSRobert Mustacchi REG_WR(pdev, emac.emac_tx_lengths, 0x2620);
2942eef4f27bSRobert Mustacchi if(link == LM_STATUS_LINK_ACTIVE)
2943eef4f27bSRobert Mustacchi {
2944eef4f27bSRobert Mustacchi if(GET_MEDIUM_SPEED(medium) == LM_MEDIUM_SPEED_1000MBPS &&
2945eef4f27bSRobert Mustacchi GET_MEDIUM_DUPLEX(medium) == LM_MEDIUM_HALF_DUPLEX)
2946eef4f27bSRobert Mustacchi {
2947eef4f27bSRobert Mustacchi REG_WR(pdev, emac.emac_tx_lengths, 0x26ff);
2948eef4f27bSRobert Mustacchi }
2949eef4f27bSRobert Mustacchi
2950eef4f27bSRobert Mustacchi pdev->vars.flow_control = set_mac_flow_control(pdev, medium, flow_ctrl);
2951eef4f27bSRobert Mustacchi }
2952eef4f27bSRobert Mustacchi
2953eef4f27bSRobert Mustacchi /* Configure the EMAC mode register. */
2954eef4f27bSRobert Mustacchi REG_RD(pdev, emac.emac_mode, &val);
2955eef4f27bSRobert Mustacchi
2956eef4f27bSRobert Mustacchi val &= ~(EMAC_MODE_PORT | EMAC_MODE_FORCE_LINK);
2957eef4f27bSRobert Mustacchi
2958eef4f27bSRobert Mustacchi if(link == LM_STATUS_LINK_ACTIVE)
2959eef4f27bSRobert Mustacchi {
2960eef4f27bSRobert Mustacchi if(GET_MEDIUM_SPEED(medium) == LM_MEDIUM_SPEED_10MBPS)
2961eef4f27bSRobert Mustacchi {
2962eef4f27bSRobert Mustacchi if(CHIP_NUM(pdev) == CHIP_NUM_5706)
2963eef4f27bSRobert Mustacchi {
2964eef4f27bSRobert Mustacchi val |= EMAC_MODE_PORT_MII;
2965eef4f27bSRobert Mustacchi }
2966eef4f27bSRobert Mustacchi else
2967eef4f27bSRobert Mustacchi {
2968eef4f27bSRobert Mustacchi /* 5708 setting. */
2969eef4f27bSRobert Mustacchi val |= EMAC_MODE_PORT_MII_10M;
2970eef4f27bSRobert Mustacchi }
2971eef4f27bSRobert Mustacchi }
2972eef4f27bSRobert Mustacchi else if(GET_MEDIUM_SPEED(medium) == LM_MEDIUM_SPEED_100MBPS)
2973eef4f27bSRobert Mustacchi {
2974eef4f27bSRobert Mustacchi val |= EMAC_MODE_PORT_MII;
2975eef4f27bSRobert Mustacchi }
2976eef4f27bSRobert Mustacchi else
2977eef4f27bSRobert Mustacchi {
2978eef4f27bSRobert Mustacchi val |= EMAC_MODE_PORT_GMII;
2979eef4f27bSRobert Mustacchi }
2980eef4f27bSRobert Mustacchi
2981eef4f27bSRobert Mustacchi if(GET_MEDIUM_SPEED(medium) == LM_MEDIUM_SPEED_2500MBPS)
2982eef4f27bSRobert Mustacchi {
2983eef4f27bSRobert Mustacchi val |= EMAC_MODE_25G_MODE;
2984eef4f27bSRobert Mustacchi }
2985eef4f27bSRobert Mustacchi
2986eef4f27bSRobert Mustacchi /* We need to set the port mode to GMII when we are running in
2987eef4f27bSRobert Mustacchi * the FPGA mode, regardless of the actual line speed. */
2988eef4f27bSRobert Mustacchi if(CHIP_REV(pdev) == CHIP_REV_FPGA)
2989eef4f27bSRobert Mustacchi {
2990eef4f27bSRobert Mustacchi val &= ~EMAC_MODE_PORT;
2991eef4f27bSRobert Mustacchi val |= EMAC_MODE_PORT_GMII;
2992eef4f27bSRobert Mustacchi }
2993eef4f27bSRobert Mustacchi }
2994eef4f27bSRobert Mustacchi else
2995eef4f27bSRobert Mustacchi {
2996eef4f27bSRobert Mustacchi val |= EMAC_MODE_PORT_GMII;
2997eef4f27bSRobert Mustacchi }
2998eef4f27bSRobert Mustacchi
2999eef4f27bSRobert Mustacchi if(GET_MEDIUM_TYPE(medium) == LM_MEDIUM_TYPE_NULL)
3000eef4f27bSRobert Mustacchi {
3001eef4f27bSRobert Mustacchi val |= EMAC_MODE_FORCE_LINK;
3002eef4f27bSRobert Mustacchi }
3003eef4f27bSRobert Mustacchi
3004eef4f27bSRobert Mustacchi /* Set the MAC to operate in the appropriate duplex mode. */
3005eef4f27bSRobert Mustacchi val &= ~EMAC_MODE_HALF_DUPLEX;
3006eef4f27bSRobert Mustacchi if(GET_MEDIUM_DUPLEX(medium) == LM_MEDIUM_HALF_DUPLEX)
3007eef4f27bSRobert Mustacchi {
3008eef4f27bSRobert Mustacchi val |= EMAC_MODE_HALF_DUPLEX;
3009eef4f27bSRobert Mustacchi }
3010eef4f27bSRobert Mustacchi REG_WR(pdev, emac.emac_mode, val);
3011eef4f27bSRobert Mustacchi
3012eef4f27bSRobert Mustacchi /* Acknowledge the interrupt. */
3013eef4f27bSRobert Mustacchi REG_WR(pdev, emac.emac_status, EMAC_STATUS_LINK_CHANGE);
3014eef4f27bSRobert Mustacchi
3015eef4f27bSRobert Mustacchi /* Enable phy link change attention. */
3016eef4f27bSRobert Mustacchi if(pdev->params.phy_int_mode == PHY_INT_MODE_MI_INTERRUPT)
3017eef4f27bSRobert Mustacchi {
3018eef4f27bSRobert Mustacchi REG_WR(pdev, emac.emac_attention_ena, EMAC_ATTENTION_ENA_MI_INT);
3019eef4f27bSRobert Mustacchi }
3020eef4f27bSRobert Mustacchi else
3021eef4f27bSRobert Mustacchi {
3022eef4f27bSRobert Mustacchi REG_WR(pdev, emac.emac_attention_ena, EMAC_ATTENTION_ENA_LINK);
3023eef4f27bSRobert Mustacchi }
3024eef4f27bSRobert Mustacchi
3025eef4f27bSRobert Mustacchi /* Enable status block link attention. */
3026eef4f27bSRobert Mustacchi REG_RD(pdev, hc.hc_attn_bits_enable, &val);
3027eef4f27bSRobert Mustacchi val &= ~STATUS_ATTN_BITS_LINK_STATE;
3028eef4f27bSRobert Mustacchi if(pdev->params.link_chng_mode == LINK_CHNG_MODE_USE_STATUS_BLOCK)
3029eef4f27bSRobert Mustacchi {
3030eef4f27bSRobert Mustacchi val |= STATUS_ATTN_BITS_LINK_STATE;
3031eef4f27bSRobert Mustacchi }
3032eef4f27bSRobert Mustacchi REG_WR(pdev, hc.hc_attn_bits_enable, val);
3033eef4f27bSRobert Mustacchi
3034eef4f27bSRobert Mustacchi pdev->vars.medium = medium;
3035eef4f27bSRobert Mustacchi pdev->vars.link_status = link;
3036eef4f27bSRobert Mustacchi } /* init_mac_link */
3037eef4f27bSRobert Mustacchi
3038eef4f27bSRobert Mustacchi
3039eef4f27bSRobert Mustacchi
3040eef4f27bSRobert Mustacchi /*******************************************************************************
3041eef4f27bSRobert Mustacchi * Description:
3042eef4f27bSRobert Mustacchi *
3043eef4f27bSRobert Mustacchi * Return:
3044eef4f27bSRobert Mustacchi ******************************************************************************/
3045eef4f27bSRobert Mustacchi STATIC lm_status_t
serdes_fallback(lm_device_t * pdev,u8_t fallback_select)3046eef4f27bSRobert Mustacchi serdes_fallback(
3047eef4f27bSRobert Mustacchi lm_device_t *pdev,
3048eef4f27bSRobert Mustacchi u8_t fallback_select)
3049eef4f27bSRobert Mustacchi {
3050eef4f27bSRobert Mustacchi u32_t intr_exp_status;
3051eef4f27bSRobert Mustacchi u8_t fallback_to;
3052eef4f27bSRobert Mustacchi u32_t phy_status;
3053eef4f27bSRobert Mustacchi u32_t phy_ctrl;
3054eef4f27bSRobert Mustacchi u32_t val;
3055eef4f27bSRobert Mustacchi u32_t cnt;
3056eef4f27bSRobert Mustacchi
3057eef4f27bSRobert Mustacchi pdev->vars.serdes_fallback_status = SERDES_FALLBACK_NONE;
3058eef4f27bSRobert Mustacchi
3059eef4f27bSRobert Mustacchi if(fallback_select == SERDES_FALLBACK_NONE)
3060eef4f27bSRobert Mustacchi {
3061eef4f27bSRobert Mustacchi return LM_STATUS_LINK_DOWN;
3062eef4f27bSRobert Mustacchi }
3063eef4f27bSRobert Mustacchi
3064eef4f27bSRobert Mustacchi /* See if the cable is connected. */
3065eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1c, 0x7c00);
3066eef4f27bSRobert Mustacchi (void) lm_mread(pdev, pdev->params.phy_addr, 0x1c, &val);
3067eef4f27bSRobert Mustacchi
3068eef4f27bSRobert Mustacchi /* We think the cable is not attached, set up the serdes to
3069eef4f27bSRobert Mustacchi * autoneg as the default. */
3070eef4f27bSRobert Mustacchi if(!(val & 0x10)) /* SIG_DETECT */
3071eef4f27bSRobert Mustacchi {
3072eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, "no cable, default to autoneg.\n");
3073eef4f27bSRobert Mustacchi
3074eef4f27bSRobert Mustacchi (void) lm_mwrite(
3075*55fea89dSDan Cross pdev,
3076eef4f27bSRobert Mustacchi pdev->params.phy_addr,
3077eef4f27bSRobert Mustacchi PHY_CTRL_REG,
3078eef4f27bSRobert Mustacchi PHY_CTRL_AUTO_NEG_ENABLE);
3079eef4f27bSRobert Mustacchi
3080eef4f27bSRobert Mustacchi return LM_STATUS_LINK_DOWN;
3081eef4f27bSRobert Mustacchi }
3082eef4f27bSRobert Mustacchi
3083eef4f27bSRobert Mustacchi /* Read the interrupt expansion register to see if rudi_c is set.
3084eef4f27bSRobert Mustacchi * rudi_c is set when we are receiving config words which means
3085eef4f27bSRobert Mustacchi * the link partner is attempting to autonegotiate.
3086eef4f27bSRobert Mustacchi *
3087eef4f27bSRobert Mustacchi * When the link partner is attempting to autonegotiate and we
3088eef4f27bSRobert Mustacchi * are not able to get linke, it could mean our transmit cable
3089eef4f27bSRobert Mustacchi * is not plugged in. In this case we don't want to fallback
3090eef4f27bSRobert Mustacchi * to the force mode. We want to remain in autonegotiation mode. */
3091eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x17, 0x0f01);
3092eef4f27bSRobert Mustacchi (void) lm_mread(pdev, pdev->params.phy_addr, 0x15, &intr_exp_status);
3093eef4f27bSRobert Mustacchi (void) lm_mread(pdev, pdev->params.phy_addr, 0x15, &intr_exp_status);
3094eef4f27bSRobert Mustacchi
3095eef4f27bSRobert Mustacchi /* See if autoneg is enabled and the remote is not sending us
3096eef4f27bSRobert Mustacchi * configs. If this is the case and link is currently down, we
3097eef4f27bSRobert Mustacchi * will switch to the force mode and disable autonegotiation.
3098eef4f27bSRobert Mustacchi *
3099eef4f27bSRobert Mustacchi * If we are current in the forced mode or the link partner is
3100eef4f27bSRobert Mustacchi * sending use configs, we'll enable autoneg and restart it. */
3101eef4f27bSRobert Mustacchi (void) lm_mread(pdev, pdev->params.phy_addr, PHY_CTRL_REG, &phy_ctrl);
3102eef4f27bSRobert Mustacchi if((phy_ctrl & PHY_CTRL_AUTO_NEG_ENABLE) && !(intr_exp_status & 0x20))
3103eef4f27bSRobert Mustacchi {
3104eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, "switch to force mode - 1G full\n");
3105eef4f27bSRobert Mustacchi
3106eef4f27bSRobert Mustacchi (void) lm_mwrite(
3107*55fea89dSDan Cross pdev,
3108eef4f27bSRobert Mustacchi pdev->params.phy_addr,
3109eef4f27bSRobert Mustacchi PHY_CTRL_REG,
3110eef4f27bSRobert Mustacchi PHY_CTRL_SPEED_SELECT_1000MBPS | PHY_CTRL_FULL_DUPLEX_MODE);
3111eef4f27bSRobert Mustacchi
3112eef4f27bSRobert Mustacchi fallback_to = SERDES_FALLBACK_1G;
3113eef4f27bSRobert Mustacchi }
3114eef4f27bSRobert Mustacchi else
3115eef4f27bSRobert Mustacchi {
3116eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, "switch to autoneg mode - 1G full\n");
3117eef4f27bSRobert Mustacchi
3118eef4f27bSRobert Mustacchi /* Switch to autoneg mode. */
3119eef4f27bSRobert Mustacchi (void) lm_mwrite(
3120*55fea89dSDan Cross pdev,
3121eef4f27bSRobert Mustacchi pdev->params.phy_addr,
3122eef4f27bSRobert Mustacchi PHY_CTRL_REG,
3123eef4f27bSRobert Mustacchi PHY_CTRL_AUTO_NEG_ENABLE | PHY_CTRL_RESTART_AUTO_NEG);
3124eef4f27bSRobert Mustacchi
3125eef4f27bSRobert Mustacchi fallback_to = SERDES_FALLBACK_NONE;
3126eef4f27bSRobert Mustacchi }
3127eef4f27bSRobert Mustacchi
3128eef4f27bSRobert Mustacchi for(cnt = 0; cnt < 100; cnt++)
3129eef4f27bSRobert Mustacchi {
3130eef4f27bSRobert Mustacchi mm_wait(pdev, 10);
3131eef4f27bSRobert Mustacchi }
3132eef4f27bSRobert Mustacchi
3133eef4f27bSRobert Mustacchi phy_status = mii_get_serdes_link_status(pdev);
3134eef4f27bSRobert Mustacchi
3135eef4f27bSRobert Mustacchi if(phy_status & PHY_STATUS_LINK_PASS)
3136eef4f27bSRobert Mustacchi {
3137eef4f27bSRobert Mustacchi pdev->vars.serdes_fallback_status = fallback_to;
3138eef4f27bSRobert Mustacchi
3139eef4f27bSRobert Mustacchi return LM_STATUS_LINK_ACTIVE;
3140eef4f27bSRobert Mustacchi }
3141eef4f27bSRobert Mustacchi
3142eef4f27bSRobert Mustacchi return LM_STATUS_LINK_DOWN;
3143eef4f27bSRobert Mustacchi } /* serdes_fallback */
3144eef4f27bSRobert Mustacchi
3145eef4f27bSRobert Mustacchi
3146eef4f27bSRobert Mustacchi
3147eef4f27bSRobert Mustacchi /*******************************************************************************
3148eef4f27bSRobert Mustacchi * Description:
3149eef4f27bSRobert Mustacchi *
3150eef4f27bSRobert Mustacchi * Return:
3151eef4f27bSRobert Mustacchi ******************************************************************************/
3152eef4f27bSRobert Mustacchi STATIC lm_status_t
get_5708_serdes_link(lm_device_t * pdev,lm_medium_t * medium)3153eef4f27bSRobert Mustacchi get_5708_serdes_link(
3154eef4f27bSRobert Mustacchi lm_device_t *pdev,
3155eef4f27bSRobert Mustacchi lm_medium_t *medium)
3156eef4f27bSRobert Mustacchi {
3157eef4f27bSRobert Mustacchi u8_t restarted_autoneg;
3158eef4f27bSRobert Mustacchi lm_medium_t duplex;
3159eef4f27bSRobert Mustacchi lm_medium_t speed;
3160eef4f27bSRobert Mustacchi lm_status_t link;
3161eef4f27bSRobert Mustacchi u32_t val;
3162eef4f27bSRobert Mustacchi u32_t idx;
3163eef4f27bSRobert Mustacchi
3164eef4f27bSRobert Mustacchi *medium = LM_MEDIUM_TYPE_FIBER |
3165eef4f27bSRobert Mustacchi LM_MEDIUM_SPEED_UNKNOWN |
3166eef4f27bSRobert Mustacchi LM_MEDIUM_FULL_DUPLEX;
3167eef4f27bSRobert Mustacchi
3168eef4f27bSRobert Mustacchi pdev->vars.cable_is_attached = FALSE;
3169eef4f27bSRobert Mustacchi
3170eef4f27bSRobert Mustacchi /* Check for link. The first read returns the latched value, the
3171eef4f27bSRobert Mustacchi * second read returns the current value. */
3172eef4f27bSRobert Mustacchi (void) lm_mread(
3173*55fea89dSDan Cross pdev,
3174*55fea89dSDan Cross pdev->params.phy_addr,
3175*55fea89dSDan Cross MII_REG(serdes_reg_t, mii_status),
3176eef4f27bSRobert Mustacchi &val);
3177eef4f27bSRobert Mustacchi (void) lm_mread(
3178*55fea89dSDan Cross pdev,
3179*55fea89dSDan Cross pdev->params.phy_addr,
3180*55fea89dSDan Cross MII_REG(serdes_reg_t, mii_status),
3181eef4f27bSRobert Mustacchi &val);
3182eef4f27bSRobert Mustacchi
3183eef4f27bSRobert Mustacchi /* CQ#23742 - Link status in the status block and the link status
3184eef4f27bSRobert Mustacchi * in the mii_status are not consistent. mii_status appears to
3185eef4f27bSRobert Mustacchi * return invalid value. Added a workaround here. */
3186eef4f27bSRobert Mustacchi for(idx = 0; idx < 10 && val == 0; idx++)
3187eef4f27bSRobert Mustacchi {
3188eef4f27bSRobert Mustacchi mm_wait(pdev, 10);
3189eef4f27bSRobert Mustacchi
3190eef4f27bSRobert Mustacchi (void) lm_mread(
3191*55fea89dSDan Cross pdev,
3192*55fea89dSDan Cross pdev->params.phy_addr,
3193*55fea89dSDan Cross MII_REG(serdes_reg_t, mii_status),
3194eef4f27bSRobert Mustacchi &val);
3195eef4f27bSRobert Mustacchi }
3196eef4f27bSRobert Mustacchi
3197eef4f27bSRobert Mustacchi if((val & MII_STAT_LINK_STATUS) == 0)
3198eef4f27bSRobert Mustacchi {
3199eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, "serdes link down.\n");
3200eef4f27bSRobert Mustacchi
3201eef4f27bSRobert Mustacchi pdev->vars.cable_is_attached = FALSE;
3202eef4f27bSRobert Mustacchi
3203eef4f27bSRobert Mustacchi return LM_STATUS_LINK_DOWN;
3204eef4f27bSRobert Mustacchi }
3205eef4f27bSRobert Mustacchi
3206eef4f27bSRobert Mustacchi link = LM_STATUS_LINK_ACTIVE;
3207eef4f27bSRobert Mustacchi pdev->vars.cable_is_attached = TRUE;
3208eef4f27bSRobert Mustacchi
3209eef4f27bSRobert Mustacchi /* Determine duplex mode. Link is present also means autoneg is done. */
3210eef4f27bSRobert Mustacchi (void) lm_mread(
3211*55fea89dSDan Cross pdev,
3212*55fea89dSDan Cross pdev->params.phy_addr,
3213*55fea89dSDan Cross MII_REG(serdes_reg_t, mii_ctrl),
3214eef4f27bSRobert Mustacchi &val);
3215eef4f27bSRobert Mustacchi if(val & MII_CTRL_ANEG_ENA)
3216eef4f27bSRobert Mustacchi {
3217eef4f27bSRobert Mustacchi /* Select Bank 0. */
3218eef4f27bSRobert Mustacchi (void) lm_mwrite(
3219*55fea89dSDan Cross pdev,
3220eef4f27bSRobert Mustacchi pdev->params.phy_addr,
3221eef4f27bSRobert Mustacchi MII_REG(serdes_reg_t, mii_block_addr),
3222eef4f27bSRobert Mustacchi MII_BLK_ADDR_DIGITAL);
3223eef4f27bSRobert Mustacchi
3224eef4f27bSRobert Mustacchi /* Get the negotiated speed and duplex mode. */
3225eef4f27bSRobert Mustacchi (void) lm_mread(
3226*55fea89dSDan Cross pdev,
3227eef4f27bSRobert Mustacchi pdev->params.phy_addr,
3228eef4f27bSRobert Mustacchi 0x10+MII_REG(serdes_digital_reg_t, mii_1000x_stat1),
3229eef4f27bSRobert Mustacchi &val);
3230eef4f27bSRobert Mustacchi switch(val & MII_1000X_STAT1_SPEED)
3231eef4f27bSRobert Mustacchi {
3232eef4f27bSRobert Mustacchi case MII_1000X_STAT1_SPEED_2G5:
3233eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, "serdes autoneg to 2.5gb.\n");
3234eef4f27bSRobert Mustacchi speed = LM_MEDIUM_SPEED_2500MBPS;
3235eef4f27bSRobert Mustacchi break;
3236eef4f27bSRobert Mustacchi
3237eef4f27bSRobert Mustacchi case MII_1000X_STAT1_SPEED_1G:
3238eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, "serdes autoneg to 1gb.\n");
3239eef4f27bSRobert Mustacchi speed = LM_MEDIUM_SPEED_1000MBPS;
3240eef4f27bSRobert Mustacchi break;
3241eef4f27bSRobert Mustacchi
3242eef4f27bSRobert Mustacchi case MII_1000X_STAT1_SPEED_100:
3243eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, "serdes autoneg to 100mb.\n");
3244eef4f27bSRobert Mustacchi speed = LM_MEDIUM_SPEED_100MBPS;
3245eef4f27bSRobert Mustacchi break;
3246eef4f27bSRobert Mustacchi
3247eef4f27bSRobert Mustacchi case MII_1000X_STAT1_SPEED_10:
3248eef4f27bSRobert Mustacchi default:
3249eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, "serdes autoneg to 10mb.\n");
3250eef4f27bSRobert Mustacchi speed = LM_MEDIUM_SPEED_10MBPS;
3251eef4f27bSRobert Mustacchi break;
3252eef4f27bSRobert Mustacchi }
3253eef4f27bSRobert Mustacchi
3254eef4f27bSRobert Mustacchi /* Get the duplex mode. */
3255eef4f27bSRobert Mustacchi duplex = LM_MEDIUM_FULL_DUPLEX;
3256eef4f27bSRobert Mustacchi if(val & MII_1000X_STAT1_DUPLEX)
3257eef4f27bSRobert Mustacchi {
3258eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, "serdes autoneg to full duplex.\n");
3259eef4f27bSRobert Mustacchi }
3260eef4f27bSRobert Mustacchi else
3261eef4f27bSRobert Mustacchi {
3262eef4f27bSRobert Mustacchi (void) lm_mread(
3263*55fea89dSDan Cross pdev,
3264*55fea89dSDan Cross pdev->params.phy_addr,
3265*55fea89dSDan Cross MII_REG(serdes_reg_t, mii_status),
3266eef4f27bSRobert Mustacchi &val);
3267eef4f27bSRobert Mustacchi if(val & MII_STAT_ANEG_CMPL)
3268eef4f27bSRobert Mustacchi {
3269eef4f27bSRobert Mustacchi duplex = LM_MEDIUM_HALF_DUPLEX;
3270eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, "serdes autoneg to half duplex.\n");
3271eef4f27bSRobert Mustacchi }
3272eef4f27bSRobert Mustacchi else
3273eef4f27bSRobert Mustacchi {
3274eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, "serdes autoneg to full duplex.\n");
3275eef4f27bSRobert Mustacchi }
3276eef4f27bSRobert Mustacchi }
3277eef4f27bSRobert Mustacchi
3278eef4f27bSRobert Mustacchi /* Set up pre-emphasis for a backplane application. */
3279eef4f27bSRobert Mustacchi if(pdev->hw_info.nvm_hw_config & SHARED_HW_CFG_BACKPLANE_APP)
3280eef4f27bSRobert Mustacchi {
3281eef4f27bSRobert Mustacchi restarted_autoneg = set_5708_serdes_pre_emphasis(
3282eef4f27bSRobert Mustacchi pdev,
3283eef4f27bSRobert Mustacchi pdev->params.serdes_pre_emphasis);
3284eef4f27bSRobert Mustacchi
3285eef4f27bSRobert Mustacchi if(restarted_autoneg)
3286eef4f27bSRobert Mustacchi {
3287eef4f27bSRobert Mustacchi speed = LM_MEDIUM_SPEED_UNKNOWN;
3288eef4f27bSRobert Mustacchi duplex = LM_MEDIUM_FULL_DUPLEX;
3289eef4f27bSRobert Mustacchi link = LM_STATUS_LINK_DOWN;
3290eef4f27bSRobert Mustacchi }
3291eef4f27bSRobert Mustacchi }
3292eef4f27bSRobert Mustacchi }
3293eef4f27bSRobert Mustacchi else
3294eef4f27bSRobert Mustacchi {
3295eef4f27bSRobert Mustacchi /* Determine the forced link settings. */
3296eef4f27bSRobert Mustacchi if(val & MII_CTRL_MANUAL_FORCE_2500)
3297eef4f27bSRobert Mustacchi {
3298eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, "serdes forced to 2.5gb.\n");
3299eef4f27bSRobert Mustacchi speed = LM_MEDIUM_SPEED_2500MBPS;
3300eef4f27bSRobert Mustacchi }
3301eef4f27bSRobert Mustacchi else if(val & MII_CTRL_MANUAL_SPD1)
3302eef4f27bSRobert Mustacchi {
3303eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, "serdes forced to 1gb.\n");
3304eef4f27bSRobert Mustacchi speed = LM_MEDIUM_SPEED_1000MBPS;
3305eef4f27bSRobert Mustacchi }
3306eef4f27bSRobert Mustacchi else if(val & MII_CTRL_MANUAL_SPD0)
3307eef4f27bSRobert Mustacchi {
3308eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, "serdes forced to 100mb.\n");
3309eef4f27bSRobert Mustacchi speed = LM_MEDIUM_SPEED_100MBPS;
3310eef4f27bSRobert Mustacchi }
3311eef4f27bSRobert Mustacchi else
3312eef4f27bSRobert Mustacchi {
3313eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, "serdes forced to 10mb.\n");
3314eef4f27bSRobert Mustacchi speed = LM_MEDIUM_SPEED_10MBPS;
3315eef4f27bSRobert Mustacchi }
3316eef4f27bSRobert Mustacchi
3317eef4f27bSRobert Mustacchi if(val & MII_CTRL_DUPLEX_MODE)
3318eef4f27bSRobert Mustacchi {
3319eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, "serdes forced to full duplex.\n");
3320eef4f27bSRobert Mustacchi duplex = LM_MEDIUM_FULL_DUPLEX;
3321eef4f27bSRobert Mustacchi }
3322eef4f27bSRobert Mustacchi else
3323eef4f27bSRobert Mustacchi {
3324eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, "serdes forced to half duplex.\n");
3325eef4f27bSRobert Mustacchi duplex = LM_MEDIUM_HALF_DUPLEX;
3326eef4f27bSRobert Mustacchi }
3327eef4f27bSRobert Mustacchi }
3328eef4f27bSRobert Mustacchi
3329eef4f27bSRobert Mustacchi *medium = LM_MEDIUM_TYPE_FIBER | speed | duplex;
3330eef4f27bSRobert Mustacchi
3331eef4f27bSRobert Mustacchi return link;
3332eef4f27bSRobert Mustacchi } /* get_5708_serdes_link */
3333eef4f27bSRobert Mustacchi
3334eef4f27bSRobert Mustacchi
3335eef4f27bSRobert Mustacchi
3336eef4f27bSRobert Mustacchi /*******************************************************************************
3337eef4f27bSRobert Mustacchi * Description:
3338eef4f27bSRobert Mustacchi *
3339eef4f27bSRobert Mustacchi * Return:
3340eef4f27bSRobert Mustacchi ******************************************************************************/
3341eef4f27bSRobert Mustacchi STATIC lm_status_t
get_5709_serdes_link(lm_device_t * pdev,lm_medium_t * medium)3342eef4f27bSRobert Mustacchi get_5709_serdes_link(
3343eef4f27bSRobert Mustacchi lm_device_t *pdev,
3344eef4f27bSRobert Mustacchi lm_medium_t *medium)
3345eef4f27bSRobert Mustacchi {
3346eef4f27bSRobert Mustacchi lm_medium_t duplex = LM_MEDIUM_FULL_DUPLEX;
3347eef4f27bSRobert Mustacchi lm_medium_t speed = LM_MEDIUM_SPEED_UNKNOWN;
3348eef4f27bSRobert Mustacchi lm_status_t link = LM_STATUS_LINK_UNKNOWN;
3349eef4f27bSRobert Mustacchi u32_t mac_status;
3350eef4f27bSRobert Mustacchi u32_t val;
3351eef4f27bSRobert Mustacchi
3352eef4f27bSRobert Mustacchi *medium = LM_MEDIUM_TYPE_FIBER |
3353eef4f27bSRobert Mustacchi LM_MEDIUM_SPEED_UNKNOWN |
3354eef4f27bSRobert Mustacchi LM_MEDIUM_FULL_DUPLEX;
3355eef4f27bSRobert Mustacchi
3356eef4f27bSRobert Mustacchi pdev->vars.cable_is_attached = FALSE;
3357eef4f27bSRobert Mustacchi
3358eef4f27bSRobert Mustacchi /* select gp_status block. */
3359eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1f, 0x8120);
3360eef4f27bSRobert Mustacchi
3361eef4f27bSRobert Mustacchi /* get status. */
3362eef4f27bSRobert Mustacchi (void) lm_mread(pdev, pdev->params.phy_addr, 0x1b, &val);
3363eef4f27bSRobert Mustacchi (void) lm_mread(pdev, pdev->params.phy_addr, 0x1b, &val); /* is this needed? */
3364eef4f27bSRobert Mustacchi
3365eef4f27bSRobert Mustacchi /* sometimes when we get a link event, mii register 0x1b does not
3366eef4f27bSRobert Mustacchi * reflect the current link status but mac_status does reflect the
3367eef4f27bSRobert Mustacchi * correct link status. */
3368eef4f27bSRobert Mustacchi REG_RD(pdev, emac.emac_status, &mac_status);
3369eef4f27bSRobert Mustacchi
3370eef4f27bSRobert Mustacchi /* link down. */
3371eef4f27bSRobert Mustacchi if((val & 0x4) == 0 && (mac_status & EMAC_STATUS_LINK) == 0)
3372eef4f27bSRobert Mustacchi {
3373eef4f27bSRobert Mustacchi return LM_STATUS_LINK_DOWN;
3374eef4f27bSRobert Mustacchi }
3375eef4f27bSRobert Mustacchi
3376eef4f27bSRobert Mustacchi link = LM_STATUS_LINK_ACTIVE;
3377eef4f27bSRobert Mustacchi pdev->vars.cable_is_attached = TRUE;
3378*55fea89dSDan Cross
3379eef4f27bSRobert Mustacchi /* select combo ieee0 block. */
3380eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1f, 0xffe0);
3381eef4f27bSRobert Mustacchi
3382eef4f27bSRobert Mustacchi /* phy_ctrl register. */
3383eef4f27bSRobert Mustacchi (void) lm_mread(pdev, pdev->params.phy_addr, 0x10, &val);
3384eef4f27bSRobert Mustacchi
3385eef4f27bSRobert Mustacchi if(val & 0x1000)
3386eef4f27bSRobert Mustacchi {
3387eef4f27bSRobert Mustacchi /* select gp_status block. */
3388eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1f, 0x8120);
3389eef4f27bSRobert Mustacchi
3390eef4f27bSRobert Mustacchi /* get status. */
3391eef4f27bSRobert Mustacchi (void) lm_mread(pdev, pdev->params.phy_addr, 0x1b, &val);
3392eef4f27bSRobert Mustacchi
3393eef4f27bSRobert Mustacchi /* duplex mode. */
3394eef4f27bSRobert Mustacchi if(val & 0x8)
3395eef4f27bSRobert Mustacchi {
3396eef4f27bSRobert Mustacchi duplex = LM_MEDIUM_FULL_DUPLEX;
3397eef4f27bSRobert Mustacchi }
3398eef4f27bSRobert Mustacchi else
3399eef4f27bSRobert Mustacchi {
3400eef4f27bSRobert Mustacchi duplex = LM_MEDIUM_HALF_DUPLEX;
3401eef4f27bSRobert Mustacchi }
3402eef4f27bSRobert Mustacchi
3403eef4f27bSRobert Mustacchi /* Determine autoneg speed. */
3404eef4f27bSRobert Mustacchi val = (val >> 8) & 0x3f;
3405eef4f27bSRobert Mustacchi if(val == 0)
3406eef4f27bSRobert Mustacchi {
3407eef4f27bSRobert Mustacchi speed = LM_MEDIUM_SPEED_10MBPS;
3408eef4f27bSRobert Mustacchi }
3409eef4f27bSRobert Mustacchi else if(val == 1)
3410eef4f27bSRobert Mustacchi {
3411eef4f27bSRobert Mustacchi speed = LM_MEDIUM_SPEED_100MBPS;
3412eef4f27bSRobert Mustacchi }
3413eef4f27bSRobert Mustacchi else if(val == 2 || val == 13)
3414eef4f27bSRobert Mustacchi {
3415eef4f27bSRobert Mustacchi speed = LM_MEDIUM_SPEED_1000MBPS;
3416eef4f27bSRobert Mustacchi }
3417eef4f27bSRobert Mustacchi else if(val == 3)
3418eef4f27bSRobert Mustacchi {
3419eef4f27bSRobert Mustacchi speed = LM_MEDIUM_SPEED_2500MBPS;
3420eef4f27bSRobert Mustacchi }
3421eef4f27bSRobert Mustacchi else
3422eef4f27bSRobert Mustacchi {
3423eef4f27bSRobert Mustacchi DbgBreakMsg("unknown link speed status.\n");
3424eef4f27bSRobert Mustacchi }
3425eef4f27bSRobert Mustacchi }
3426eef4f27bSRobert Mustacchi else
3427eef4f27bSRobert Mustacchi {
3428eef4f27bSRobert Mustacchi /* get forced duplex mode. */
3429eef4f27bSRobert Mustacchi if(val & 0x100)
3430eef4f27bSRobert Mustacchi {
3431eef4f27bSRobert Mustacchi duplex = LM_MEDIUM_FULL_DUPLEX;
3432eef4f27bSRobert Mustacchi }
3433eef4f27bSRobert Mustacchi else
3434eef4f27bSRobert Mustacchi {
3435eef4f27bSRobert Mustacchi duplex = LM_MEDIUM_HALF_DUPLEX;
3436eef4f27bSRobert Mustacchi }
3437eef4f27bSRobert Mustacchi
3438eef4f27bSRobert Mustacchi /* get forced speed. */
3439eef4f27bSRobert Mustacchi if(val & 0x20)
3440eef4f27bSRobert Mustacchi {
3441eef4f27bSRobert Mustacchi speed = LM_MEDIUM_SPEED_2500MBPS;
3442eef4f27bSRobert Mustacchi }
3443eef4f27bSRobert Mustacchi else if((val & 0x2040) == 0)
3444eef4f27bSRobert Mustacchi {
3445eef4f27bSRobert Mustacchi speed = LM_MEDIUM_SPEED_10MBPS;
3446eef4f27bSRobert Mustacchi }
3447eef4f27bSRobert Mustacchi else if((val & 0x2040) == 0x2000)
3448eef4f27bSRobert Mustacchi {
3449eef4f27bSRobert Mustacchi speed = LM_MEDIUM_SPEED_100MBPS;
3450eef4f27bSRobert Mustacchi }
3451eef4f27bSRobert Mustacchi else if((val & 0x2040) == 0x40)
3452eef4f27bSRobert Mustacchi {
3453eef4f27bSRobert Mustacchi speed = LM_MEDIUM_SPEED_1000MBPS;
3454eef4f27bSRobert Mustacchi }
3455eef4f27bSRobert Mustacchi else
3456eef4f27bSRobert Mustacchi {
3457eef4f27bSRobert Mustacchi DbgBreakMsg("unknown speed.\n");
3458eef4f27bSRobert Mustacchi }
3459eef4f27bSRobert Mustacchi }
3460eef4f27bSRobert Mustacchi
3461eef4f27bSRobert Mustacchi *medium = LM_MEDIUM_TYPE_FIBER | speed | duplex;
3462eef4f27bSRobert Mustacchi
3463eef4f27bSRobert Mustacchi return link;
3464eef4f27bSRobert Mustacchi } /* get_5709_serdes_link */
3465eef4f27bSRobert Mustacchi
3466eef4f27bSRobert Mustacchi
3467eef4f27bSRobert Mustacchi
3468eef4f27bSRobert Mustacchi /*******************************************************************************
3469eef4f27bSRobert Mustacchi * Description:
3470eef4f27bSRobert Mustacchi *
3471eef4f27bSRobert Mustacchi * Return:
3472eef4f27bSRobert Mustacchi ******************************************************************************/
3473eef4f27bSRobert Mustacchi STATIC lm_status_t
get_5706_serdes_link(lm_device_t * pdev,lm_medium_t * medium)3474eef4f27bSRobert Mustacchi get_5706_serdes_link(
3475eef4f27bSRobert Mustacchi lm_device_t *pdev,
3476eef4f27bSRobert Mustacchi lm_medium_t *medium)
3477eef4f27bSRobert Mustacchi {
3478eef4f27bSRobert Mustacchi lm_status_t link;
3479eef4f27bSRobert Mustacchi u32_t phy_status;
3480eef4f27bSRobert Mustacchi u32_t remote_adv;
3481eef4f27bSRobert Mustacchi u32_t local_adv;
3482eef4f27bSRobert Mustacchi u32_t phy_ctrl;
3483eef4f27bSRobert Mustacchi u32_t val;
3484eef4f27bSRobert Mustacchi
3485eef4f27bSRobert Mustacchi *medium = LM_MEDIUM_TYPE_FIBER;
3486eef4f27bSRobert Mustacchi
3487eef4f27bSRobert Mustacchi phy_status = mii_get_serdes_link_status(pdev);
3488eef4f27bSRobert Mustacchi
3489eef4f27bSRobert Mustacchi if(phy_status & PHY_STATUS_LINK_PASS)
3490eef4f27bSRobert Mustacchi {
3491eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, "serdes link up.\n");
3492eef4f27bSRobert Mustacchi
3493eef4f27bSRobert Mustacchi link = LM_STATUS_LINK_ACTIVE;
3494eef4f27bSRobert Mustacchi *medium |= LM_MEDIUM_SPEED_1000MBPS;
3495eef4f27bSRobert Mustacchi
3496eef4f27bSRobert Mustacchi /* Determine duplex mode. Link is present also means
3497eef4f27bSRobert Mustacchi * autoneg is done. */
3498eef4f27bSRobert Mustacchi (void) lm_mread(pdev, pdev->params.phy_addr, PHY_CTRL_REG, &phy_ctrl);
3499eef4f27bSRobert Mustacchi if(phy_ctrl & PHY_CTRL_AUTO_NEG_ENABLE)
3500eef4f27bSRobert Mustacchi {
3501eef4f27bSRobert Mustacchi (void) lm_mread(
3502*55fea89dSDan Cross pdev,
3503*55fea89dSDan Cross pdev->params.phy_addr,
3504*55fea89dSDan Cross PHY_AN_AD_REG,
3505eef4f27bSRobert Mustacchi &local_adv);
3506eef4f27bSRobert Mustacchi (void) lm_mread(
3507*55fea89dSDan Cross pdev,
3508*55fea89dSDan Cross pdev->params.phy_addr,
3509*55fea89dSDan Cross PHY_LINK_PARTNER_ABILITY_REG,
3510eef4f27bSRobert Mustacchi &remote_adv);
3511eef4f27bSRobert Mustacchi
3512eef4f27bSRobert Mustacchi val = local_adv & remote_adv;
3513eef4f27bSRobert Mustacchi if(val & PHY_AN_AD_1000X_FULL_DUPLEX)
3514eef4f27bSRobert Mustacchi {
3515eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, "serdes autoneg to full duplex.\n");
3516eef4f27bSRobert Mustacchi
3517eef4f27bSRobert Mustacchi *medium |= LM_MEDIUM_FULL_DUPLEX;
3518eef4f27bSRobert Mustacchi }
3519eef4f27bSRobert Mustacchi else
3520eef4f27bSRobert Mustacchi {
3521eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, "serdes autoneg to half duplex.\n");
3522eef4f27bSRobert Mustacchi
3523eef4f27bSRobert Mustacchi *medium |= LM_MEDIUM_HALF_DUPLEX;
3524eef4f27bSRobert Mustacchi }
3525eef4f27bSRobert Mustacchi
3526eef4f27bSRobert Mustacchi pdev->vars.serdes_fallback_status = SERDES_FALLBACK_NONE;
3527eef4f27bSRobert Mustacchi }
3528eef4f27bSRobert Mustacchi else
3529eef4f27bSRobert Mustacchi {
3530eef4f27bSRobert Mustacchi if(phy_ctrl & PHY_CTRL_FULL_DUPLEX_MODE)
3531eef4f27bSRobert Mustacchi {
3532eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, "serdes forced to full duplex.\n");
3533eef4f27bSRobert Mustacchi
3534eef4f27bSRobert Mustacchi *medium |= LM_MEDIUM_FULL_DUPLEX;
3535eef4f27bSRobert Mustacchi }
3536eef4f27bSRobert Mustacchi else
3537eef4f27bSRobert Mustacchi {
3538eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, "serdes forced to half duplex.\n");
3539eef4f27bSRobert Mustacchi
3540eef4f27bSRobert Mustacchi *medium |= LM_MEDIUM_HALF_DUPLEX;
3541eef4f27bSRobert Mustacchi }
3542eef4f27bSRobert Mustacchi
3543eef4f27bSRobert Mustacchi if(pdev->vars.serdes_fallback_select)
3544eef4f27bSRobert Mustacchi {
3545eef4f27bSRobert Mustacchi pdev->vars.serdes_fallback_status = SERDES_FALLBACK_1G;
3546eef4f27bSRobert Mustacchi }
3547eef4f27bSRobert Mustacchi }
3548eef4f27bSRobert Mustacchi }
3549eef4f27bSRobert Mustacchi else
3550eef4f27bSRobert Mustacchi {
3551eef4f27bSRobert Mustacchi DbgMessage(pdev, INFORM, "serdes link down.\n");
3552eef4f27bSRobert Mustacchi
3553eef4f27bSRobert Mustacchi /* This routine is called only when the link is down. */
3554eef4f27bSRobert Mustacchi link = serdes_fallback(pdev, pdev->vars.serdes_fallback_select);
3555eef4f27bSRobert Mustacchi }
3556eef4f27bSRobert Mustacchi
3557eef4f27bSRobert Mustacchi /* cq#30504 - restore the tx driver current so we can get link. */
3558eef4f27bSRobert Mustacchi if(pdev->vars.bcm5706s_tx_drv_cur)
3559eef4f27bSRobert Mustacchi {
3560eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x17, 0x0f03);
3561eef4f27bSRobert Mustacchi
3562eef4f27bSRobert Mustacchi (void) lm_mwrite(
3563eef4f27bSRobert Mustacchi pdev,
3564eef4f27bSRobert Mustacchi pdev->params.phy_addr,
3565eef4f27bSRobert Mustacchi 0x15,
3566eef4f27bSRobert Mustacchi pdev->vars.bcm5706s_tx_drv_cur);
3567eef4f27bSRobert Mustacchi
3568eef4f27bSRobert Mustacchi pdev->vars.bcm5706s_tx_drv_cur = 0;
3569eef4f27bSRobert Mustacchi }
3570eef4f27bSRobert Mustacchi
3571eef4f27bSRobert Mustacchi pdev->vars.cable_is_attached = TRUE;
3572eef4f27bSRobert Mustacchi
3573eef4f27bSRobert Mustacchi if(link == LM_STATUS_LINK_DOWN)
3574eef4f27bSRobert Mustacchi {
3575eef4f27bSRobert Mustacchi (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1c, 0x7c00);
3576eef4f27bSRobert Mustacchi (void) lm_mread(pdev, pdev->params.phy_addr, 0x1c, &val);
3577eef4f27bSRobert Mustacchi if(!(val & 0x10))
3578eef4f27bSRobert Mustacchi {
3579eef4f27bSRobert Mustacchi pdev->vars.cable_is_attached = FALSE;
3580eef4f27bSRobert Mustacchi }
3581eef4f27bSRobert Mustacchi }
3582eef4f27bSRobert Mustacchi
3583eef4f27bSRobert Mustacchi return link;
3584eef4f27bSRobert Mustacchi } /* get_5706_serdes_link */
3585eef4f27bSRobert Mustacchi
3586eef4f27bSRobert Mustacchi
3587eef4f27bSRobert Mustacchi
3588eef4f27bSRobert Mustacchi /*******************************************************************************
3589eef4f27bSRobert Mustacchi * Description:
3590eef4f27bSRobert Mustacchi *
3591eef4f27bSRobert Mustacchi * Return:
3592eef4f27bSRobert Mustacchi ******************************************************************************/
3593eef4f27bSRobert Mustacchi STATIC lm_status_t
get_remote_phy_link(lm_device_t * pdev,lm_medium_t * medium)3594eef4f27bSRobert Mustacchi get_remote_phy_link(
3595eef4f27bSRobert Mustacchi lm_device_t *pdev,
3596eef4f27bSRobert Mustacchi lm_medium_t *medium)
3597eef4f27bSRobert Mustacchi {
3598eef4f27bSRobert Mustacchi u32_t remote_phy_link;
3599eef4f27bSRobert Mustacchi lm_medium_t duplex;
3600eef4f27bSRobert Mustacchi lm_medium_t speed;
3601eef4f27bSRobert Mustacchi lm_status_t link;
3602eef4f27bSRobert Mustacchi
3603eef4f27bSRobert Mustacchi DbgBreakIf(pdev->params.enable_remote_phy == FALSE);
3604eef4f27bSRobert Mustacchi
3605eef4f27bSRobert Mustacchi *medium = LM_MEDIUM_TYPE_FIBER |
3606eef4f27bSRobert Mustacchi LM_MEDIUM_SPEED_UNKNOWN |
3607eef4f27bSRobert Mustacchi LM_MEDIUM_FULL_DUPLEX;
3608eef4f27bSRobert Mustacchi
3609eef4f27bSRobert Mustacchi pdev->vars.cable_is_attached = FALSE;
3610eef4f27bSRobert Mustacchi
3611eef4f27bSRobert Mustacchi REG_RD_IND(
3612eef4f27bSRobert Mustacchi pdev,
3613eef4f27bSRobert Mustacchi pdev->hw_info.shmem_base +
3614eef4f27bSRobert Mustacchi OFFSETOF(shmem_region_t, drv_fw_mb.link_status),
3615eef4f27bSRobert Mustacchi &remote_phy_link);
3616eef4f27bSRobert Mustacchi
3617eef4f27bSRobert Mustacchi pdev->vars.rphy_status = 0;
3618eef4f27bSRobert Mustacchi
3619eef4f27bSRobert Mustacchi if((remote_phy_link & NETLINK_GET_LINK_STATUS_SERDES_LINK) == 0)
3620eef4f27bSRobert Mustacchi {
3621eef4f27bSRobert Mustacchi pdev->vars.rphy_status |= RPHY_STATUS_ACTIVE;
3622eef4f27bSRobert Mustacchi }
3623eef4f27bSRobert Mustacchi
3624eef4f27bSRobert Mustacchi if((remote_phy_link & NETLINK_GET_LINK_STATUS_NO_MEDIA_DETECTED) == 0)
3625eef4f27bSRobert Mustacchi {
3626eef4f27bSRobert Mustacchi pdev->vars.rphy_status |= RPHY_STATUS_MODULE_PRESENT;
3627eef4f27bSRobert Mustacchi }
3628eef4f27bSRobert Mustacchi
3629eef4f27bSRobert Mustacchi if((remote_phy_link & NETLINK_GET_LINK_STATUS_LINK_UP) == 0)
3630eef4f27bSRobert Mustacchi {
3631eef4f27bSRobert Mustacchi return LM_STATUS_LINK_DOWN;
3632eef4f27bSRobert Mustacchi }
3633eef4f27bSRobert Mustacchi
3634eef4f27bSRobert Mustacchi link = LM_STATUS_LINK_ACTIVE;
3635eef4f27bSRobert Mustacchi pdev->vars.cable_is_attached = TRUE;
3636eef4f27bSRobert Mustacchi
3637eef4f27bSRobert Mustacchi switch(remote_phy_link & NETLINK_GET_LINK_STATUS_SPEED_MASK)
3638eef4f27bSRobert Mustacchi {
3639eef4f27bSRobert Mustacchi case NETLINK_GET_LINK_STATUS_10HALF:
3640eef4f27bSRobert Mustacchi speed = LM_MEDIUM_SPEED_10MBPS;
3641eef4f27bSRobert Mustacchi duplex = LM_MEDIUM_HALF_DUPLEX;
3642eef4f27bSRobert Mustacchi break;
3643eef4f27bSRobert Mustacchi
3644eef4f27bSRobert Mustacchi case NETLINK_GET_LINK_STATUS_10FULL:
3645eef4f27bSRobert Mustacchi speed = LM_MEDIUM_SPEED_10MBPS;
3646eef4f27bSRobert Mustacchi duplex = LM_MEDIUM_FULL_DUPLEX;
3647eef4f27bSRobert Mustacchi break;
3648eef4f27bSRobert Mustacchi
3649eef4f27bSRobert Mustacchi case NETLINK_GET_LINK_STATUS_100HALF:
3650eef4f27bSRobert Mustacchi speed = LM_MEDIUM_SPEED_100MBPS;
3651eef4f27bSRobert Mustacchi duplex = LM_MEDIUM_HALF_DUPLEX;
3652eef4f27bSRobert Mustacchi break;
3653eef4f27bSRobert Mustacchi
3654eef4f27bSRobert Mustacchi case NETLINK_GET_LINK_STATUS_100FULL:
3655eef4f27bSRobert Mustacchi speed = LM_MEDIUM_SPEED_100MBPS;
3656eef4f27bSRobert Mustacchi duplex = LM_MEDIUM_FULL_DUPLEX;
3657eef4f27bSRobert Mustacchi break;
3658eef4f27bSRobert Mustacchi
3659eef4f27bSRobert Mustacchi case NETLINK_GET_LINK_STATUS_1000HALF:
3660eef4f27bSRobert Mustacchi speed = LM_MEDIUM_SPEED_1000MBPS;
3661eef4f27bSRobert Mustacchi duplex = LM_MEDIUM_HALF_DUPLEX;
3662eef4f27bSRobert Mustacchi break;
3663eef4f27bSRobert Mustacchi
3664eef4f27bSRobert Mustacchi case NETLINK_GET_LINK_STATUS_1000FULL:
3665eef4f27bSRobert Mustacchi speed = LM_MEDIUM_SPEED_1000MBPS;
3666eef4f27bSRobert Mustacchi duplex = LM_MEDIUM_FULL_DUPLEX;
3667eef4f27bSRobert Mustacchi break;
3668eef4f27bSRobert Mustacchi
3669eef4f27bSRobert Mustacchi case NETLINK_GET_LINK_STATUS_2500HALF:
3670eef4f27bSRobert Mustacchi speed = LM_MEDIUM_SPEED_2500MBPS;
3671eef4f27bSRobert Mustacchi duplex = LM_MEDIUM_HALF_DUPLEX;
3672eef4f27bSRobert Mustacchi break;
3673eef4f27bSRobert Mustacchi
3674eef4f27bSRobert Mustacchi case NETLINK_GET_LINK_STATUS_2500FULL:
3675eef4f27bSRobert Mustacchi speed = LM_MEDIUM_SPEED_2500MBPS;
3676eef4f27bSRobert Mustacchi duplex = LM_MEDIUM_FULL_DUPLEX;
3677eef4f27bSRobert Mustacchi break;
3678eef4f27bSRobert Mustacchi
3679eef4f27bSRobert Mustacchi default:
3680eef4f27bSRobert Mustacchi speed = LM_MEDIUM_SPEED_UNKNOWN;
3681eef4f27bSRobert Mustacchi duplex = LM_MEDIUM_FULL_DUPLEX;
3682eef4f27bSRobert Mustacchi break;
3683eef4f27bSRobert Mustacchi }
3684eef4f27bSRobert Mustacchi
3685eef4f27bSRobert Mustacchi *medium = LM_MEDIUM_TYPE_FIBER | speed | duplex;
3686eef4f27bSRobert Mustacchi
3687eef4f27bSRobert Mustacchi return link;
3688eef4f27bSRobert Mustacchi } /* get_remote_phy_link */
3689eef4f27bSRobert Mustacchi
3690eef4f27bSRobert Mustacchi
3691eef4f27bSRobert Mustacchi
3692eef4f27bSRobert Mustacchi /*******************************************************************************
3693eef4f27bSRobert Mustacchi * Description:
3694eef4f27bSRobert Mustacchi *
3695eef4f27bSRobert Mustacchi * Return:
3696eef4f27bSRobert Mustacchi ******************************************************************************/
3697eef4f27bSRobert Mustacchi lm_status_t
lm_init_mac_link(lm_device_t * pdev)3698eef4f27bSRobert Mustacchi lm_init_mac_link(
3699eef4f27bSRobert Mustacchi lm_device_t *pdev)
3700eef4f27bSRobert Mustacchi {
3701eef4f27bSRobert Mustacchi lm_status_t lm_status;
3702eef4f27bSRobert Mustacchi lm_medium_t medium;
3703eef4f27bSRobert Mustacchi lm_status_t link;
3704eef4f27bSRobert Mustacchi u32_t val, phy_ctrl, phy_status;
3705eef4f27bSRobert Mustacchi
3706eef4f27bSRobert Mustacchi if(pdev->params.enable_remote_phy)
3707eef4f27bSRobert Mustacchi {
3708eef4f27bSRobert Mustacchi link = get_remote_phy_link(pdev, &medium);
3709eef4f27bSRobert Mustacchi init_mac_link(pdev, link, medium, pdev->params.flow_ctrl_cap);
3710eef4f27bSRobert Mustacchi
3711eef4f27bSRobert Mustacchi return LM_STATUS_SUCCESS;
3712eef4f27bSRobert Mustacchi }
3713eef4f27bSRobert Mustacchi
3714eef4f27bSRobert Mustacchi switch(GET_MEDIUM_TYPE(pdev->vars.medium))
3715eef4f27bSRobert Mustacchi {
3716eef4f27bSRobert Mustacchi case LM_MEDIUM_TYPE_UTP:
3717eef4f27bSRobert Mustacchi link = get_copper_phy_link(pdev, &medium);
3718eef4f27bSRobert Mustacchi init_mac_link(pdev, link, medium, pdev->params.flow_ctrl_cap);
3719eef4f27bSRobert Mustacchi
3720eef4f27bSRobert Mustacchi lm_status = LM_STATUS_SUCCESS;
3721eef4f27bSRobert Mustacchi break;
3722eef4f27bSRobert Mustacchi
3723eef4f27bSRobert Mustacchi case LM_MEDIUM_TYPE_FIBER:
3724eef4f27bSRobert Mustacchi DbgBreakIf(CHIP_NUM(pdev) != CHIP_NUM_5706 &&
3725eef4f27bSRobert Mustacchi CHIP_NUM(pdev) != CHIP_NUM_5708 &&
3726eef4f27bSRobert Mustacchi CHIP_NUM(pdev) != CHIP_NUM_5709);
3727eef4f27bSRobert Mustacchi
3728eef4f27bSRobert Mustacchi if(CHIP_NUM(pdev) == CHIP_NUM_5706)
3729eef4f27bSRobert Mustacchi {
3730eef4f27bSRobert Mustacchi link = get_5706_serdes_link(pdev, &medium);
3731eef4f27bSRobert Mustacchi }
3732eef4f27bSRobert Mustacchi else if(CHIP_NUM(pdev) == CHIP_NUM_5708)
3733eef4f27bSRobert Mustacchi {
3734eef4f27bSRobert Mustacchi link = get_5708_serdes_link(pdev, &medium);
3735eef4f27bSRobert Mustacchi }
3736eef4f27bSRobert Mustacchi else
3737eef4f27bSRobert Mustacchi {
3738eef4f27bSRobert Mustacchi link = get_5709_serdes_link(pdev, &medium);
3739eef4f27bSRobert Mustacchi }
3740eef4f27bSRobert Mustacchi
3741eef4f27bSRobert Mustacchi init_mac_link(pdev, link, medium, pdev->params.flow_ctrl_cap);
3742eef4f27bSRobert Mustacchi
3743eef4f27bSRobert Mustacchi lm_status = LM_STATUS_SUCCESS;
3744eef4f27bSRobert Mustacchi break;
3745eef4f27bSRobert Mustacchi
3746eef4f27bSRobert Mustacchi case LM_MEDIUM_TYPE_PHY_LOOPBACK:
3747eef4f27bSRobert Mustacchi case LM_MEDIUM_TYPE_MAC_LOOPBACK:
3748eef4f27bSRobert Mustacchi lm_status = init_loopback_mac_link(
3749eef4f27bSRobert Mustacchi pdev,
3750eef4f27bSRobert Mustacchi pdev->params.req_medium,
3751eef4f27bSRobert Mustacchi pdev->params.flow_ctrl_cap);
3752eef4f27bSRobert Mustacchi break;
3753eef4f27bSRobert Mustacchi
3754eef4f27bSRobert Mustacchi case LM_MEDIUM_TYPE_NULL:
3755eef4f27bSRobert Mustacchi init_mac_link(
3756eef4f27bSRobert Mustacchi pdev,
3757eef4f27bSRobert Mustacchi LM_STATUS_LINK_ACTIVE,
3758eef4f27bSRobert Mustacchi LM_MEDIUM_TYPE_NULL |
3759eef4f27bSRobert Mustacchi LM_MEDIUM_SPEED_1000MBPS |
3760eef4f27bSRobert Mustacchi LM_MEDIUM_FULL_DUPLEX,
3761eef4f27bSRobert Mustacchi pdev->params.flow_ctrl_cap);
3762eef4f27bSRobert Mustacchi
3763eef4f27bSRobert Mustacchi lm_status = LM_STATUS_SUCCESS;
3764eef4f27bSRobert Mustacchi break;
3765eef4f27bSRobert Mustacchi
3766eef4f27bSRobert Mustacchi default:
3767eef4f27bSRobert Mustacchi lm_status = LM_STATUS_UNKNOWN_MEDIUM;
3768eef4f27bSRobert Mustacchi break;
3769eef4f27bSRobert Mustacchi }
3770eef4f27bSRobert Mustacchi
3771eef4f27bSRobert Mustacchi /* Report the currnet link status to the management firmware. */
3772eef4f27bSRobert Mustacchi val = 0;
3773eef4f27bSRobert Mustacchi
3774eef4f27bSRobert Mustacchi if(pdev->vars.link_status == LM_STATUS_LINK_ACTIVE)
3775eef4f27bSRobert Mustacchi {
3776eef4f27bSRobert Mustacchi val |= NETLINK_GET_LINK_STATUS_LINK_UP;
3777eef4f27bSRobert Mustacchi
3778eef4f27bSRobert Mustacchi if(lm_get_medium(pdev) == LM_MEDIUM_TYPE_FIBER)
3779eef4f27bSRobert Mustacchi {
3780eef4f27bSRobert Mustacchi val |= NETLINK_GET_LINK_STATUS_SERDES_LINK;
3781eef4f27bSRobert Mustacchi }
3782eef4f27bSRobert Mustacchi }
3783eef4f27bSRobert Mustacchi
3784eef4f27bSRobert Mustacchi switch(GET_MEDIUM_SPEED(pdev->vars.medium))
3785eef4f27bSRobert Mustacchi {
3786eef4f27bSRobert Mustacchi case LM_MEDIUM_SPEED_10MBPS:
3787eef4f27bSRobert Mustacchi if(GET_MEDIUM_DUPLEX(pdev->vars.medium) == LM_MEDIUM_FULL_DUPLEX)
3788eef4f27bSRobert Mustacchi {
3789eef4f27bSRobert Mustacchi val |= NETLINK_GET_LINK_STATUS_10FULL;
3790eef4f27bSRobert Mustacchi }
3791eef4f27bSRobert Mustacchi else
3792eef4f27bSRobert Mustacchi {
3793eef4f27bSRobert Mustacchi val |= NETLINK_GET_LINK_STATUS_10HALF;
3794eef4f27bSRobert Mustacchi }
3795eef4f27bSRobert Mustacchi break;
3796eef4f27bSRobert Mustacchi
3797eef4f27bSRobert Mustacchi case LM_MEDIUM_SPEED_100MBPS:
3798eef4f27bSRobert Mustacchi if(GET_MEDIUM_DUPLEX(pdev->vars.medium) == LM_MEDIUM_FULL_DUPLEX)
3799eef4f27bSRobert Mustacchi {
3800eef4f27bSRobert Mustacchi val |= NETLINK_GET_LINK_STATUS_100FULL;
3801eef4f27bSRobert Mustacchi }
3802eef4f27bSRobert Mustacchi else
3803eef4f27bSRobert Mustacchi {
3804eef4f27bSRobert Mustacchi val |= NETLINK_GET_LINK_STATUS_100HALF;
3805eef4f27bSRobert Mustacchi }
3806eef4f27bSRobert Mustacchi break;
3807eef4f27bSRobert Mustacchi
3808eef4f27bSRobert Mustacchi case LM_MEDIUM_SPEED_1000MBPS:
3809eef4f27bSRobert Mustacchi if(GET_MEDIUM_DUPLEX(pdev->vars.medium) == LM_MEDIUM_FULL_DUPLEX)
3810eef4f27bSRobert Mustacchi {
3811eef4f27bSRobert Mustacchi val |= NETLINK_GET_LINK_STATUS_1000FULL;
3812eef4f27bSRobert Mustacchi }
3813eef4f27bSRobert Mustacchi else
3814eef4f27bSRobert Mustacchi {
3815eef4f27bSRobert Mustacchi val |= NETLINK_GET_LINK_STATUS_1000HALF;
3816eef4f27bSRobert Mustacchi }
3817eef4f27bSRobert Mustacchi break;
3818eef4f27bSRobert Mustacchi
3819eef4f27bSRobert Mustacchi case LM_MEDIUM_SPEED_2500MBPS:
3820eef4f27bSRobert Mustacchi if(GET_MEDIUM_DUPLEX(pdev->vars.medium) == LM_MEDIUM_FULL_DUPLEX)
3821eef4f27bSRobert Mustacchi {
3822eef4f27bSRobert Mustacchi val |= NETLINK_GET_LINK_STATUS_2500FULL;
3823eef4f27bSRobert Mustacchi }
3824eef4f27bSRobert Mustacchi else
3825eef4f27bSRobert Mustacchi {
3826eef4f27bSRobert Mustacchi val |= NETLINK_GET_LINK_STATUS_2500HALF;
3827eef4f27bSRobert Mustacchi }
3828eef4f27bSRobert Mustacchi break;
3829eef4f27bSRobert Mustacchi }
3830eef4f27bSRobert Mustacchi
3831eef4f27bSRobert Mustacchi // read PHY_CTRL_REG to see if auto-negotiation is enabled/completed
3832eef4f27bSRobert Mustacchi (void) lm_mread(pdev, pdev->params.phy_addr, PHY_CTRL_REG, &phy_ctrl);
3833eef4f27bSRobert Mustacchi
3834eef4f27bSRobert Mustacchi if(phy_ctrl & PHY_CTRL_AUTO_NEG_ENABLE)
3835eef4f27bSRobert Mustacchi {
3836eef4f27bSRobert Mustacchi val |= NETLINK_GET_LINK_STATUS_AN_ENABLED;
3837eef4f27bSRobert Mustacchi (void) lm_mread(pdev, pdev->params.phy_addr, PHY_STATUS_REG, &phy_status);
3838eef4f27bSRobert Mustacchi if(phy_status & PHY_STATUS_AUTO_NEG_COMPLETE)
3839eef4f27bSRobert Mustacchi {
3840eef4f27bSRobert Mustacchi val |= NETLINK_GET_LINK_STATUS_AN_COMPLETE;
3841eef4f27bSRobert Mustacchi // Following bits are valid for copper (i.e. SerDes flag == 0)
3842eef4f27bSRobert Mustacchi if ((val & NETLINK_GET_LINK_STATUS_SERDES_LINK) == 0)
3843eef4f27bSRobert Mustacchi {
3844eef4f27bSRobert Mustacchi u32_t remote_phy_ad;
3845eef4f27bSRobert Mustacchi (void) lm_mread(
3846*55fea89dSDan Cross pdev,
3847*55fea89dSDan Cross pdev->params.phy_addr,
3848*55fea89dSDan Cross PHY_1000BASET_STATUS_REG,
3849eef4f27bSRobert Mustacchi &remote_phy_ad);
3850eef4f27bSRobert Mustacchi
3851eef4f27bSRobert Mustacchi if(remote_phy_ad & PHY_LINK_PARTNER_1000BASET_FULL)
3852eef4f27bSRobert Mustacchi val |= NETLINK_GET_LINK_STATUS_PARTNER_AD_1000FULL;
3853eef4f27bSRobert Mustacchi if(remote_phy_ad & PHY_LINK_PARTNER_1000BASET_HALF)
3854eef4f27bSRobert Mustacchi val |= NETLINK_GET_LINK_STATUS_PARTNER_AD_1000HALF;
3855eef4f27bSRobert Mustacchi
3856eef4f27bSRobert Mustacchi (void) lm_mread(
3857*55fea89dSDan Cross pdev,
3858*55fea89dSDan Cross pdev->params.phy_addr,
3859*55fea89dSDan Cross PHY_LINK_PARTNER_ABILITY_REG,
3860eef4f27bSRobert Mustacchi &remote_phy_ad);
3861*55fea89dSDan Cross if (remote_phy_ad & PHY_LINK_PARTNER_10BASET_HALF)
3862eef4f27bSRobert Mustacchi val |= NETLINK_GET_LINK_STATUS_PARTNER_AD_10HALF;
3863*55fea89dSDan Cross if (remote_phy_ad & PHY_LINK_PARTNER_10BASET_FULL)
3864eef4f27bSRobert Mustacchi val |= NETLINK_GET_LINK_STATUS_PARTNER_AD_10FULL;
3865eef4f27bSRobert Mustacchi if (remote_phy_ad & PHY_LINK_PARTNER_100BASETX_HALF)
3866eef4f27bSRobert Mustacchi val |= NETLINK_GET_LINK_STATUS_PARTNER_AD_100HALF;
3867eef4f27bSRobert Mustacchi if (remote_phy_ad & PHY_LINK_PARTNER_100BASETX_FULL)
3868eef4f27bSRobert Mustacchi val |= NETLINK_GET_LINK_STATUS_PARTNER_AD_100FULL;
3869eef4f27bSRobert Mustacchi if (remote_phy_ad & PHY_LINK_PARTNER_PAUSE_CAPABLE)
3870eef4f27bSRobert Mustacchi val |= NETLINK_GET_LINK_STATUS_PARTNER_SYM_PAUSE_CAP;
3871eef4f27bSRobert Mustacchi if (remote_phy_ad & PHY_LINK_PARTNER_ASYM_PAUSE)
3872eef4f27bSRobert Mustacchi val |= NETLINK_GET_LINK_STATUS_PARTNER_ASYM_PAUSE_CAP;
3873eef4f27bSRobert Mustacchi // Read PHY_AN_EXPANSION_REG to see if Link partner support auto
3874*55fea89dSDan Cross // negotiation
3875eef4f27bSRobert Mustacchi (void) lm_mread(
3876*55fea89dSDan Cross pdev,
3877*55fea89dSDan Cross pdev->params.phy_addr,
3878*55fea89dSDan Cross PHY_AN_EXPANSION_REG,
3879eef4f27bSRobert Mustacchi &remote_phy_ad);
3880eef4f27bSRobert Mustacchi // If Link partner does not support auto negotiation, we assume
3881eef4f27bSRobert Mustacchi // parallel detection was used to get link.
3882*55fea89dSDan Cross if ((remote_phy_ad & PHY_LINK_PARTNER_AUTONEG_ABILITY) == 0)
3883eef4f27bSRobert Mustacchi val |= NETLINK_GET_LINK_STATUS_PARALLEL_DET;
3884eef4f27bSRobert Mustacchi }
3885eef4f27bSRobert Mustacchi }
3886eef4f27bSRobert Mustacchi }
3887eef4f27bSRobert Mustacchi if(pdev->vars.flow_control & LM_FLOW_CONTROL_TRANSMIT_PAUSE)
3888eef4f27bSRobert Mustacchi {
3889eef4f27bSRobert Mustacchi val |= NETLINK_GET_LINK_STATUS_TX_FC_ENABLED;
3890eef4f27bSRobert Mustacchi }
3891eef4f27bSRobert Mustacchi if(pdev->vars.flow_control & LM_FLOW_CONTROL_RECEIVE_PAUSE)
3892eef4f27bSRobert Mustacchi {
3893eef4f27bSRobert Mustacchi val |= NETLINK_GET_LINK_STATUS_RX_FC_ENABLED;
3894eef4f27bSRobert Mustacchi }
3895eef4f27bSRobert Mustacchi // Following bits are not supported yet
3896eef4f27bSRobert Mustacchi // NETLINK_GET_LINK_STATUS_NO_MEDIA_DETECTED;
3897eef4f27bSRobert Mustacchi // NETLINK_GET_LINK_STATUS_CABLESENSE;
3898eef4f27bSRobert Mustacchi // NETLINK_GET_LINK_STATUS_SW_TIMER_EVENT;
3899eef4f27bSRobert Mustacchi REG_WR_IND(
3900eef4f27bSRobert Mustacchi pdev,
3901eef4f27bSRobert Mustacchi pdev->hw_info.shmem_base +
3902eef4f27bSRobert Mustacchi OFFSETOF(shmem_region_t, drv_fw_mb.link_status),
3903eef4f27bSRobert Mustacchi val);
3904*55fea89dSDan Cross
3905eef4f27bSRobert Mustacchi return lm_status;
3906eef4f27bSRobert Mustacchi } /* lm_init_mac_link */
3907eef4f27bSRobert Mustacchi
3908eef4f27bSRobert Mustacchi
3909eef4f27bSRobert Mustacchi
3910eef4f27bSRobert Mustacchi /*******************************************************************************
3911eef4f27bSRobert Mustacchi * Description:
3912eef4f27bSRobert Mustacchi *
3913eef4f27bSRobert Mustacchi * Return:
3914eef4f27bSRobert Mustacchi ******************************************************************************/
3915eef4f27bSRobert Mustacchi void
lm_service_phy_int(lm_device_t * pdev,u32_t force_service_int)3916eef4f27bSRobert Mustacchi lm_service_phy_int(
3917eef4f27bSRobert Mustacchi lm_device_t *pdev,
3918eef4f27bSRobert Mustacchi u32_t force_service_int)
3919eef4f27bSRobert Mustacchi {
3920eef4f27bSRobert Mustacchi u32_t deasserted_attns;
3921eef4f27bSRobert Mustacchi u32_t asserted_attns;
3922eef4f27bSRobert Mustacchi u32_t link_chng;
3923eef4f27bSRobert Mustacchi u32_t val;
3924eef4f27bSRobert Mustacchi
3925eef4f27bSRobert Mustacchi link_chng = FALSE;
3926eef4f27bSRobert Mustacchi
3927eef4f27bSRobert Mustacchi if(pdev->params.link_chng_mode == LINK_CHNG_MODE_USE_STATUS_REG)
3928eef4f27bSRobert Mustacchi {
3929eef4f27bSRobert Mustacchi REG_RD(pdev, emac.emac_status, &val);
3930eef4f27bSRobert Mustacchi if(pdev->params.phy_int_mode == PHY_INT_MODE_MI_INTERRUPT)
3931eef4f27bSRobert Mustacchi {
3932eef4f27bSRobert Mustacchi if(val & EMAC_STATUS_MI_INT)
3933eef4f27bSRobert Mustacchi {
3934eef4f27bSRobert Mustacchi link_chng = TRUE;
3935eef4f27bSRobert Mustacchi }
3936eef4f27bSRobert Mustacchi }
3937eef4f27bSRobert Mustacchi else if(val & EMAC_STATUS_LINK_CHANGE)
3938eef4f27bSRobert Mustacchi {
3939eef4f27bSRobert Mustacchi link_chng = TRUE;
3940eef4f27bSRobert Mustacchi }
3941eef4f27bSRobert Mustacchi }
3942eef4f27bSRobert Mustacchi else
3943eef4f27bSRobert Mustacchi {
3944eef4f27bSRobert Mustacchi link_chng = FALSE;
3945eef4f27bSRobert Mustacchi
3946eef4f27bSRobert Mustacchi GET_ATTN_CHNG_BITS(pdev, &asserted_attns, &deasserted_attns);
3947eef4f27bSRobert Mustacchi
3948eef4f27bSRobert Mustacchi asserted_attns &= STATUS_ATTN_BITS_LINK_STATE;
3949eef4f27bSRobert Mustacchi deasserted_attns &= STATUS_ATTN_BITS_LINK_STATE;
3950eef4f27bSRobert Mustacchi
3951eef4f27bSRobert Mustacchi if(asserted_attns)
3952eef4f27bSRobert Mustacchi {
3953eef4f27bSRobert Mustacchi link_chng = TRUE;
3954eef4f27bSRobert Mustacchi
3955eef4f27bSRobert Mustacchi REG_WR(
3956eef4f27bSRobert Mustacchi pdev,
3957eef4f27bSRobert Mustacchi pci_config.pcicfg_status_bit_set_cmd,
3958eef4f27bSRobert Mustacchi asserted_attns);
3959eef4f27bSRobert Mustacchi }
3960eef4f27bSRobert Mustacchi else if(deasserted_attns)
3961eef4f27bSRobert Mustacchi {
3962eef4f27bSRobert Mustacchi link_chng = TRUE;
3963eef4f27bSRobert Mustacchi
3964eef4f27bSRobert Mustacchi REG_WR(
3965eef4f27bSRobert Mustacchi pdev,
3966eef4f27bSRobert Mustacchi pci_config.pcicfg_status_bit_clear_cmd,
3967eef4f27bSRobert Mustacchi deasserted_attns);
3968eef4f27bSRobert Mustacchi }
3969eef4f27bSRobert Mustacchi }
3970eef4f27bSRobert Mustacchi
3971eef4f27bSRobert Mustacchi if(link_chng || force_service_int || pdev->params.enable_remote_phy)
3972eef4f27bSRobert Mustacchi {
3973eef4f27bSRobert Mustacchi (void) lm_init_mac_link(pdev);
3974eef4f27bSRobert Mustacchi
3975eef4f27bSRobert Mustacchi mm_indicate_link(pdev, pdev->vars.link_status, pdev->vars.medium);
3976eef4f27bSRobert Mustacchi }
3977eef4f27bSRobert Mustacchi } /* lm_service_phy_int */
3978eef4f27bSRobert Mustacchi
3979eef4f27bSRobert Mustacchi
3980eef4f27bSRobert Mustacchi
3981eef4f27bSRobert Mustacchi /*******************************************************************************
3982eef4f27bSRobert Mustacchi * Description:
3983eef4f27bSRobert Mustacchi *
3984eef4f27bSRobert Mustacchi * Return:
3985eef4f27bSRobert Mustacchi ******************************************************************************/
3986eef4f27bSRobert Mustacchi lm_medium_t
lm_get_medium(lm_device_t * pdev)3987eef4f27bSRobert Mustacchi lm_get_medium(
3988eef4f27bSRobert Mustacchi lm_device_t *pdev)
3989eef4f27bSRobert Mustacchi {
3990eef4f27bSRobert Mustacchi u32_t decode;
3991eef4f27bSRobert Mustacchi u32_t val;
3992eef4f27bSRobert Mustacchi
3993eef4f27bSRobert Mustacchi if(CHIP_REV(pdev) == CHIP_REV_IKOS)
3994eef4f27bSRobert Mustacchi {
3995eef4f27bSRobert Mustacchi return LM_MEDIUM_TYPE_NULL;
3996eef4f27bSRobert Mustacchi }
3997eef4f27bSRobert Mustacchi
3998eef4f27bSRobert Mustacchi if(CHIP_REV(pdev) == CHIP_REV_FPGA)
3999eef4f27bSRobert Mustacchi {
4000eef4f27bSRobert Mustacchi return LM_MEDIUM_TYPE_UTP;
4001eef4f27bSRobert Mustacchi }
4002eef4f27bSRobert Mustacchi
4003eef4f27bSRobert Mustacchi if(CHIP_NUM(pdev) == CHIP_NUM_5706 || CHIP_NUM(pdev) == CHIP_NUM_5708)
4004eef4f27bSRobert Mustacchi {
4005eef4f27bSRobert Mustacchi if(CHIP_BOND_ID(pdev) & CHIP_BOND_ID_SERDES_BIT)
4006eef4f27bSRobert Mustacchi {
4007eef4f27bSRobert Mustacchi return LM_MEDIUM_TYPE_FIBER;
4008eef4f27bSRobert Mustacchi }
4009eef4f27bSRobert Mustacchi
4010eef4f27bSRobert Mustacchi return LM_MEDIUM_TYPE_UTP;
4011eef4f27bSRobert Mustacchi }
4012eef4f27bSRobert Mustacchi
4013eef4f27bSRobert Mustacchi if(CHIP_NUM(pdev) == CHIP_NUM_5709)
4014eef4f27bSRobert Mustacchi {
4015eef4f27bSRobert Mustacchi REG_RD(pdev, misc.misc_dual_media_ctrl, &val);
4016eef4f27bSRobert Mustacchi
4017eef4f27bSRobert Mustacchi if((val & MISC_DUAL_MEDIA_CTRL_BOND_ID) ==
4018eef4f27bSRobert Mustacchi MISC_DUAL_MEDIA_CTRL_BOND_ID_C)
4019eef4f27bSRobert Mustacchi {
4020eef4f27bSRobert Mustacchi return LM_MEDIUM_TYPE_UTP;
4021eef4f27bSRobert Mustacchi }
4022eef4f27bSRobert Mustacchi
4023eef4f27bSRobert Mustacchi if((val & MISC_DUAL_MEDIA_CTRL_BOND_ID) ==
4024eef4f27bSRobert Mustacchi MISC_DUAL_MEDIA_CTRL_BOND_ID_S)
4025eef4f27bSRobert Mustacchi {
4026eef4f27bSRobert Mustacchi return LM_MEDIUM_TYPE_FIBER;
4027eef4f27bSRobert Mustacchi }
4028eef4f27bSRobert Mustacchi
4029eef4f27bSRobert Mustacchi /* mac to phy/serdes decode.
4030eef4f27bSRobert Mustacchi * swap strap mac0 mac1
4031eef4f27bSRobert Mustacchi * ==== ===== ==== ====
4032eef4f27bSRobert Mustacchi * 0 000 phy0 phy1
4033eef4f27bSRobert Mustacchi * 0 001 phy0 ser0
4034eef4f27bSRobert Mustacchi * 0 010 phy0 ser1
4035eef4f27bSRobert Mustacchi * 0 110 ser0 phy0
4036eef4f27bSRobert Mustacchi * 0 101 ser0 phy1
4037eef4f27bSRobert Mustacchi * 0 100 ser0 ser1
4038eef4f27bSRobert Mustacchi *
4039eef4f27bSRobert Mustacchi * 1 000 phy1 phy0
4040eef4f27bSRobert Mustacchi * 1 001 phy1 ser1
4041eef4f27bSRobert Mustacchi * 1 010 phy1 ser0
4042eef4f27bSRobert Mustacchi * 1 110 ser1 phy1
4043eef4f27bSRobert Mustacchi * 1 101 ser1 phy0
4044eef4f27bSRobert Mustacchi * 1 100 ser1 ser0 */
4045eef4f27bSRobert Mustacchi if(val & MISC_DUAL_MEDIA_CTRL_STRAP_OVERRIDE)
4046eef4f27bSRobert Mustacchi {
4047eef4f27bSRobert Mustacchi decode = (val & MISC_DUAL_MEDIA_CTRL_PHY_CTRL) >> 21;
4048eef4f27bSRobert Mustacchi
4049eef4f27bSRobert Mustacchi if(val & MISC_DUAL_MEDIA_CTRL_PORT_SWAP)
4050eef4f27bSRobert Mustacchi {
4051eef4f27bSRobert Mustacchi decode |= 0x8;
4052eef4f27bSRobert Mustacchi }
4053eef4f27bSRobert Mustacchi }
4054eef4f27bSRobert Mustacchi else
4055eef4f27bSRobert Mustacchi {
4056eef4f27bSRobert Mustacchi decode = (val & MISC_DUAL_MEDIA_CTRL_PHY_CTRL_STRAP) >> 8;
4057eef4f27bSRobert Mustacchi
4058eef4f27bSRobert Mustacchi if(val & MISC_DUAL_MEDIA_CTRL_PORT_SWAP_PIN)
4059eef4f27bSRobert Mustacchi {
4060eef4f27bSRobert Mustacchi decode |= 0x8;
4061eef4f27bSRobert Mustacchi }
4062eef4f27bSRobert Mustacchi }
4063eef4f27bSRobert Mustacchi
4064eef4f27bSRobert Mustacchi decode |= pdev->hw_info.mac_id << 4;
4065eef4f27bSRobert Mustacchi
4066eef4f27bSRobert Mustacchi /* mac:4, swap:3, strap:2-0. */
4067eef4f27bSRobert Mustacchi switch(decode)
4068eef4f27bSRobert Mustacchi {
4069eef4f27bSRobert Mustacchi case 0x00: /* 00000 - mac0, phy0 */
4070eef4f27bSRobert Mustacchi case 0x01: /* 00001 - mac0, phy0 */
4071eef4f27bSRobert Mustacchi case 0x02: /* 00010 - mac0, phy0 */
4072eef4f27bSRobert Mustacchi case 0x08: /* 01000 - mac0, phy1 */
4073eef4f27bSRobert Mustacchi case 0x09: /* 01001 - mac0, phy1 */
4074eef4f27bSRobert Mustacchi case 0x0a: /* 01010 - mac0, phy1 */
4075eef4f27bSRobert Mustacchi case 0x10: /* 10000 - mac1, phy1 */
4076eef4f27bSRobert Mustacchi case 0x15: /* 10101 - mac1, phy1 */
4077eef4f27bSRobert Mustacchi case 0x16: /* 10110 - mac1, phy0 */
4078eef4f27bSRobert Mustacchi case 0x18: /* 11000 - mac1, phy0 */
4079eef4f27bSRobert Mustacchi case 0x1d: /* 11101 - mac1, phy0 */
4080eef4f27bSRobert Mustacchi case 0x1e: /* 11110 - mac1, phy1 */
4081eef4f27bSRobert Mustacchi return LM_MEDIUM_TYPE_UTP;
4082eef4f27bSRobert Mustacchi
4083eef4f27bSRobert Mustacchi case 0x04: /* 00100 - mac0, ser0 */
4084eef4f27bSRobert Mustacchi case 0x05: /* 00101 - mac0, ser0 */
4085eef4f27bSRobert Mustacchi case 0x06: /* 00110 - mac0, ser0 */
4086eef4f27bSRobert Mustacchi case 0x0c: /* 01100 - mac0, ser1 */
4087eef4f27bSRobert Mustacchi case 0x0d: /* 01101 - mac0, ser1 */
4088eef4f27bSRobert Mustacchi case 0x0e: /* 01110 - mac0, ser1 */
4089eef4f27bSRobert Mustacchi case 0x11: /* 10001 - mac1, ser0 */
4090eef4f27bSRobert Mustacchi case 0x12: /* 10010 - mac1, ser1 */
4091eef4f27bSRobert Mustacchi case 0x14: /* 10100 - mac1, ser1 */
4092eef4f27bSRobert Mustacchi case 0x19: /* 11001 - mac1, ser1 */
4093eef4f27bSRobert Mustacchi case 0x1a: /* 11010 - mac1, ser0 */
4094eef4f27bSRobert Mustacchi case 0x1c: /* 11100 - mac1, ser0 */
4095eef4f27bSRobert Mustacchi return LM_MEDIUM_TYPE_FIBER;
4096eef4f27bSRobert Mustacchi }
4097eef4f27bSRobert Mustacchi }
4098eef4f27bSRobert Mustacchi
4099eef4f27bSRobert Mustacchi return LM_MEDIUM_TYPE_NULL;
4100eef4f27bSRobert Mustacchi } /* lm_get_medium */
4101