2 * Core PHY library, taken from phy.c
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
9 #include <linux/export.h>
10 #include <linux/phy.h>
12 const char *phy_speed_to_str(int speed
)
44 return "Unsupported (update phy-core.c)";
47 EXPORT_SYMBOL_GPL(phy_speed_to_str
);
49 const char *phy_duplex_to_str(unsigned int duplex
)
51 if (duplex
== DUPLEX_HALF
)
53 if (duplex
== DUPLEX_FULL
)
55 if (duplex
== DUPLEX_UNKNOWN
)
57 return "Unsupported (update phy-core.c)";
59 EXPORT_SYMBOL_GPL(phy_duplex_to_str
);
61 /* A mapping of all SUPPORTED settings to speed/duplex. This table
62 * must be grouped by speed and sorted in descending match priority
63 * - iow, descending speed. */
64 static const struct phy_setting settings
[] = {
67 .duplex
= DUPLEX_FULL
,
68 .bit
= ETHTOOL_LINK_MODE_10000baseKR_Full_BIT
,
72 .duplex
= DUPLEX_FULL
,
73 .bit
= ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT
,
77 .duplex
= DUPLEX_FULL
,
78 .bit
= ETHTOOL_LINK_MODE_10000baseT_Full_BIT
,
82 .duplex
= DUPLEX_FULL
,
83 .bit
= ETHTOOL_LINK_MODE_2500baseX_Full_BIT
,
87 .duplex
= DUPLEX_FULL
,
88 .bit
= ETHTOOL_LINK_MODE_1000baseKX_Full_BIT
,
92 .duplex
= DUPLEX_FULL
,
93 .bit
= ETHTOOL_LINK_MODE_1000baseX_Full_BIT
,
97 .duplex
= DUPLEX_FULL
,
98 .bit
= ETHTOOL_LINK_MODE_1000baseT_Full_BIT
,
102 .duplex
= DUPLEX_HALF
,
103 .bit
= ETHTOOL_LINK_MODE_1000baseT_Half_BIT
,
107 .duplex
= DUPLEX_FULL
,
108 .bit
= ETHTOOL_LINK_MODE_100baseT_Full_BIT
,
112 .duplex
= DUPLEX_HALF
,
113 .bit
= ETHTOOL_LINK_MODE_100baseT_Half_BIT
,
117 .duplex
= DUPLEX_FULL
,
118 .bit
= ETHTOOL_LINK_MODE_10baseT_Full_BIT
,
122 .duplex
= DUPLEX_HALF
,
123 .bit
= ETHTOOL_LINK_MODE_10baseT_Half_BIT
,
128 * phy_lookup_setting - lookup a PHY setting
129 * @speed: speed to match
130 * @duplex: duplex to match
131 * @mask: allowed link modes
132 * @maxbit: bit size of link modes
133 * @exact: an exact match is required
135 * Search the settings array for a setting that matches the speed and
136 * duplex, and which is supported.
138 * If @exact is unset, either an exact match or %NULL for no match will
141 * If @exact is set, an exact match, the fastest supported setting at
142 * or below the specified speed, the slowest supported setting, or if
143 * they all fail, %NULL will be returned.
145 const struct phy_setting
*
146 phy_lookup_setting(int speed
, int duplex
, const unsigned long *mask
,
147 size_t maxbit
, bool exact
)
149 const struct phy_setting
*p
, *match
= NULL
, *last
= NULL
;
152 for (i
= 0, p
= settings
; i
< ARRAY_SIZE(settings
); i
++, p
++) {
153 if (p
->bit
< maxbit
&& test_bit(p
->bit
, mask
)) {
155 if (p
->speed
== speed
&& p
->duplex
== duplex
) {
156 /* Exact match for speed and duplex */
160 if (!match
&& p
->speed
<= speed
)
164 if (p
->speed
< speed
)
170 if (!match
&& !exact
)
175 EXPORT_SYMBOL_GPL(phy_lookup_setting
);
177 size_t phy_speeds(unsigned int *speeds
, size_t size
,
178 unsigned long *mask
, size_t maxbit
)
183 for (i
= 0, count
= 0; i
< ARRAY_SIZE(settings
) && count
< size
; i
++)
184 if (settings
[i
].bit
< maxbit
&&
185 test_bit(settings
[i
].bit
, mask
) &&
186 (count
== 0 || speeds
[count
- 1] != settings
[i
].speed
))
187 speeds
[count
++] = settings
[i
].speed
;
192 static void mmd_phy_indirect(struct mii_bus
*bus
, int phy_addr
, int devad
,
195 /* Write the desired MMD Devad */
196 bus
->write(bus
, phy_addr
, MII_MMD_CTRL
, devad
);
198 /* Write the desired MMD register address */
199 bus
->write(bus
, phy_addr
, MII_MMD_DATA
, regnum
);
201 /* Select the Function : DATA with no post increment */
202 bus
->write(bus
, phy_addr
, MII_MMD_CTRL
, devad
| MII_MMD_CTRL_NOINCR
);
206 * phy_read_mmd - Convenience function for reading a register
207 * from an MMD on a given PHY.
208 * @phydev: The phy_device struct
209 * @devad: The MMD to read from (0..31)
210 * @regnum: The register on the MMD to read (0..65535)
212 * Same rules as for phy_read();
214 int phy_read_mmd(struct phy_device
*phydev
, int devad
, u32 regnum
)
218 if (regnum
> (u16
)~0 || devad
> 32)
221 if (phydev
->drv
->read_mmd
) {
222 val
= phydev
->drv
->read_mmd(phydev
, devad
, regnum
);
223 } else if (phydev
->is_c45
) {
224 u32 addr
= MII_ADDR_C45
| (devad
<< 16) | (regnum
& 0xffff);
226 val
= mdiobus_read(phydev
->mdio
.bus
, phydev
->mdio
.addr
, addr
);
228 struct mii_bus
*bus
= phydev
->mdio
.bus
;
229 int phy_addr
= phydev
->mdio
.addr
;
231 mutex_lock(&bus
->mdio_lock
);
232 mmd_phy_indirect(bus
, phy_addr
, devad
, regnum
);
234 /* Read the content of the MMD's selected register */
235 val
= bus
->read(bus
, phy_addr
, MII_MMD_DATA
);
236 mutex_unlock(&bus
->mdio_lock
);
240 EXPORT_SYMBOL(phy_read_mmd
);
243 * phy_write_mmd - Convenience function for writing a register
244 * on an MMD on a given PHY.
245 * @phydev: The phy_device struct
246 * @devad: The MMD to read from
247 * @regnum: The register on the MMD to read
248 * @val: value to write to @regnum
250 * Same rules as for phy_write();
252 int phy_write_mmd(struct phy_device
*phydev
, int devad
, u32 regnum
, u16 val
)
256 if (regnum
> (u16
)~0 || devad
> 32)
259 if (phydev
->drv
->write_mmd
) {
260 ret
= phydev
->drv
->write_mmd(phydev
, devad
, regnum
, val
);
261 } else if (phydev
->is_c45
) {
262 u32 addr
= MII_ADDR_C45
| (devad
<< 16) | (regnum
& 0xffff);
264 ret
= mdiobus_write(phydev
->mdio
.bus
, phydev
->mdio
.addr
,
267 struct mii_bus
*bus
= phydev
->mdio
.bus
;
268 int phy_addr
= phydev
->mdio
.addr
;
270 mutex_lock(&bus
->mdio_lock
);
271 mmd_phy_indirect(bus
, phy_addr
, devad
, regnum
);
273 /* Write the data into MMD's selected register */
274 bus
->write(bus
, phy_addr
, MII_MMD_DATA
, val
);
275 mutex_unlock(&bus
->mdio_lock
);
281 EXPORT_SYMBOL(phy_write_mmd
);