net/ice: fix build when Rx descriptor size is 16
[dpdk.git] / drivers / net / ngbe / base / ngbe_phy_rtl.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2018-2021 Beijing WangXun Technology Co., Ltd.
3  */
4
5 #include "ngbe_phy_rtl.h"
6
7 #define RTL_PHY_RST_WAIT_PERIOD               5
8
9 s32 ngbe_read_phy_reg_rtl(struct ngbe_hw *hw,
10                 u32 reg_addr, u32 device_type, u16 *phy_data)
11 {
12         mdi_reg_t reg;
13         mdi_reg_22_t reg22;
14
15         reg.device_type = device_type;
16         reg.addr = reg_addr;
17         ngbe_mdi_map_register(&reg, &reg22);
18
19         wr32(hw, NGBE_PHY_CONFIG(RTL_PAGE_SELECT), reg22.page);
20         *phy_data = 0xFFFF & rd32(hw, NGBE_PHY_CONFIG(reg22.addr));
21
22         return 0;
23 }
24
25 s32 ngbe_write_phy_reg_rtl(struct ngbe_hw *hw,
26                 u32 reg_addr, u32 device_type, u16 phy_data)
27 {
28         mdi_reg_t reg;
29         mdi_reg_22_t reg22;
30
31         reg.device_type = device_type;
32         reg.addr = reg_addr;
33         ngbe_mdi_map_register(&reg, &reg22);
34
35         wr32(hw, NGBE_PHY_CONFIG(RTL_PAGE_SELECT), reg22.page);
36         wr32(hw, NGBE_PHY_CONFIG(reg22.addr), phy_data);
37
38         return 0;
39 }
40
41 s32 ngbe_init_phy_rtl(struct ngbe_hw *hw)
42 {
43         int i;
44         u16 value = 0;
45
46         /* enable interrupts, only link status change and an done is allowed */
47         value = RTL_INER_LSC | RTL_INER_ANC;
48         hw->phy.write_reg(hw, RTL_INER, 0xa42, value);
49
50         hw->phy.read_reg(hw, RTL_INSR, 0xa43, &value);
51
52         for (i = 0; i < 15; i++) {
53                 if (!rd32m(hw, NGBE_STAT,
54                         NGBE_STAT_GPHY_IN_RST(hw->bus.lan_id)))
55                         break;
56
57                 msec_delay(10);
58         }
59         if (i == 15) {
60                 DEBUGOUT("GPhy reset exceeds maximum times.\n");
61                 return NGBE_ERR_PHY_TIMEOUT;
62         }
63
64         for (i = 0; i < 1000; i++) {
65                 hw->phy.read_reg(hw, RTL_INSR, 0xa43, &value);
66                 if (value & RTL_INSR_ACCESS)
67                         break;
68         }
69
70         hw->phy.write_reg(hw, RTL_SCR, 0xa46, RTL_SCR_EFUSE);
71         for (i = 0; i < 1000; i++) {
72                 hw->phy.read_reg(hw, RTL_INSR, 0xa43, &value);
73                 if (value & RTL_INSR_ACCESS)
74                         break;
75         }
76         if (i == 1000)
77                 return NGBE_ERR_PHY_TIMEOUT;
78
79         hw->phy.write_reg(hw, RTL_SCR, 0xa46, RTL_SCR_EXTINI);
80         for (i = 0; i < 1000; i++) {
81                 hw->phy.read_reg(hw, RTL_INSR, 0xa43, &value);
82                 if (value & RTL_INSR_ACCESS)
83                         break;
84         }
85         if (i == 1000)
86                 return NGBE_ERR_PHY_TIMEOUT;
87
88         for (i = 0; i < 1000; i++) {
89                 hw->phy.read_reg(hw, RTL_GSR, 0xa42, &value);
90                 if ((value & RTL_GSR_ST) == RTL_GSR_ST_LANON)
91                         break;
92         }
93         if (i == 1000)
94                 return NGBE_ERR_PHY_TIMEOUT;
95
96         return 0;
97 }
98
99 /**
100  *  ngbe_setup_phy_link_rtl - Set and restart auto-neg
101  *  @hw: pointer to hardware structure
102  *
103  *  Restart auto-negotiation and PHY and waits for completion.
104  **/
105 s32 ngbe_setup_phy_link_rtl(struct ngbe_hw *hw,
106                 u32 speed, bool autoneg_wait_to_complete)
107 {
108         u16 autoneg_reg = NGBE_MII_AUTONEG_REG;
109         u16 value = 0;
110
111         DEBUGFUNC("ngbe_setup_phy_link_rtl");
112
113         UNREFERENCED_PARAMETER(autoneg_wait_to_complete);
114
115         hw->phy.read_reg(hw, RTL_INSR, 0xa43, &autoneg_reg);
116
117         if (!hw->mac.autoneg) {
118                 hw->phy.reset_hw(hw);
119
120                 switch (speed) {
121                 case NGBE_LINK_SPEED_1GB_FULL:
122                         value = RTL_BMCR_SPEED_SELECT1;
123                         break;
124                 case NGBE_LINK_SPEED_100M_FULL:
125                         value = RTL_BMCR_SPEED_SELECT0;
126                         break;
127                 case NGBE_LINK_SPEED_10M_FULL:
128                         value = 0;
129                         break;
130                 default:
131                         value = RTL_BMCR_SPEED_SELECT1 | RTL_BMCR_SPEED_SELECT0;
132                         DEBUGOUT("unknown speed = 0x%x.\n", speed);
133                         break;
134                 }
135                 /* duplex full */
136                 value |= RTL_BMCR_DUPLEX;
137                 hw->phy.write_reg(hw, RTL_BMCR, RTL_DEV_ZERO, value);
138
139                 goto skip_an;
140         }
141
142         /*
143          * Clear autoneg_advertised and set new values based on input link
144          * speed.
145          */
146         if (speed) {
147                 hw->phy.autoneg_advertised = 0;
148
149                 if (speed & NGBE_LINK_SPEED_1GB_FULL)
150                         hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_1GB_FULL;
151
152                 if (speed & NGBE_LINK_SPEED_100M_FULL)
153                         hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_100M_FULL;
154
155                 if (speed & NGBE_LINK_SPEED_10M_FULL)
156                         hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_10M_FULL;
157         }
158
159         /* disable 10/100M Half Duplex */
160         hw->phy.read_reg(hw, RTL_ANAR, RTL_DEV_ZERO, &autoneg_reg);
161         autoneg_reg &= 0xFF5F;
162         hw->phy.write_reg(hw, RTL_ANAR, RTL_DEV_ZERO, autoneg_reg);
163
164         /* set advertise enable according to input speed */
165         if (!(speed & NGBE_LINK_SPEED_1GB_FULL)) {
166                 hw->phy.read_reg(hw, RTL_GBCR,
167                         RTL_DEV_ZERO, &autoneg_reg);
168                 autoneg_reg &= ~RTL_GBCR_1000F;
169                 hw->phy.write_reg(hw, RTL_GBCR,
170                         RTL_DEV_ZERO, autoneg_reg);
171         } else {
172                 hw->phy.read_reg(hw, RTL_GBCR,
173                         RTL_DEV_ZERO, &autoneg_reg);
174                 autoneg_reg |= RTL_GBCR_1000F;
175                 hw->phy.write_reg(hw, RTL_GBCR,
176                         RTL_DEV_ZERO, autoneg_reg);
177         }
178
179         if (!(speed & NGBE_LINK_SPEED_100M_FULL)) {
180                 hw->phy.read_reg(hw, RTL_ANAR,
181                         RTL_DEV_ZERO, &autoneg_reg);
182                 autoneg_reg &= ~RTL_ANAR_100F;
183                 autoneg_reg &= ~RTL_ANAR_100H;
184                 hw->phy.write_reg(hw, RTL_ANAR,
185                         RTL_DEV_ZERO, autoneg_reg);
186         } else {
187                 hw->phy.read_reg(hw, RTL_ANAR,
188                         RTL_DEV_ZERO, &autoneg_reg);
189                 autoneg_reg |= RTL_ANAR_100F;
190                 hw->phy.write_reg(hw, RTL_ANAR,
191                         RTL_DEV_ZERO, autoneg_reg);
192         }
193
194         if (!(speed & NGBE_LINK_SPEED_10M_FULL)) {
195                 hw->phy.read_reg(hw, RTL_ANAR,
196                         RTL_DEV_ZERO, &autoneg_reg);
197                 autoneg_reg &= ~RTL_ANAR_10F;
198                 autoneg_reg &= ~RTL_ANAR_10H;
199                 hw->phy.write_reg(hw, RTL_ANAR,
200                         RTL_DEV_ZERO, autoneg_reg);
201         } else {
202                 hw->phy.read_reg(hw, RTL_ANAR,
203                         RTL_DEV_ZERO, &autoneg_reg);
204                 autoneg_reg |= RTL_ANAR_10F;
205                 hw->phy.write_reg(hw, RTL_ANAR,
206                         RTL_DEV_ZERO, autoneg_reg);
207         }
208
209         /* restart AN and wait AN done interrupt */
210         autoneg_reg = RTL_BMCR_RESTART_AN | RTL_BMCR_ANE;
211         hw->phy.write_reg(hw, RTL_BMCR, RTL_DEV_ZERO, autoneg_reg);
212
213 skip_an:
214         autoneg_reg = 0x205B;
215         hw->phy.write_reg(hw, RTL_LCR, 0xd04, autoneg_reg);
216         hw->phy.write_reg(hw, RTL_EEELCR, 0xd04, 0);
217
218         hw->phy.read_reg(hw, RTL_LPCR, 0xd04, &autoneg_reg);
219         autoneg_reg = autoneg_reg & 0xFFFC;
220         /* act led blinking mode set to 60ms */
221         autoneg_reg |= 0x2;
222         hw->phy.write_reg(hw, RTL_LPCR, 0xd04, autoneg_reg);
223
224         return 0;
225 }
226
227 s32 ngbe_reset_phy_rtl(struct ngbe_hw *hw)
228 {
229         u16 value = 0, i;
230         s32 status = 0;
231
232         DEBUGFUNC("ngbe_reset_phy_rtl");
233
234         value |= RTL_BMCR_RESET;
235         status = hw->phy.write_reg(hw, RTL_BMCR, RTL_DEV_ZERO, value);
236
237         for (i = 0; i < RTL_PHY_RST_WAIT_PERIOD; i++) {
238                 status = hw->phy.read_reg(hw, RTL_BMCR, RTL_DEV_ZERO, &value);
239                 if (!(value & RTL_BMCR_RESET))
240                         break;
241                 msleep(1);
242         }
243
244         if (i == RTL_PHY_RST_WAIT_PERIOD) {
245                 DEBUGOUT("PHY reset polling failed to complete.\n");
246                 return NGBE_ERR_RESET_FAILED;
247         }
248
249         return status;
250 }
251
252 s32 ngbe_check_phy_link_rtl(struct ngbe_hw *hw, u32 *speed, bool *link_up)
253 {
254         s32 status = 0;
255         u16 phy_link = 0;
256         u16 phy_speed = 0;
257         u16 phy_data = 0;
258         u16 insr = 0;
259
260         DEBUGFUNC("ngbe_check_phy_link_rtl");
261
262         hw->phy.read_reg(hw, RTL_INSR, 0xa43, &insr);
263
264         /* Initialize speed and link to default case */
265         *link_up = false;
266         *speed = NGBE_LINK_SPEED_UNKNOWN;
267
268         /*
269          * Check current speed and link status of the PHY register.
270          * This is a vendor specific register and may have to
271          * be changed for other copper PHYs.
272          */
273         status = hw->phy.read_reg(hw, RTL_PHYSR, 0xa43, &phy_data);
274         phy_link = phy_data & RTL_PHYSR_RTLS;
275         phy_speed = phy_data & (RTL_PHYSR_SPEED_MASK | RTL_PHYSR_DP);
276         if (phy_link == RTL_PHYSR_RTLS) {
277                 *link_up = true;
278
279                 if (phy_speed == (RTL_PHYSR_SPEED_1000M | RTL_PHYSR_DP))
280                         *speed = NGBE_LINK_SPEED_1GB_FULL;
281                 else if (phy_speed == (RTL_PHYSR_SPEED_100M | RTL_PHYSR_DP))
282                         *speed = NGBE_LINK_SPEED_100M_FULL;
283                 else if (phy_speed == (RTL_PHYSR_SPEED_10M | RTL_PHYSR_DP))
284                         *speed = NGBE_LINK_SPEED_10M_FULL;
285         }
286
287         return status;
288 }
289