net/ngbe: support RSS hash
[dpdk.git] / drivers / net / ngbe / base / ngbe_phy_yt.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2018-2021 Beijing WangXun Technology Co., Ltd.
3  */
4
5 #include "ngbe_phy_yt.h"
6
7 #define YT_PHY_RST_WAIT_PERIOD          5
8
9 s32 ngbe_read_phy_reg_yt(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
18         ngbe_mdi_map_register(&reg, &reg22);
19
20         /* Read MII reg according to media type */
21         if (hw->phy.media_type == ngbe_media_type_fiber) {
22                 ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY,
23                                         reg22.device_type, YT_SMI_PHY_SDS);
24                 ngbe_read_phy_reg_mdi(hw, reg22.addr,
25                                         reg22.device_type, phy_data);
26                 ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY,
27                                         reg22.device_type, 0);
28         } else {
29                 ngbe_read_phy_reg_mdi(hw, reg22.addr,
30                                         reg22.device_type, phy_data);
31         }
32
33         return 0;
34 }
35
36 s32 ngbe_write_phy_reg_yt(struct ngbe_hw *hw,
37                 u32 reg_addr, u32 device_type, u16 phy_data)
38 {
39         mdi_reg_t reg;
40         mdi_reg_22_t reg22;
41
42         reg.device_type = device_type;
43         reg.addr = reg_addr;
44
45         ngbe_mdi_map_register(&reg, &reg22);
46
47         /* Write MII reg according to media type */
48         if (hw->phy.media_type == ngbe_media_type_fiber) {
49                 ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY,
50                                         reg22.device_type, YT_SMI_PHY_SDS);
51                 ngbe_write_phy_reg_mdi(hw, reg22.addr,
52                                         reg22.device_type, phy_data);
53                 ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY,
54                                         reg22.device_type, 0);
55         } else {
56                 ngbe_write_phy_reg_mdi(hw, reg22.addr,
57                                         reg22.device_type, phy_data);
58         }
59
60         return 0;
61 }
62
63 s32 ngbe_read_phy_reg_ext_yt(struct ngbe_hw *hw,
64                 u32 reg_addr, u32 device_type, u16 *phy_data)
65 {
66         ngbe_write_phy_reg_mdi(hw, 0x1E, device_type, reg_addr);
67         ngbe_read_phy_reg_mdi(hw, 0x1F, device_type, phy_data);
68
69         return 0;
70 }
71
72 s32 ngbe_write_phy_reg_ext_yt(struct ngbe_hw *hw,
73                 u32 reg_addr, u32 device_type, u16 phy_data)
74 {
75         ngbe_write_phy_reg_mdi(hw, 0x1E, device_type, reg_addr);
76         ngbe_write_phy_reg_mdi(hw, 0x1F, device_type, phy_data);
77
78         return 0;
79 }
80
81 s32 ngbe_read_phy_reg_sds_ext_yt(struct ngbe_hw *hw,
82                 u32 reg_addr, u32 device_type, u16 *phy_data)
83 {
84         ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY, device_type, YT_SMI_PHY_SDS);
85         ngbe_read_phy_reg_ext_yt(hw, reg_addr, device_type, phy_data);
86         ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY, device_type, 0);
87
88         return 0;
89 }
90
91 s32 ngbe_write_phy_reg_sds_ext_yt(struct ngbe_hw *hw,
92                 u32 reg_addr, u32 device_type, u16 phy_data)
93 {
94         ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY, device_type, YT_SMI_PHY_SDS);
95         ngbe_write_phy_reg_ext_yt(hw, reg_addr, device_type, phy_data);
96         ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY, device_type, 0);
97
98         return 0;
99 }
100
101 s32 ngbe_init_phy_yt(struct ngbe_hw *hw)
102 {
103         u16 value = 0;
104
105         DEBUGFUNC("ngbe_init_phy_yt");
106
107         if (hw->phy.type != ngbe_phy_yt8521s_sfi)
108                 return 0;
109
110         /* select sds area register */
111         ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY, 0, 0);
112         /* enable interrupts */
113         ngbe_write_phy_reg_mdi(hw, YT_INTR, 0, YT_INTR_ENA_MASK);
114
115         /* select fiber_to_rgmii first in multiplex */
116         ngbe_read_phy_reg_ext_yt(hw, YT_MISC, 0, &value);
117         value |= YT_MISC_FIBER_PRIO;
118         ngbe_write_phy_reg_ext_yt(hw, YT_MISC, 0, value);
119
120         hw->phy.read_reg(hw, YT_BCR, 0, &value);
121         value |= YT_BCR_PWDN;
122         hw->phy.write_reg(hw, YT_BCR, 0, value);
123
124         return 0;
125 }
126
127 s32 ngbe_setup_phy_link_yt(struct ngbe_hw *hw, u32 speed,
128                                 bool autoneg_wait_to_complete)
129 {
130         u16 value_r4 = 0;
131         u16 value_r9 = 0;
132         u16 value;
133
134         DEBUGFUNC("ngbe_setup_phy_link_yt");
135         UNREFERENCED_PARAMETER(autoneg_wait_to_complete);
136
137         hw->phy.autoneg_advertised = 0;
138
139         if (hw->phy.type == ngbe_phy_yt8521s) {
140                 /*disable 100/10base-T Self-negotiation ability*/
141                 hw->phy.read_reg(hw, YT_ANA, 0, &value);
142                 value &= ~(YT_ANA_100BASET_FULL | YT_ANA_10BASET_FULL);
143                 hw->phy.write_reg(hw, YT_ANA, 0, value);
144
145                 /*disable 1000base-T Self-negotiation ability*/
146                 hw->phy.read_reg(hw, YT_MS_CTRL, 0, &value);
147                 value &= ~YT_MS_1000BASET_FULL;
148                 hw->phy.write_reg(hw, YT_MS_CTRL, 0, value);
149
150                 if (speed & NGBE_LINK_SPEED_1GB_FULL) {
151                         hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_1GB_FULL;
152                         value_r9 |= YT_MS_1000BASET_FULL;
153                 }
154                 if (speed & NGBE_LINK_SPEED_100M_FULL) {
155                         hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_100M_FULL;
156                         value_r4 |= YT_ANA_100BASET_FULL;
157                 }
158                 if (speed & NGBE_LINK_SPEED_10M_FULL) {
159                         hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_10M_FULL;
160                         value_r4 |= YT_ANA_10BASET_FULL;
161                 }
162
163                 /* enable 1000base-T Self-negotiation ability */
164                 hw->phy.read_reg(hw, YT_MS_CTRL, 0, &value);
165                 value |= value_r9;
166                 hw->phy.write_reg(hw, YT_MS_CTRL, 0, value);
167
168                 /* enable 100/10base-T Self-negotiation ability */
169                 hw->phy.read_reg(hw, YT_ANA, 0, &value);
170                 value |= value_r4;
171                 hw->phy.write_reg(hw, YT_ANA, 0, value);
172
173                 /* software reset to make the above configuration take effect*/
174                 hw->phy.read_reg(hw, YT_BCR, 0, &value);
175                 value |= YT_BCR_RESET;
176                 hw->phy.write_reg(hw, YT_BCR, 0, value);
177         } else {
178                 hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_1GB_FULL;
179
180                 /* RGMII_Config1 : Config rx and tx training delay */
181                 value = YT_RGMII_CONF1_RXDELAY |
182                         YT_RGMII_CONF1_TXDELAY_FE |
183                         YT_RGMII_CONF1_TXDELAY;
184                 ngbe_write_phy_reg_ext_yt(hw, YT_RGMII_CONF1, 0, value);
185                 value = YT_CHIP_MODE_SEL(1) |
186                         YT_CHIP_SW_LDO_EN |
187                         YT_CHIP_SW_RST;
188                 ngbe_write_phy_reg_ext_yt(hw, YT_CHIP, 0, value);
189
190                 /* software reset */
191                 ngbe_write_phy_reg_sds_ext_yt(hw, 0x0, 0, 0x9140);
192
193                 /* power on phy */
194                 hw->phy.read_reg(hw, YT_BCR, 0, &value);
195                 value &= ~YT_BCR_PWDN;
196                 hw->phy.write_reg(hw, YT_BCR, 0, value);
197         }
198
199         ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY, 0, 0);
200         ngbe_read_phy_reg_mdi(hw, YT_INTR_STATUS, 0, &value);
201
202         return 0;
203 }
204
205 s32 ngbe_reset_phy_yt(struct ngbe_hw *hw)
206 {
207         u32 i;
208         u16 ctrl = 0;
209         s32 status = 0;
210
211         DEBUGFUNC("ngbe_reset_phy_yt");
212
213         if (hw->phy.type != ngbe_phy_yt8521s &&
214                 hw->phy.type != ngbe_phy_yt8521s_sfi)
215                 return NGBE_ERR_PHY_TYPE;
216
217         status = hw->phy.read_reg(hw, YT_BCR, 0, &ctrl);
218         /* sds software reset */
219         ctrl |= YT_BCR_RESET;
220         status = hw->phy.write_reg(hw, YT_BCR, 0, ctrl);
221
222         for (i = 0; i < YT_PHY_RST_WAIT_PERIOD; i++) {
223                 status = hw->phy.read_reg(hw, YT_BCR, 0, &ctrl);
224                 if (!(ctrl & YT_BCR_RESET))
225                         break;
226                 msleep(1);
227         }
228
229         if (i == YT_PHY_RST_WAIT_PERIOD) {
230                 DEBUGOUT("PHY reset polling failed to complete.\n");
231                 return NGBE_ERR_RESET_FAILED;
232         }
233
234         return status;
235 }
236
237 s32 ngbe_check_phy_link_yt(struct ngbe_hw *hw,
238                 u32 *speed, bool *link_up)
239 {
240         s32 status = 0;
241         u16 phy_link = 0;
242         u16 phy_speed = 0;
243         u16 phy_data = 0;
244         u16 insr = 0;
245
246         DEBUGFUNC("ngbe_check_phy_link_yt");
247
248         /* Initialize speed and link to default case */
249         *link_up = false;
250         *speed = NGBE_LINK_SPEED_UNKNOWN;
251
252         ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY, 0, 0);
253         ngbe_read_phy_reg_mdi(hw, YT_INTR_STATUS, 0, &insr);
254
255         status = hw->phy.read_reg(hw, YT_SPST, 0, &phy_data);
256         phy_link = phy_data & YT_SPST_LINK;
257         phy_speed = phy_data & YT_SPST_SPEED_MASK;
258
259         if (phy_link) {
260                 *link_up = true;
261
262                 if (phy_speed == YT_SPST_SPEED_1000M)
263                         *speed = NGBE_LINK_SPEED_1GB_FULL;
264                 else if (phy_speed == YT_SPST_SPEED_100M)
265                         *speed = NGBE_LINK_SPEED_100M_FULL;
266                 else if (phy_speed == YT_SPST_SPEED_10M)
267                         *speed = NGBE_LINK_SPEED_10M_FULL;
268         }
269
270         return status;
271 }
272