Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0+
2 : : /*
3 : : * Core PHY library, taken from phy.c
4 : : */
5 : : #include <linux/export.h>
6 : : #include <linux/phy.h>
7 : : #include <linux/of.h>
8 : :
9 : 0 : const char *phy_speed_to_str(int speed)
10 : : {
11 : 0 : BUILD_BUG_ON_MSG(__ETHTOOL_LINK_MODE_MASK_NBITS != 74,
12 : : "Enum ethtool_link_mode_bit_indices and phylib are out of sync. "
13 : : "If a speed or mode has been added please update phy_speed_to_str "
14 : : "and the PHY settings array.\n");
15 : :
16 [ # # # # : 0 : switch (speed) {
# # # # #
# # # # #
# # # ]
17 : : case SPEED_10:
18 : : return "10Mbps";
19 : 0 : case SPEED_100:
20 : 0 : return "100Mbps";
21 : 0 : case SPEED_1000:
22 : 0 : return "1Gbps";
23 : 0 : case SPEED_2500:
24 : 0 : return "2.5Gbps";
25 : 0 : case SPEED_5000:
26 : 0 : return "5Gbps";
27 : 0 : case SPEED_10000:
28 : 0 : return "10Gbps";
29 : 0 : case SPEED_14000:
30 : 0 : return "14Gbps";
31 : 0 : case SPEED_20000:
32 : 0 : return "20Gbps";
33 : 0 : case SPEED_25000:
34 : 0 : return "25Gbps";
35 : 0 : case SPEED_40000:
36 : 0 : return "40Gbps";
37 : 0 : case SPEED_50000:
38 : 0 : return "50Gbps";
39 : 0 : case SPEED_56000:
40 : 0 : return "56Gbps";
41 : 0 : case SPEED_100000:
42 : 0 : return "100Gbps";
43 : 0 : case SPEED_200000:
44 : 0 : return "200Gbps";
45 : 0 : case SPEED_400000:
46 : 0 : return "400Gbps";
47 : 0 : case SPEED_UNKNOWN:
48 : 0 : return "Unknown";
49 : 0 : default:
50 : 0 : return "Unsupported (update phy-core.c)";
51 : : }
52 : : }
53 : : EXPORT_SYMBOL_GPL(phy_speed_to_str);
54 : :
55 : 0 : const char *phy_duplex_to_str(unsigned int duplex)
56 : : {
57 [ # # ]: 0 : if (duplex == DUPLEX_HALF)
58 : : return "Half";
59 [ # # ]: 0 : if (duplex == DUPLEX_FULL)
60 : : return "Full";
61 [ # # ]: 0 : if (duplex == DUPLEX_UNKNOWN)
62 : 0 : return "Unknown";
63 : : return "Unsupported (update phy-core.c)";
64 : : }
65 : : EXPORT_SYMBOL_GPL(phy_duplex_to_str);
66 : :
67 : : /* A mapping of all SUPPORTED settings to speed/duplex. This table
68 : : * must be grouped by speed and sorted in descending match priority
69 : : * - iow, descending speed. */
70 : :
71 : : #define PHY_SETTING(s, d, b) { .speed = SPEED_ ## s, .duplex = DUPLEX_ ## d, \
72 : : .bit = ETHTOOL_LINK_MODE_ ## b ## _BIT}
73 : :
74 : : static const struct phy_setting settings[] = {
75 : : /* 400G */
76 : : PHY_SETTING( 400000, FULL, 400000baseCR8_Full ),
77 : : PHY_SETTING( 400000, FULL, 400000baseKR8_Full ),
78 : : PHY_SETTING( 400000, FULL, 400000baseLR8_ER8_FR8_Full ),
79 : : PHY_SETTING( 400000, FULL, 400000baseDR8_Full ),
80 : : PHY_SETTING( 400000, FULL, 400000baseSR8_Full ),
81 : : /* 200G */
82 : : PHY_SETTING( 200000, FULL, 200000baseCR4_Full ),
83 : : PHY_SETTING( 200000, FULL, 200000baseKR4_Full ),
84 : : PHY_SETTING( 200000, FULL, 200000baseLR4_ER4_FR4_Full ),
85 : : PHY_SETTING( 200000, FULL, 200000baseDR4_Full ),
86 : : PHY_SETTING( 200000, FULL, 200000baseSR4_Full ),
87 : : /* 100G */
88 : : PHY_SETTING( 100000, FULL, 100000baseCR4_Full ),
89 : : PHY_SETTING( 100000, FULL, 100000baseKR4_Full ),
90 : : PHY_SETTING( 100000, FULL, 100000baseLR4_ER4_Full ),
91 : : PHY_SETTING( 100000, FULL, 100000baseSR4_Full ),
92 : : PHY_SETTING( 100000, FULL, 100000baseCR2_Full ),
93 : : PHY_SETTING( 100000, FULL, 100000baseKR2_Full ),
94 : : PHY_SETTING( 100000, FULL, 100000baseLR2_ER2_FR2_Full ),
95 : : PHY_SETTING( 100000, FULL, 100000baseDR2_Full ),
96 : : PHY_SETTING( 100000, FULL, 100000baseSR2_Full ),
97 : : /* 56G */
98 : : PHY_SETTING( 56000, FULL, 56000baseCR4_Full ),
99 : : PHY_SETTING( 56000, FULL, 56000baseKR4_Full ),
100 : : PHY_SETTING( 56000, FULL, 56000baseLR4_Full ),
101 : : PHY_SETTING( 56000, FULL, 56000baseSR4_Full ),
102 : : /* 50G */
103 : : PHY_SETTING( 50000, FULL, 50000baseCR2_Full ),
104 : : PHY_SETTING( 50000, FULL, 50000baseKR2_Full ),
105 : : PHY_SETTING( 50000, FULL, 50000baseSR2_Full ),
106 : : PHY_SETTING( 50000, FULL, 50000baseCR_Full ),
107 : : PHY_SETTING( 50000, FULL, 50000baseKR_Full ),
108 : : PHY_SETTING( 50000, FULL, 50000baseLR_ER_FR_Full ),
109 : : PHY_SETTING( 50000, FULL, 50000baseDR_Full ),
110 : : PHY_SETTING( 50000, FULL, 50000baseSR_Full ),
111 : : /* 40G */
112 : : PHY_SETTING( 40000, FULL, 40000baseCR4_Full ),
113 : : PHY_SETTING( 40000, FULL, 40000baseKR4_Full ),
114 : : PHY_SETTING( 40000, FULL, 40000baseLR4_Full ),
115 : : PHY_SETTING( 40000, FULL, 40000baseSR4_Full ),
116 : : /* 25G */
117 : : PHY_SETTING( 25000, FULL, 25000baseCR_Full ),
118 : : PHY_SETTING( 25000, FULL, 25000baseKR_Full ),
119 : : PHY_SETTING( 25000, FULL, 25000baseSR_Full ),
120 : : /* 20G */
121 : : PHY_SETTING( 20000, FULL, 20000baseKR2_Full ),
122 : : PHY_SETTING( 20000, FULL, 20000baseMLD2_Full ),
123 : : /* 10G */
124 : : PHY_SETTING( 10000, FULL, 10000baseCR_Full ),
125 : : PHY_SETTING( 10000, FULL, 10000baseER_Full ),
126 : : PHY_SETTING( 10000, FULL, 10000baseKR_Full ),
127 : : PHY_SETTING( 10000, FULL, 10000baseKX4_Full ),
128 : : PHY_SETTING( 10000, FULL, 10000baseLR_Full ),
129 : : PHY_SETTING( 10000, FULL, 10000baseLRM_Full ),
130 : : PHY_SETTING( 10000, FULL, 10000baseR_FEC ),
131 : : PHY_SETTING( 10000, FULL, 10000baseSR_Full ),
132 : : PHY_SETTING( 10000, FULL, 10000baseT_Full ),
133 : : /* 5G */
134 : : PHY_SETTING( 5000, FULL, 5000baseT_Full ),
135 : : /* 2.5G */
136 : : PHY_SETTING( 2500, FULL, 2500baseT_Full ),
137 : : PHY_SETTING( 2500, FULL, 2500baseX_Full ),
138 : : /* 1G */
139 : : PHY_SETTING( 1000, FULL, 1000baseKX_Full ),
140 : : PHY_SETTING( 1000, FULL, 1000baseT_Full ),
141 : : PHY_SETTING( 1000, HALF, 1000baseT_Half ),
142 : : PHY_SETTING( 1000, FULL, 1000baseT1_Full ),
143 : : PHY_SETTING( 1000, FULL, 1000baseX_Full ),
144 : : /* 100M */
145 : : PHY_SETTING( 100, FULL, 100baseT_Full ),
146 : : PHY_SETTING( 100, FULL, 100baseT1_Full ),
147 : : PHY_SETTING( 100, HALF, 100baseT_Half ),
148 : : /* 10M */
149 : : PHY_SETTING( 10, FULL, 10baseT_Full ),
150 : : PHY_SETTING( 10, HALF, 10baseT_Half ),
151 : : };
152 : : #undef PHY_SETTING
153 : :
154 : : /**
155 : : * phy_lookup_setting - lookup a PHY setting
156 : : * @speed: speed to match
157 : : * @duplex: duplex to match
158 : : * @mask: allowed link modes
159 : : * @exact: an exact match is required
160 : : *
161 : : * Search the settings array for a setting that matches the speed and
162 : : * duplex, and which is supported.
163 : : *
164 : : * If @exact is unset, either an exact match or %NULL for no match will
165 : : * be returned.
166 : : *
167 : : * If @exact is set, an exact match, the fastest supported setting at
168 : : * or below the specified speed, the slowest supported setting, or if
169 : : * they all fail, %NULL will be returned.
170 : : */
171 : : const struct phy_setting *
172 : 0 : phy_lookup_setting(int speed, int duplex, const unsigned long *mask, bool exact)
173 : : {
174 : 0 : const struct phy_setting *p, *match = NULL, *last = NULL;
175 : 0 : int i;
176 : :
177 [ # # ]: 0 : for (i = 0, p = settings; i < ARRAY_SIZE(settings); i++, p++) {
178 [ # # # # ]: 0 : if (p->bit < __ETHTOOL_LINK_MODE_MASK_NBITS &&
179 : 0 : test_bit(p->bit, mask)) {
180 : 0 : last = p;
181 [ # # # # ]: 0 : if (p->speed == speed && p->duplex == duplex) {
182 : : /* Exact match for speed and duplex */
183 : : match = p;
184 : : break;
185 [ # # ]: 0 : } else if (!exact) {
186 [ # # # # ]: 0 : if (!match && p->speed <= speed)
187 : : /* Candidate */
188 : 0 : match = p;
189 : :
190 [ # # ]: 0 : if (p->speed < speed)
191 : : break;
192 : : }
193 : : }
194 : : }
195 : :
196 [ # # ]: 0 : if (!match && !exact)
197 : 0 : match = last;
198 : :
199 : 0 : return match;
200 : : }
201 : : EXPORT_SYMBOL_GPL(phy_lookup_setting);
202 : :
203 : 0 : size_t phy_speeds(unsigned int *speeds, size_t size,
204 : : unsigned long *mask)
205 : : {
206 : 0 : size_t count;
207 : 0 : int i;
208 : :
209 [ # # ]: 0 : for (i = 0, count = 0; i < ARRAY_SIZE(settings) && count < size; i++)
210 [ # # # # ]: 0 : if (settings[i].bit < __ETHTOOL_LINK_MODE_MASK_NBITS &&
211 [ # # ]: 0 : test_bit(settings[i].bit, mask) &&
212 [ # # ]: 0 : (count == 0 || speeds[count - 1] != settings[i].speed))
213 : 0 : speeds[count++] = settings[i].speed;
214 : :
215 : 0 : return count;
216 : : }
217 : :
218 : 0 : static int __set_linkmode_max_speed(u32 max_speed, unsigned long *addr)
219 : : {
220 : 0 : const struct phy_setting *p;
221 : 0 : int i;
222 : :
223 [ # # ]: 0 : for (i = 0, p = settings; i < ARRAY_SIZE(settings); i++, p++) {
224 [ # # ]: 0 : if (p->speed > max_speed)
225 : 0 : linkmode_clear_bit(p->bit, addr);
226 : : else
227 : : break;
228 : : }
229 : :
230 : 0 : return 0;
231 : : }
232 : :
233 : 0 : static int __set_phy_supported(struct phy_device *phydev, u32 max_speed)
234 : : {
235 : 0 : return __set_linkmode_max_speed(max_speed, phydev->supported);
236 : : }
237 : :
238 : 0 : int phy_set_max_speed(struct phy_device *phydev, u32 max_speed)
239 : : {
240 : 0 : int err;
241 : :
242 : 0 : err = __set_phy_supported(phydev, max_speed);
243 [ # # ]: 0 : if (err)
244 : : return err;
245 : :
246 : 0 : phy_advertise_supported(phydev);
247 : :
248 : 0 : return 0;
249 : : }
250 : : EXPORT_SYMBOL(phy_set_max_speed);
251 : :
252 : 21 : void of_set_phy_supported(struct phy_device *phydev)
253 : : {
254 : 21 : struct device_node *node = phydev->mdio.dev.of_node;
255 : 21 : u32 max_speed;
256 : :
257 : 21 : if (!IS_ENABLED(CONFIG_OF_MDIO))
258 : 21 : return;
259 : :
260 : : if (!node)
261 : : return;
262 : :
263 : : if (!of_property_read_u32(node, "max-speed", &max_speed))
264 : : __set_phy_supported(phydev, max_speed);
265 : : }
266 : :
267 : 21 : void of_set_phy_eee_broken(struct phy_device *phydev)
268 : : {
269 : 21 : struct device_node *node = phydev->mdio.dev.of_node;
270 : 21 : u32 broken = 0;
271 : :
272 : 21 : if (!IS_ENABLED(CONFIG_OF_MDIO))
273 : 21 : return;
274 : :
275 : : if (!node)
276 : : return;
277 : :
278 : : if (of_property_read_bool(node, "eee-broken-100tx"))
279 : : broken |= MDIO_EEE_100TX;
280 : : if (of_property_read_bool(node, "eee-broken-1000t"))
281 : : broken |= MDIO_EEE_1000T;
282 : : if (of_property_read_bool(node, "eee-broken-10gt"))
283 : : broken |= MDIO_EEE_10GT;
284 : : if (of_property_read_bool(node, "eee-broken-1000kx"))
285 : : broken |= MDIO_EEE_1000KX;
286 : : if (of_property_read_bool(node, "eee-broken-10gkx4"))
287 : : broken |= MDIO_EEE_10GKX4;
288 : : if (of_property_read_bool(node, "eee-broken-10gkr"))
289 : : broken |= MDIO_EEE_10GKR;
290 : :
291 : : phydev->eee_broken_modes = broken;
292 : : }
293 : :
294 : 0 : void phy_resolve_aneg_pause(struct phy_device *phydev)
295 : : {
296 [ # # ]: 0 : if (phydev->duplex == DUPLEX_FULL) {
297 : 0 : phydev->pause = linkmode_test_bit(ETHTOOL_LINK_MODE_Pause_BIT,
298 : 0 : phydev->lp_advertising);
299 : 0 : phydev->asym_pause = linkmode_test_bit(
300 : : ETHTOOL_LINK_MODE_Asym_Pause_BIT,
301 : : phydev->lp_advertising);
302 : : }
303 : 0 : }
304 : : EXPORT_SYMBOL_GPL(phy_resolve_aneg_pause);
305 : :
306 : : /**
307 : : * phy_resolve_aneg_linkmode - resolve the advertisements into phy settings
308 : : * @phydev: The phy_device struct
309 : : *
310 : : * Resolve our and the link partner advertisements into their corresponding
311 : : * speed and duplex. If full duplex was negotiated, extract the pause mode
312 : : * from the link partner mask.
313 : : */
314 : 0 : void phy_resolve_aneg_linkmode(struct phy_device *phydev)
315 : : {
316 : 0 : __ETHTOOL_DECLARE_LINK_MODE_MASK(common);
317 : 0 : int i;
318 : :
319 : 0 : linkmode_and(common, phydev->lp_advertising, phydev->advertising);
320 : :
321 [ # # ]: 0 : for (i = 0; i < ARRAY_SIZE(settings); i++)
322 [ # # ]: 0 : if (test_bit(settings[i].bit, common)) {
323 : 0 : phydev->speed = settings[i].speed;
324 : 0 : phydev->duplex = settings[i].duplex;
325 : 0 : break;
326 : : }
327 : :
328 : 0 : phy_resolve_aneg_pause(phydev);
329 : 0 : }
330 : : EXPORT_SYMBOL_GPL(phy_resolve_aneg_linkmode);
331 : :
332 : 0 : static int phy_resolve_min_speed(struct phy_device *phydev, bool fdx_only)
333 : : {
334 : 0 : __ETHTOOL_DECLARE_LINK_MODE_MASK(common);
335 : 0 : int i = ARRAY_SIZE(settings);
336 : :
337 : 0 : linkmode_and(common, phydev->lp_advertising, phydev->advertising);
338 : :
339 [ # # ]: 0 : while (--i >= 0) {
340 [ # # ]: 0 : if (test_bit(settings[i].bit, common)) {
341 [ # # # # ]: 0 : if (fdx_only && settings[i].duplex != DUPLEX_FULL)
342 : 0 : continue;
343 : 0 : return settings[i].speed;
344 : : }
345 : : }
346 : :
347 : : return SPEED_UNKNOWN;
348 : : }
349 : :
350 : 0 : int phy_speed_down_core(struct phy_device *phydev)
351 : : {
352 : 0 : int min_common_speed = phy_resolve_min_speed(phydev, true);
353 : :
354 [ # # ]: 0 : if (min_common_speed == SPEED_UNKNOWN)
355 : : return -EINVAL;
356 : :
357 : 0 : return __set_linkmode_max_speed(min_common_speed, phydev->advertising);
358 : : }
359 : :
360 : 0 : static void mmd_phy_indirect(struct mii_bus *bus, int phy_addr, int devad,
361 : : u16 regnum)
362 : : {
363 : : /* Write the desired MMD Devad */
364 : 0 : __mdiobus_write(bus, phy_addr, MII_MMD_CTRL, devad);
365 : :
366 : : /* Write the desired MMD register address */
367 : 0 : __mdiobus_write(bus, phy_addr, MII_MMD_DATA, regnum);
368 : :
369 : : /* Select the Function : DATA with no post increment */
370 : 0 : __mdiobus_write(bus, phy_addr, MII_MMD_CTRL,
371 : 0 : devad | MII_MMD_CTRL_NOINCR);
372 : 0 : }
373 : :
374 : : /**
375 : : * __phy_read_mmd - Convenience function for reading a register
376 : : * from an MMD on a given PHY.
377 : : * @phydev: The phy_device struct
378 : : * @devad: The MMD to read from (0..31)
379 : : * @regnum: The register on the MMD to read (0..65535)
380 : : *
381 : : * Same rules as for __phy_read();
382 : : */
383 : 0 : int __phy_read_mmd(struct phy_device *phydev, int devad, u32 regnum)
384 : : {
385 : 0 : int val;
386 : :
387 [ # # ]: 0 : if (regnum > (u16)~0 || devad > 32)
388 : : return -EINVAL;
389 : :
390 [ # # # # ]: 0 : if (phydev->drv && phydev->drv->read_mmd) {
391 : 0 : val = phydev->drv->read_mmd(phydev, devad, regnum);
392 [ # # ]: 0 : } else if (phydev->is_c45) {
393 : 0 : u32 addr = MII_ADDR_C45 | (devad << 16) | (regnum & 0xffff);
394 : :
395 : 0 : val = __mdiobus_read(phydev->mdio.bus, phydev->mdio.addr, addr);
396 : : } else {
397 : 0 : struct mii_bus *bus = phydev->mdio.bus;
398 : 0 : int phy_addr = phydev->mdio.addr;
399 : :
400 : 0 : mmd_phy_indirect(bus, phy_addr, devad, regnum);
401 : :
402 : : /* Read the content of the MMD's selected register */
403 : 0 : val = __mdiobus_read(bus, phy_addr, MII_MMD_DATA);
404 : : }
405 : : return val;
406 : : }
407 : : EXPORT_SYMBOL(__phy_read_mmd);
408 : :
409 : : /**
410 : : * phy_read_mmd - Convenience function for reading a register
411 : : * from an MMD on a given PHY.
412 : : * @phydev: The phy_device struct
413 : : * @devad: The MMD to read from
414 : : * @regnum: The register on the MMD to read
415 : : *
416 : : * Same rules as for phy_read();
417 : : */
418 : 0 : int phy_read_mmd(struct phy_device *phydev, int devad, u32 regnum)
419 : : {
420 : 0 : int ret;
421 : :
422 : 0 : phy_lock_mdio_bus(phydev);
423 : 0 : ret = __phy_read_mmd(phydev, devad, regnum);
424 : 0 : phy_unlock_mdio_bus(phydev);
425 : :
426 : 0 : return ret;
427 : : }
428 : : EXPORT_SYMBOL(phy_read_mmd);
429 : :
430 : : /**
431 : : * __phy_write_mmd - Convenience function for writing a register
432 : : * on an MMD on a given PHY.
433 : : * @phydev: The phy_device struct
434 : : * @devad: The MMD to read from
435 : : * @regnum: The register on the MMD to read
436 : : * @val: value to write to @regnum
437 : : *
438 : : * Same rules as for __phy_write();
439 : : */
440 : 0 : int __phy_write_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val)
441 : : {
442 : 0 : int ret;
443 : :
444 [ # # ]: 0 : if (regnum > (u16)~0 || devad > 32)
445 : : return -EINVAL;
446 : :
447 [ # # # # ]: 0 : if (phydev->drv && phydev->drv->write_mmd) {
448 : 0 : ret = phydev->drv->write_mmd(phydev, devad, regnum, val);
449 [ # # ]: 0 : } else if (phydev->is_c45) {
450 : 0 : u32 addr = MII_ADDR_C45 | (devad << 16) | (regnum & 0xffff);
451 : :
452 : 0 : ret = __mdiobus_write(phydev->mdio.bus, phydev->mdio.addr,
453 : : addr, val);
454 : : } else {
455 : 0 : struct mii_bus *bus = phydev->mdio.bus;
456 : 0 : int phy_addr = phydev->mdio.addr;
457 : :
458 : 0 : mmd_phy_indirect(bus, phy_addr, devad, regnum);
459 : :
460 : : /* Write the data into MMD's selected register */
461 : 0 : __mdiobus_write(bus, phy_addr, MII_MMD_DATA, val);
462 : :
463 : 0 : ret = 0;
464 : : }
465 : : return ret;
466 : : }
467 : : EXPORT_SYMBOL(__phy_write_mmd);
468 : :
469 : : /**
470 : : * phy_write_mmd - Convenience function for writing a register
471 : : * on an MMD on a given PHY.
472 : : * @phydev: The phy_device struct
473 : : * @devad: The MMD to read from
474 : : * @regnum: The register on the MMD to read
475 : : * @val: value to write to @regnum
476 : : *
477 : : * Same rules as for phy_write();
478 : : */
479 : 0 : int phy_write_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val)
480 : : {
481 : 0 : int ret;
482 : :
483 : 0 : phy_lock_mdio_bus(phydev);
484 : 0 : ret = __phy_write_mmd(phydev, devad, regnum, val);
485 : 0 : phy_unlock_mdio_bus(phydev);
486 : :
487 : 0 : return ret;
488 : : }
489 : : EXPORT_SYMBOL(phy_write_mmd);
490 : :
491 : : /**
492 : : * __phy_modify_changed() - Convenience function for modifying a PHY register
493 : : * @phydev: a pointer to a &struct phy_device
494 : : * @regnum: register number
495 : : * @mask: bit mask of bits to clear
496 : : * @set: bit mask of bits to set
497 : : *
498 : : * Unlocked helper function which allows a PHY register to be modified as
499 : : * new register value = (old register value & ~mask) | set
500 : : *
501 : : * Returns negative errno, 0 if there was no change, and 1 in case of change
502 : : */
503 : 105 : int __phy_modify_changed(struct phy_device *phydev, u32 regnum, u16 mask,
504 : : u16 set)
505 : : {
506 : 105 : int new, ret;
507 : :
508 : 105 : ret = __phy_read(phydev, regnum);
509 [ + - ]: 105 : if (ret < 0)
510 : : return ret;
511 : :
512 : 105 : new = (ret & ~mask) | set;
513 [ + - ]: 105 : if (new == ret)
514 : : return 0;
515 : :
516 : 105 : ret = __phy_write(phydev, regnum, new);
517 : :
518 [ + - ]: 105 : return ret < 0 ? ret : 1;
519 : : }
520 : : EXPORT_SYMBOL_GPL(__phy_modify_changed);
521 : :
522 : : /**
523 : : * phy_modify_changed - Function for modifying a PHY register
524 : : * @phydev: the phy_device struct
525 : : * @regnum: register number to modify
526 : : * @mask: bit mask of bits to clear
527 : : * @set: new value of bits set in mask to write to @regnum
528 : : *
529 : : * NOTE: MUST NOT be called from interrupt context,
530 : : * because the bus read/write functions may wait for an interrupt
531 : : * to conclude the operation.
532 : : *
533 : : * Returns negative errno, 0 if there was no change, and 1 in case of change
534 : : */
535 : 42 : int phy_modify_changed(struct phy_device *phydev, u32 regnum, u16 mask, u16 set)
536 : : {
537 : 42 : int ret;
538 : :
539 : 42 : phy_lock_mdio_bus(phydev);
540 : 42 : ret = __phy_modify_changed(phydev, regnum, mask, set);
541 : 42 : phy_unlock_mdio_bus(phydev);
542 : :
543 : 42 : return ret;
544 : : }
545 : : EXPORT_SYMBOL_GPL(phy_modify_changed);
546 : :
547 : : /**
548 : : * __phy_modify - Convenience function for modifying a PHY register
549 : : * @phydev: the phy_device struct
550 : : * @regnum: register number to modify
551 : : * @mask: bit mask of bits to clear
552 : : * @set: new value of bits set in mask to write to @regnum
553 : : *
554 : : * NOTE: MUST NOT be called from interrupt context,
555 : : * because the bus read/write functions may wait for an interrupt
556 : : * to conclude the operation.
557 : : */
558 : 63 : int __phy_modify(struct phy_device *phydev, u32 regnum, u16 mask, u16 set)
559 : : {
560 : 63 : int ret;
561 : :
562 : 0 : ret = __phy_modify_changed(phydev, regnum, mask, set);
563 : :
564 : 63 : return ret < 0 ? ret : 0;
565 : : }
566 : : EXPORT_SYMBOL_GPL(__phy_modify);
567 : :
568 : : /**
569 : : * phy_modify - Convenience function for modifying a given PHY register
570 : : * @phydev: the phy_device struct
571 : : * @regnum: register number to write
572 : : * @mask: bit mask of bits to clear
573 : : * @set: new value of bits set in mask to write to @regnum
574 : : *
575 : : * NOTE: MUST NOT be called from interrupt context,
576 : : * because the bus read/write functions may wait for an interrupt
577 : : * to conclude the operation.
578 : : */
579 : 63 : int phy_modify(struct phy_device *phydev, u32 regnum, u16 mask, u16 set)
580 : : {
581 : 63 : int ret;
582 : :
583 : 63 : phy_lock_mdio_bus(phydev);
584 : 63 : ret = __phy_modify(phydev, regnum, mask, set);
585 : 63 : phy_unlock_mdio_bus(phydev);
586 : :
587 : 63 : return ret;
588 : : }
589 : : EXPORT_SYMBOL_GPL(phy_modify);
590 : :
591 : : /**
592 : : * __phy_modify_mmd_changed - Function for modifying a register on MMD
593 : : * @phydev: the phy_device struct
594 : : * @devad: the MMD containing register to modify
595 : : * @regnum: register number to modify
596 : : * @mask: bit mask of bits to clear
597 : : * @set: new value of bits set in mask to write to @regnum
598 : : *
599 : : * Unlocked helper function which allows a MMD register to be modified as
600 : : * new register value = (old register value & ~mask) | set
601 : : *
602 : : * Returns negative errno, 0 if there was no change, and 1 in case of change
603 : : */
604 : 0 : int __phy_modify_mmd_changed(struct phy_device *phydev, int devad, u32 regnum,
605 : : u16 mask, u16 set)
606 : : {
607 : 0 : int new, ret;
608 : :
609 : 0 : ret = __phy_read_mmd(phydev, devad, regnum);
610 [ # # ]: 0 : if (ret < 0)
611 : : return ret;
612 : :
613 : 0 : new = (ret & ~mask) | set;
614 [ # # ]: 0 : if (new == ret)
615 : : return 0;
616 : :
617 : 0 : ret = __phy_write_mmd(phydev, devad, regnum, new);
618 : :
619 [ # # ]: 0 : return ret < 0 ? ret : 1;
620 : : }
621 : : EXPORT_SYMBOL_GPL(__phy_modify_mmd_changed);
622 : :
623 : : /**
624 : : * phy_modify_mmd_changed - Function for modifying a register on MMD
625 : : * @phydev: the phy_device struct
626 : : * @devad: the MMD containing register to modify
627 : : * @regnum: register number to modify
628 : : * @mask: bit mask of bits to clear
629 : : * @set: new value of bits set in mask to write to @regnum
630 : : *
631 : : * NOTE: MUST NOT be called from interrupt context,
632 : : * because the bus read/write functions may wait for an interrupt
633 : : * to conclude the operation.
634 : : *
635 : : * Returns negative errno, 0 if there was no change, and 1 in case of change
636 : : */
637 : 0 : int phy_modify_mmd_changed(struct phy_device *phydev, int devad, u32 regnum,
638 : : u16 mask, u16 set)
639 : : {
640 : 0 : int ret;
641 : :
642 : 0 : phy_lock_mdio_bus(phydev);
643 : 0 : ret = __phy_modify_mmd_changed(phydev, devad, regnum, mask, set);
644 : 0 : phy_unlock_mdio_bus(phydev);
645 : :
646 : 0 : return ret;
647 : : }
648 : : EXPORT_SYMBOL_GPL(phy_modify_mmd_changed);
649 : :
650 : : /**
651 : : * __phy_modify_mmd - Convenience function for modifying a register on MMD
652 : : * @phydev: the phy_device struct
653 : : * @devad: the MMD containing register to modify
654 : : * @regnum: register number to modify
655 : : * @mask: bit mask of bits to clear
656 : : * @set: new value of bits set in mask to write to @regnum
657 : : *
658 : : * NOTE: MUST NOT be called from interrupt context,
659 : : * because the bus read/write functions may wait for an interrupt
660 : : * to conclude the operation.
661 : : */
662 : 0 : int __phy_modify_mmd(struct phy_device *phydev, int devad, u32 regnum,
663 : : u16 mask, u16 set)
664 : : {
665 : 0 : int ret;
666 : :
667 : 0 : ret = __phy_modify_mmd_changed(phydev, devad, regnum, mask, set);
668 : :
669 : 0 : return ret < 0 ? ret : 0;
670 : : }
671 : : EXPORT_SYMBOL_GPL(__phy_modify_mmd);
672 : :
673 : : /**
674 : : * phy_modify_mmd - Convenience function for modifying a register on MMD
675 : : * @phydev: the phy_device struct
676 : : * @devad: the MMD containing register to modify
677 : : * @regnum: register number to modify
678 : : * @mask: bit mask of bits to clear
679 : : * @set: new value of bits set in mask to write to @regnum
680 : : *
681 : : * NOTE: MUST NOT be called from interrupt context,
682 : : * because the bus read/write functions may wait for an interrupt
683 : : * to conclude the operation.
684 : : */
685 : 0 : int phy_modify_mmd(struct phy_device *phydev, int devad, u32 regnum,
686 : : u16 mask, u16 set)
687 : : {
688 : 0 : int ret;
689 : :
690 : 0 : phy_lock_mdio_bus(phydev);
691 : 0 : ret = __phy_modify_mmd(phydev, devad, regnum, mask, set);
692 : 0 : phy_unlock_mdio_bus(phydev);
693 : :
694 : 0 : return ret;
695 : : }
696 : : EXPORT_SYMBOL_GPL(phy_modify_mmd);
697 : :
698 : 0 : static int __phy_read_page(struct phy_device *phydev)
699 : : {
700 [ # # # # : 0 : if (WARN_ONCE(!phydev->drv->read_page, "read_page callback not available, PHY driver not loaded?\n"))
# # ]
701 : : return -EOPNOTSUPP;
702 : :
703 : 0 : return phydev->drv->read_page(phydev);
704 : : }
705 : :
706 : 0 : static int __phy_write_page(struct phy_device *phydev, int page)
707 : : {
708 [ # # # # : 0 : if (WARN_ONCE(!phydev->drv->write_page, "write_page callback not available, PHY driver not loaded?\n"))
# # ]
709 : : return -EOPNOTSUPP;
710 : :
711 : 0 : return phydev->drv->write_page(phydev, page);
712 : : }
713 : :
714 : : /**
715 : : * phy_save_page() - take the bus lock and save the current page
716 : : * @phydev: a pointer to a &struct phy_device
717 : : *
718 : : * Take the MDIO bus lock, and return the current page number. On error,
719 : : * returns a negative errno. phy_restore_page() must always be called
720 : : * after this, irrespective of success or failure of this call.
721 : : */
722 : 0 : int phy_save_page(struct phy_device *phydev)
723 : : {
724 : 0 : phy_lock_mdio_bus(phydev);
725 : 0 : return __phy_read_page(phydev);
726 : : }
727 : : EXPORT_SYMBOL_GPL(phy_save_page);
728 : :
729 : : /**
730 : : * phy_select_page() - take the bus lock, save the current page, and set a page
731 : : * @phydev: a pointer to a &struct phy_device
732 : : * @page: desired page
733 : : *
734 : : * Take the MDIO bus lock to protect against concurrent access, save the
735 : : * current PHY page, and set the current page. On error, returns a
736 : : * negative errno, otherwise returns the previous page number.
737 : : * phy_restore_page() must always be called after this, irrespective
738 : : * of success or failure of this call.
739 : : */
740 : 0 : int phy_select_page(struct phy_device *phydev, int page)
741 : : {
742 : 0 : int ret, oldpage;
743 : :
744 : 0 : oldpage = ret = phy_save_page(phydev);
745 [ # # ]: 0 : if (ret < 0)
746 : : return ret;
747 : :
748 [ # # ]: 0 : if (oldpage != page) {
749 : 0 : ret = __phy_write_page(phydev, page);
750 [ # # ]: 0 : if (ret < 0)
751 : 0 : return ret;
752 : : }
753 : :
754 : : return oldpage;
755 : : }
756 : : EXPORT_SYMBOL_GPL(phy_select_page);
757 : :
758 : : /**
759 : : * phy_restore_page() - restore the page register and release the bus lock
760 : : * @phydev: a pointer to a &struct phy_device
761 : : * @oldpage: the old page, return value from phy_save_page() or phy_select_page()
762 : : * @ret: operation's return code
763 : : *
764 : : * Release the MDIO bus lock, restoring @oldpage if it is a valid page.
765 : : * This function propagates the earliest error code from the group of
766 : : * operations.
767 : : *
768 : : * Returns:
769 : : * @oldpage if it was a negative value, otherwise
770 : : * @ret if it was a negative errno value, otherwise
771 : : * phy_write_page()'s negative value if it were in error, otherwise
772 : : * @ret.
773 : : */
774 : 0 : int phy_restore_page(struct phy_device *phydev, int oldpage, int ret)
775 : : {
776 : 0 : int r;
777 : :
778 [ # # ]: 0 : if (oldpage >= 0) {
779 : 0 : r = __phy_write_page(phydev, oldpage);
780 : :
781 : : /* Propagate the operation return code if the page write
782 : : * was successful.
783 : : */
784 [ # # ]: 0 : if (ret >= 0 && r < 0)
785 : 0 : ret = r;
786 : : } else {
787 : : /* Propagate the phy page selection error code */
788 : : ret = oldpage;
789 : : }
790 : :
791 : 0 : phy_unlock_mdio_bus(phydev);
792 : :
793 : 0 : return ret;
794 : : }
795 : : EXPORT_SYMBOL_GPL(phy_restore_page);
796 : :
797 : : /**
798 : : * phy_read_paged() - Convenience function for reading a paged register
799 : : * @phydev: a pointer to a &struct phy_device
800 : : * @page: the page for the phy
801 : : * @regnum: register number
802 : : *
803 : : * Same rules as for phy_read().
804 : : */
805 : 0 : int phy_read_paged(struct phy_device *phydev, int page, u32 regnum)
806 : : {
807 : 0 : int ret = 0, oldpage;
808 : :
809 : 0 : oldpage = phy_select_page(phydev, page);
810 [ # # ]: 0 : if (oldpage >= 0)
811 : 0 : ret = __phy_read(phydev, regnum);
812 : :
813 : 0 : return phy_restore_page(phydev, oldpage, ret);
814 : : }
815 : : EXPORT_SYMBOL(phy_read_paged);
816 : :
817 : : /**
818 : : * phy_write_paged() - Convenience function for writing a paged register
819 : : * @phydev: a pointer to a &struct phy_device
820 : : * @page: the page for the phy
821 : : * @regnum: register number
822 : : * @val: value to write
823 : : *
824 : : * Same rules as for phy_write().
825 : : */
826 : 0 : int phy_write_paged(struct phy_device *phydev, int page, u32 regnum, u16 val)
827 : : {
828 : 0 : int ret = 0, oldpage;
829 : :
830 : 0 : oldpage = phy_select_page(phydev, page);
831 [ # # ]: 0 : if (oldpage >= 0)
832 : 0 : ret = __phy_write(phydev, regnum, val);
833 : :
834 : 0 : return phy_restore_page(phydev, oldpage, ret);
835 : : }
836 : : EXPORT_SYMBOL(phy_write_paged);
837 : :
838 : : /**
839 : : * phy_modify_paged_changed() - Function for modifying a paged register
840 : : * @phydev: a pointer to a &struct phy_device
841 : : * @page: the page for the phy
842 : : * @regnum: register number
843 : : * @mask: bit mask of bits to clear
844 : : * @set: bit mask of bits to set
845 : : *
846 : : * Returns negative errno, 0 if there was no change, and 1 in case of change
847 : : */
848 : 0 : int phy_modify_paged_changed(struct phy_device *phydev, int page, u32 regnum,
849 : : u16 mask, u16 set)
850 : : {
851 : 0 : int ret = 0, oldpage;
852 : :
853 : 0 : oldpage = phy_select_page(phydev, page);
854 [ # # ]: 0 : if (oldpage >= 0)
855 : 0 : ret = __phy_modify_changed(phydev, regnum, mask, set);
856 : :
857 : 0 : return phy_restore_page(phydev, oldpage, ret);
858 : : }
859 : : EXPORT_SYMBOL(phy_modify_paged_changed);
860 : :
861 : : /**
862 : : * phy_modify_paged() - Convenience function for modifying a paged register
863 : : * @phydev: a pointer to a &struct phy_device
864 : : * @page: the page for the phy
865 : : * @regnum: register number
866 : : * @mask: bit mask of bits to clear
867 : : * @set: bit mask of bits to set
868 : : *
869 : : * Same rules as for phy_read() and phy_write().
870 : : */
871 : 0 : int phy_modify_paged(struct phy_device *phydev, int page, u32 regnum,
872 : : u16 mask, u16 set)
873 : : {
874 : 0 : int ret = phy_modify_paged_changed(phydev, page, regnum, mask, set);
875 : :
876 : 0 : return ret < 0 ? ret : 0;
877 : : }
878 : : EXPORT_SYMBOL(phy_modify_paged);
|