1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /**************************************************************************** |
3 | * Driver for Solarflare network controllers and boards |
4 | * Copyright 2006-2011 Solarflare Communications Inc. |
5 | */ |
6 | |
7 | /* |
8 | * Driver for Transwitch/Mysticom CX4 retimer |
9 | * see www.transwitch.com, part is TXC-43128 |
10 | */ |
11 | |
12 | #include <linux/delay.h> |
13 | #include <linux/slab.h> |
14 | #include "efx.h" |
15 | #include "mdio_10g.h" |
16 | #include "phy.h" |
17 | #include "nic.h" |
18 | |
19 | /* We expect these MMDs to be in the package */ |
20 | #define TXC_REQUIRED_DEVS (MDIO_DEVS_PCS | \ |
21 | MDIO_DEVS_PMAPMD | \ |
22 | MDIO_DEVS_PHYXS) |
23 | |
24 | #define TXC_LOOPBACKS ((1 << LOOPBACK_PCS) | \ |
25 | (1 << LOOPBACK_PMAPMD) | \ |
26 | (1 << LOOPBACK_PHYXS_WS)) |
27 | |
28 | /************************************************************************** |
29 | * |
30 | * Compile-time config |
31 | * |
32 | ************************************************************************** |
33 | */ |
34 | #define TXCNAME "TXC43128" |
35 | /* Total length of time we'll wait for the PHY to come out of reset (ms) */ |
36 | #define TXC_MAX_RESET_TIME 500 |
37 | /* Interval between checks (ms) */ |
38 | #define TXC_RESET_WAIT 10 |
39 | /* How long to run BIST (us) */ |
40 | #define TXC_BIST_DURATION 50 |
41 | |
42 | /************************************************************************** |
43 | * |
44 | * Register definitions |
45 | * |
46 | ************************************************************************** |
47 | */ |
48 | |
49 | /* Command register */ |
50 | #define TXC_GLRGS_GLCMD 0xc004 |
51 | /* Useful bits in command register */ |
52 | /* Lane power-down */ |
53 | #define TXC_GLCMD_L01PD_LBN 5 |
54 | #define TXC_GLCMD_L23PD_LBN 6 |
55 | /* Limited SW reset: preserves configuration but |
56 | * initiates a logic reset. Self-clearing */ |
57 | #define TXC_GLCMD_LMTSWRST_LBN 14 |
58 | |
59 | /* Signal Quality Control */ |
60 | #define TXC_GLRGS_GSGQLCTL 0xc01a |
61 | /* Enable bit */ |
62 | #define TXC_GSGQLCT_SGQLEN_LBN 15 |
63 | /* Lane selection */ |
64 | #define TXC_GSGQLCT_LNSL_LBN 13 |
65 | #define TXC_GSGQLCT_LNSL_WIDTH 2 |
66 | |
67 | /* Analog TX control */ |
68 | #define TXC_ALRGS_ATXCTL 0xc040 |
69 | /* Lane power-down */ |
70 | #define TXC_ATXCTL_TXPD3_LBN 15 |
71 | #define TXC_ATXCTL_TXPD2_LBN 14 |
72 | #define TXC_ATXCTL_TXPD1_LBN 13 |
73 | #define TXC_ATXCTL_TXPD0_LBN 12 |
74 | |
75 | /* Amplitude on lanes 0, 1 */ |
76 | #define TXC_ALRGS_ATXAMP0 0xc041 |
77 | /* Amplitude on lanes 2, 3 */ |
78 | #define TXC_ALRGS_ATXAMP1 0xc042 |
79 | /* Bit position of value for lane 0 (or 2) */ |
80 | #define TXC_ATXAMP_LANE02_LBN 3 |
81 | /* Bit position of value for lane 1 (or 3) */ |
82 | #define TXC_ATXAMP_LANE13_LBN 11 |
83 | |
84 | #define TXC_ATXAMP_1280_mV 0 |
85 | #define TXC_ATXAMP_1200_mV 8 |
86 | #define TXC_ATXAMP_1120_mV 12 |
87 | #define TXC_ATXAMP_1060_mV 14 |
88 | #define TXC_ATXAMP_0820_mV 25 |
89 | #define TXC_ATXAMP_0720_mV 26 |
90 | #define TXC_ATXAMP_0580_mV 27 |
91 | #define TXC_ATXAMP_0440_mV 28 |
92 | |
93 | #define TXC_ATXAMP_0820_BOTH \ |
94 | ((TXC_ATXAMP_0820_mV << TXC_ATXAMP_LANE02_LBN) \ |
95 | | (TXC_ATXAMP_0820_mV << TXC_ATXAMP_LANE13_LBN)) |
96 | |
97 | #define TXC_ATXAMP_DEFAULT 0x6060 /* From databook */ |
98 | |
99 | /* Preemphasis on lanes 0, 1 */ |
100 | #define TXC_ALRGS_ATXPRE0 0xc043 |
101 | /* Preemphasis on lanes 2, 3 */ |
102 | #define TXC_ALRGS_ATXPRE1 0xc044 |
103 | |
104 | #define TXC_ATXPRE_NONE 0 |
105 | #define TXC_ATXPRE_DEFAULT 0x1010 /* From databook */ |
106 | |
107 | #define TXC_ALRGS_ARXCTL 0xc045 |
108 | /* Lane power-down */ |
109 | #define TXC_ARXCTL_RXPD3_LBN 15 |
110 | #define TXC_ARXCTL_RXPD2_LBN 14 |
111 | #define TXC_ARXCTL_RXPD1_LBN 13 |
112 | #define TXC_ARXCTL_RXPD0_LBN 12 |
113 | |
114 | /* Main control */ |
115 | #define TXC_MRGS_CTL 0xc340 |
116 | /* Bits in main control */ |
117 | #define TXC_MCTL_RESET_LBN 15 /* Self clear */ |
118 | #define TXC_MCTL_TXLED_LBN 14 /* 1 to show align status */ |
119 | #define TXC_MCTL_RXLED_LBN 13 /* 1 to show align status */ |
120 | |
121 | /* GPIO output */ |
122 | #define TXC_GPIO_OUTPUT 0xc346 |
123 | #define TXC_GPIO_DIR 0xc348 |
124 | |
125 | /* Vendor-specific BIST registers */ |
126 | #define TXC_BIST_CTL 0xc280 |
127 | #define TXC_BIST_TXFRMCNT 0xc281 |
128 | #define TXC_BIST_RX0FRMCNT 0xc282 |
129 | #define TXC_BIST_RX1FRMCNT 0xc283 |
130 | #define TXC_BIST_RX2FRMCNT 0xc284 |
131 | #define TXC_BIST_RX3FRMCNT 0xc285 |
132 | #define TXC_BIST_RX0ERRCNT 0xc286 |
133 | #define TXC_BIST_RX1ERRCNT 0xc287 |
134 | #define TXC_BIST_RX2ERRCNT 0xc288 |
135 | #define TXC_BIST_RX3ERRCNT 0xc289 |
136 | |
137 | /* BIST type (controls bit patter in test) */ |
138 | #define TXC_BIST_CTRL_TYPE_LBN 10 |
139 | #define TXC_BIST_CTRL_TYPE_TSD 0 /* TranSwitch Deterministic */ |
140 | #define TXC_BIST_CTRL_TYPE_CRP 1 /* CRPAT standard */ |
141 | #define TXC_BIST_CTRL_TYPE_CJP 2 /* CJPAT standard */ |
142 | #define TXC_BIST_CTRL_TYPE_TSR 3 /* TranSwitch pseudo-random */ |
143 | /* Set this to 1 for 10 bit and 0 for 8 bit */ |
144 | #define TXC_BIST_CTRL_B10EN_LBN 12 |
145 | /* Enable BIST (write 0 to disable) */ |
146 | #define TXC_BIST_CTRL_ENAB_LBN 13 |
147 | /* Stop BIST (self-clears when stop complete) */ |
148 | #define TXC_BIST_CTRL_STOP_LBN 14 |
149 | /* Start BIST (cleared by writing 1 to STOP) */ |
150 | #define TXC_BIST_CTRL_STRT_LBN 15 |
151 | |
152 | /* Mt. Diablo test configuration */ |
153 | #define TXC_MTDIABLO_CTRL 0xc34f |
154 | #define TXC_MTDIABLO_CTRL_PMA_LOOP_LBN 10 |
155 | |
156 | struct txc43128_data { |
157 | unsigned long bug10934_timer; |
158 | enum ef4_phy_mode phy_mode; |
159 | enum ef4_loopback_mode loopback_mode; |
160 | }; |
161 | |
162 | /* The PHY sometimes needs a reset to bring the link back up. So long as |
163 | * it reports link down, we reset it every 5 seconds. |
164 | */ |
165 | #define BUG10934_RESET_INTERVAL (5 * HZ) |
166 | |
167 | /* Perform a reset that doesn't clear configuration changes */ |
168 | static void txc_reset_logic(struct ef4_nic *efx); |
169 | |
170 | /* Set the output value of a gpio */ |
171 | void falcon_txc_set_gpio_val(struct ef4_nic *efx, int pin, int on) |
172 | { |
173 | ef4_mdio_set_flag(efx, MDIO_MMD_PHYXS, TXC_GPIO_OUTPUT, mask: 1 << pin, state: on); |
174 | } |
175 | |
176 | /* Set up the GPIO direction register */ |
177 | void falcon_txc_set_gpio_dir(struct ef4_nic *efx, int pin, int dir) |
178 | { |
179 | ef4_mdio_set_flag(efx, MDIO_MMD_PHYXS, TXC_GPIO_DIR, mask: 1 << pin, state: dir); |
180 | } |
181 | |
182 | /* Reset the PMA/PMD MMD. The documentation is explicit that this does a |
183 | * global reset (it's less clear what reset of other MMDs does).*/ |
184 | static int txc_reset_phy(struct ef4_nic *efx) |
185 | { |
186 | int rc = ef4_mdio_reset_mmd(efx, MDIO_MMD_PMAPMD, |
187 | TXC_MAX_RESET_TIME / TXC_RESET_WAIT, |
188 | TXC_RESET_WAIT); |
189 | if (rc < 0) |
190 | goto fail; |
191 | |
192 | /* Check that all the MMDs we expect are present and responding. */ |
193 | rc = ef4_mdio_check_mmds(efx, TXC_REQUIRED_DEVS); |
194 | if (rc < 0) |
195 | goto fail; |
196 | |
197 | return 0; |
198 | |
199 | fail: |
200 | netif_err(efx, hw, efx->net_dev, TXCNAME ": reset timed out!\n" ); |
201 | return rc; |
202 | } |
203 | |
204 | /* Run a single BIST on one MMD */ |
205 | static int txc_bist_one(struct ef4_nic *efx, int mmd, int test) |
206 | { |
207 | int ctrl, bctl; |
208 | int lane; |
209 | int rc = 0; |
210 | |
211 | /* Set PMA to test into loopback using Mt Diablo reg as per app note */ |
212 | ctrl = ef4_mdio_read(efx, MDIO_MMD_PCS, TXC_MTDIABLO_CTRL); |
213 | ctrl |= (1 << TXC_MTDIABLO_CTRL_PMA_LOOP_LBN); |
214 | ef4_mdio_write(efx, MDIO_MMD_PCS, TXC_MTDIABLO_CTRL, value: ctrl); |
215 | |
216 | /* The BIST app. note lists these as 3 distinct steps. */ |
217 | /* Set the BIST type */ |
218 | bctl = (test << TXC_BIST_CTRL_TYPE_LBN); |
219 | ef4_mdio_write(efx, devad: mmd, TXC_BIST_CTL, value: bctl); |
220 | |
221 | /* Set the BSTEN bit in the BIST Control register to enable */ |
222 | bctl |= (1 << TXC_BIST_CTRL_ENAB_LBN); |
223 | ef4_mdio_write(efx, devad: mmd, TXC_BIST_CTL, value: bctl); |
224 | |
225 | /* Set the BSTRT bit in the BIST Control register */ |
226 | ef4_mdio_write(efx, devad: mmd, TXC_BIST_CTL, |
227 | value: bctl | (1 << TXC_BIST_CTRL_STRT_LBN)); |
228 | |
229 | /* Wait. */ |
230 | udelay(TXC_BIST_DURATION); |
231 | |
232 | /* Set the BSTOP bit in the BIST Control register */ |
233 | bctl |= (1 << TXC_BIST_CTRL_STOP_LBN); |
234 | ef4_mdio_write(efx, devad: mmd, TXC_BIST_CTL, value: bctl); |
235 | |
236 | /* The STOP bit should go off when things have stopped */ |
237 | while (bctl & (1 << TXC_BIST_CTRL_STOP_LBN)) |
238 | bctl = ef4_mdio_read(efx, devad: mmd, TXC_BIST_CTL); |
239 | |
240 | /* Check all the error counts are 0 and all the frame counts are |
241 | non-zero */ |
242 | for (lane = 0; lane < 4; lane++) { |
243 | int count = ef4_mdio_read(efx, devad: mmd, TXC_BIST_RX0ERRCNT + lane); |
244 | if (count != 0) { |
245 | netif_err(efx, hw, efx->net_dev, TXCNAME": BIST error. " |
246 | "Lane %d had %d errs\n" , lane, count); |
247 | rc = -EIO; |
248 | } |
249 | count = ef4_mdio_read(efx, devad: mmd, TXC_BIST_RX0FRMCNT + lane); |
250 | if (count == 0) { |
251 | netif_err(efx, hw, efx->net_dev, TXCNAME": BIST error. " |
252 | "Lane %d got 0 frames\n" , lane); |
253 | rc = -EIO; |
254 | } |
255 | } |
256 | |
257 | if (rc == 0) |
258 | netif_info(efx, hw, efx->net_dev, TXCNAME": BIST pass\n" ); |
259 | |
260 | /* Disable BIST */ |
261 | ef4_mdio_write(efx, devad: mmd, TXC_BIST_CTL, value: 0); |
262 | |
263 | /* Turn off loopback */ |
264 | ctrl &= ~(1 << TXC_MTDIABLO_CTRL_PMA_LOOP_LBN); |
265 | ef4_mdio_write(efx, MDIO_MMD_PCS, TXC_MTDIABLO_CTRL, value: ctrl); |
266 | |
267 | return rc; |
268 | } |
269 | |
270 | static int txc_bist(struct ef4_nic *efx) |
271 | { |
272 | return txc_bist_one(efx, MDIO_MMD_PCS, TXC_BIST_CTRL_TYPE_TSD); |
273 | } |
274 | |
275 | /* Push the non-configurable defaults into the PHY. This must be |
276 | * done after every full reset */ |
277 | static void txc_apply_defaults(struct ef4_nic *efx) |
278 | { |
279 | int mctrl; |
280 | |
281 | /* Turn amplitude down and preemphasis off on the host side |
282 | * (PHY<->MAC) as this is believed less likely to upset Falcon |
283 | * and no adverse effects have been noted. It probably also |
284 | * saves a picowatt or two */ |
285 | |
286 | /* Turn off preemphasis */ |
287 | ef4_mdio_write(efx, MDIO_MMD_PHYXS, TXC_ALRGS_ATXPRE0, TXC_ATXPRE_NONE); |
288 | ef4_mdio_write(efx, MDIO_MMD_PHYXS, TXC_ALRGS_ATXPRE1, TXC_ATXPRE_NONE); |
289 | |
290 | /* Turn down the amplitude */ |
291 | ef4_mdio_write(efx, MDIO_MMD_PHYXS, |
292 | TXC_ALRGS_ATXAMP0, TXC_ATXAMP_0820_BOTH); |
293 | ef4_mdio_write(efx, MDIO_MMD_PHYXS, |
294 | TXC_ALRGS_ATXAMP1, TXC_ATXAMP_0820_BOTH); |
295 | |
296 | /* Set the line side amplitude and preemphasis to the databook |
297 | * defaults as an erratum causes them to be 0 on at least some |
298 | * PHY rev.s */ |
299 | ef4_mdio_write(efx, MDIO_MMD_PMAPMD, |
300 | TXC_ALRGS_ATXPRE0, TXC_ATXPRE_DEFAULT); |
301 | ef4_mdio_write(efx, MDIO_MMD_PMAPMD, |
302 | TXC_ALRGS_ATXPRE1, TXC_ATXPRE_DEFAULT); |
303 | ef4_mdio_write(efx, MDIO_MMD_PMAPMD, |
304 | TXC_ALRGS_ATXAMP0, TXC_ATXAMP_DEFAULT); |
305 | ef4_mdio_write(efx, MDIO_MMD_PMAPMD, |
306 | TXC_ALRGS_ATXAMP1, TXC_ATXAMP_DEFAULT); |
307 | |
308 | /* Set up the LEDs */ |
309 | mctrl = ef4_mdio_read(efx, MDIO_MMD_PHYXS, TXC_MRGS_CTL); |
310 | |
311 | /* Set the Green and Red LEDs to their default modes */ |
312 | mctrl &= ~((1 << TXC_MCTL_TXLED_LBN) | (1 << TXC_MCTL_RXLED_LBN)); |
313 | ef4_mdio_write(efx, MDIO_MMD_PHYXS, TXC_MRGS_CTL, value: mctrl); |
314 | |
315 | /* Databook recommends doing this after configuration changes */ |
316 | txc_reset_logic(efx); |
317 | |
318 | falcon_board(efx)->type->init_phy(efx); |
319 | } |
320 | |
321 | static int txc43128_phy_probe(struct ef4_nic *efx) |
322 | { |
323 | struct txc43128_data *phy_data; |
324 | |
325 | /* Allocate phy private storage */ |
326 | phy_data = kzalloc(size: sizeof(*phy_data), GFP_KERNEL); |
327 | if (!phy_data) |
328 | return -ENOMEM; |
329 | efx->phy_data = phy_data; |
330 | phy_data->phy_mode = efx->phy_mode; |
331 | |
332 | efx->mdio.mmds = TXC_REQUIRED_DEVS; |
333 | efx->mdio.mode_support = MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22; |
334 | |
335 | efx->loopback_modes = TXC_LOOPBACKS | FALCON_XMAC_LOOPBACKS; |
336 | |
337 | return 0; |
338 | } |
339 | |
340 | /* Initialisation entry point for this PHY driver */ |
341 | static int txc43128_phy_init(struct ef4_nic *efx) |
342 | { |
343 | int rc; |
344 | |
345 | rc = txc_reset_phy(efx); |
346 | if (rc < 0) |
347 | return rc; |
348 | |
349 | rc = txc_bist(efx); |
350 | if (rc < 0) |
351 | return rc; |
352 | |
353 | txc_apply_defaults(efx); |
354 | |
355 | return 0; |
356 | } |
357 | |
358 | /* Set the lane power down state in the global registers */ |
359 | static void txc_glrgs_lane_power(struct ef4_nic *efx, int mmd) |
360 | { |
361 | int pd = (1 << TXC_GLCMD_L01PD_LBN) | (1 << TXC_GLCMD_L23PD_LBN); |
362 | int ctl = ef4_mdio_read(efx, devad: mmd, TXC_GLRGS_GLCMD); |
363 | |
364 | if (!(efx->phy_mode & PHY_MODE_LOW_POWER)) |
365 | ctl &= ~pd; |
366 | else |
367 | ctl |= pd; |
368 | |
369 | ef4_mdio_write(efx, devad: mmd, TXC_GLRGS_GLCMD, value: ctl); |
370 | } |
371 | |
372 | /* Set the lane power down state in the analog control registers */ |
373 | static void txc_analog_lane_power(struct ef4_nic *efx, int mmd) |
374 | { |
375 | int txpd = (1 << TXC_ATXCTL_TXPD3_LBN) | (1 << TXC_ATXCTL_TXPD2_LBN) |
376 | | (1 << TXC_ATXCTL_TXPD1_LBN) | (1 << TXC_ATXCTL_TXPD0_LBN); |
377 | int rxpd = (1 << TXC_ARXCTL_RXPD3_LBN) | (1 << TXC_ARXCTL_RXPD2_LBN) |
378 | | (1 << TXC_ARXCTL_RXPD1_LBN) | (1 << TXC_ARXCTL_RXPD0_LBN); |
379 | int txctl = ef4_mdio_read(efx, devad: mmd, TXC_ALRGS_ATXCTL); |
380 | int rxctl = ef4_mdio_read(efx, devad: mmd, TXC_ALRGS_ARXCTL); |
381 | |
382 | if (!(efx->phy_mode & PHY_MODE_LOW_POWER)) { |
383 | txctl &= ~txpd; |
384 | rxctl &= ~rxpd; |
385 | } else { |
386 | txctl |= txpd; |
387 | rxctl |= rxpd; |
388 | } |
389 | |
390 | ef4_mdio_write(efx, devad: mmd, TXC_ALRGS_ATXCTL, value: txctl); |
391 | ef4_mdio_write(efx, devad: mmd, TXC_ALRGS_ARXCTL, value: rxctl); |
392 | } |
393 | |
394 | static void txc_set_power(struct ef4_nic *efx) |
395 | { |
396 | /* According to the data book, all the MMDs can do low power */ |
397 | ef4_mdio_set_mmds_lpower(efx, |
398 | low_power: !!(efx->phy_mode & PHY_MODE_LOW_POWER), |
399 | TXC_REQUIRED_DEVS); |
400 | |
401 | /* Global register bank is in PCS, PHY XS. These control the host |
402 | * side and line side settings respectively. */ |
403 | txc_glrgs_lane_power(efx, MDIO_MMD_PCS); |
404 | txc_glrgs_lane_power(efx, MDIO_MMD_PHYXS); |
405 | |
406 | /* Analog register bank in PMA/PMD, PHY XS */ |
407 | txc_analog_lane_power(efx, MDIO_MMD_PMAPMD); |
408 | txc_analog_lane_power(efx, MDIO_MMD_PHYXS); |
409 | } |
410 | |
411 | static void txc_reset_logic_mmd(struct ef4_nic *efx, int mmd) |
412 | { |
413 | int val = ef4_mdio_read(efx, devad: mmd, TXC_GLRGS_GLCMD); |
414 | int tries = 50; |
415 | |
416 | val |= (1 << TXC_GLCMD_LMTSWRST_LBN); |
417 | ef4_mdio_write(efx, devad: mmd, TXC_GLRGS_GLCMD, value: val); |
418 | while (--tries) { |
419 | val = ef4_mdio_read(efx, devad: mmd, TXC_GLRGS_GLCMD); |
420 | if (!(val & (1 << TXC_GLCMD_LMTSWRST_LBN))) |
421 | break; |
422 | udelay(1); |
423 | } |
424 | if (!tries) |
425 | netif_info(efx, hw, efx->net_dev, |
426 | TXCNAME " Logic reset timed out!\n" ); |
427 | } |
428 | |
429 | /* Perform a logic reset. This preserves the configuration registers |
430 | * and is needed for some configuration changes to take effect */ |
431 | static void txc_reset_logic(struct ef4_nic *efx) |
432 | { |
433 | /* The data sheet claims we can do the logic reset on either the |
434 | * PCS or the PHYXS and the result is a reset of both host- and |
435 | * line-side logic. */ |
436 | txc_reset_logic_mmd(efx, MDIO_MMD_PCS); |
437 | } |
438 | |
439 | static bool txc43128_phy_read_link(struct ef4_nic *efx) |
440 | { |
441 | return ef4_mdio_links_ok(efx, TXC_REQUIRED_DEVS); |
442 | } |
443 | |
444 | static int txc43128_phy_reconfigure(struct ef4_nic *efx) |
445 | { |
446 | struct txc43128_data *phy_data = efx->phy_data; |
447 | enum ef4_phy_mode mode_change = efx->phy_mode ^ phy_data->phy_mode; |
448 | bool loop_change = LOOPBACK_CHANGED(phy_data, efx, TXC_LOOPBACKS); |
449 | |
450 | if (efx->phy_mode & mode_change & PHY_MODE_TX_DISABLED) { |
451 | txc_reset_phy(efx); |
452 | txc_apply_defaults(efx); |
453 | falcon_reset_xaui(efx); |
454 | mode_change &= ~PHY_MODE_TX_DISABLED; |
455 | } |
456 | |
457 | ef4_mdio_transmit_disable(efx); |
458 | ef4_mdio_phy_reconfigure(efx); |
459 | if (mode_change & PHY_MODE_LOW_POWER) |
460 | txc_set_power(efx); |
461 | |
462 | /* The data sheet claims this is required after every reconfiguration |
463 | * (note at end of 7.1), but we mustn't do it when nothing changes as |
464 | * it glitches the link, and reconfigure gets called on link change, |
465 | * so we get an IRQ storm on link up. */ |
466 | if (loop_change || mode_change) |
467 | txc_reset_logic(efx); |
468 | |
469 | phy_data->phy_mode = efx->phy_mode; |
470 | phy_data->loopback_mode = efx->loopback_mode; |
471 | |
472 | return 0; |
473 | } |
474 | |
475 | static void txc43128_phy_fini(struct ef4_nic *efx) |
476 | { |
477 | /* Disable link events */ |
478 | ef4_mdio_write(efx, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_CTRL, value: 0); |
479 | } |
480 | |
481 | static void txc43128_phy_remove(struct ef4_nic *efx) |
482 | { |
483 | kfree(objp: efx->phy_data); |
484 | efx->phy_data = NULL; |
485 | } |
486 | |
487 | /* Periodic callback: this exists mainly to poll link status as we |
488 | * don't use LASI interrupts */ |
489 | static bool txc43128_phy_poll(struct ef4_nic *efx) |
490 | { |
491 | struct txc43128_data *data = efx->phy_data; |
492 | bool was_up = efx->link_state.up; |
493 | |
494 | efx->link_state.up = txc43128_phy_read_link(efx); |
495 | efx->link_state.speed = 10000; |
496 | efx->link_state.fd = true; |
497 | efx->link_state.fc = efx->wanted_fc; |
498 | |
499 | if (efx->link_state.up || (efx->loopback_mode != LOOPBACK_NONE)) { |
500 | data->bug10934_timer = jiffies; |
501 | } else { |
502 | if (time_after_eq(jiffies, (data->bug10934_timer + |
503 | BUG10934_RESET_INTERVAL))) { |
504 | data->bug10934_timer = jiffies; |
505 | txc_reset_logic(efx); |
506 | } |
507 | } |
508 | |
509 | return efx->link_state.up != was_up; |
510 | } |
511 | |
512 | static const char *const txc43128_test_names[] = { |
513 | "bist" |
514 | }; |
515 | |
516 | static const char *txc43128_test_name(struct ef4_nic *efx, unsigned int index) |
517 | { |
518 | if (index < ARRAY_SIZE(txc43128_test_names)) |
519 | return txc43128_test_names[index]; |
520 | return NULL; |
521 | } |
522 | |
523 | static int txc43128_run_tests(struct ef4_nic *efx, int *results, unsigned flags) |
524 | { |
525 | int rc; |
526 | |
527 | if (!(flags & ETH_TEST_FL_OFFLINE)) |
528 | return 0; |
529 | |
530 | rc = txc_reset_phy(efx); |
531 | if (rc < 0) |
532 | return rc; |
533 | |
534 | rc = txc_bist(efx); |
535 | txc_apply_defaults(efx); |
536 | results[0] = rc ? -1 : 1; |
537 | return rc; |
538 | } |
539 | |
540 | static void txc43128_get_link_ksettings(struct ef4_nic *efx, |
541 | struct ethtool_link_ksettings *cmd) |
542 | { |
543 | mdio45_ethtool_ksettings_get(mdio: &efx->mdio, cmd); |
544 | } |
545 | |
546 | const struct ef4_phy_operations falcon_txc_phy_ops = { |
547 | .probe = txc43128_phy_probe, |
548 | .init = txc43128_phy_init, |
549 | .reconfigure = txc43128_phy_reconfigure, |
550 | .poll = txc43128_phy_poll, |
551 | .fini = txc43128_phy_fini, |
552 | .remove = txc43128_phy_remove, |
553 | .get_link_ksettings = txc43128_get_link_ksettings, |
554 | .set_link_ksettings = ef4_mdio_set_link_ksettings, |
555 | .test_alive = ef4_mdio_test_alive, |
556 | .run_tests = txc43128_run_tests, |
557 | .test_name = txc43128_test_name, |
558 | }; |
559 | |