kernel: bump 4.9 to 4.9.77
[openwrt/openwrt.git] / target / linux / mvebu / patches-4.9 / 407-net-phy-add-802.3-clause-45-support-to-phylib.patch
1 From: Russell King <rmk+kernel@armlinux.org.uk>
2 Date: Thu, 29 Dec 2016 11:03:09 +0000
3 Subject: [PATCH] net: phy: add 802.3 clause 45 support to phylib
4
5 Add generic helpers for 802.3 clause 45 PHYs for >= 10Gbps support.
6
7 Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
8 ---
9 create mode 100644 drivers/net/phy/phy-c45.c
10
11 --- a/drivers/net/phy/Makefile
12 +++ b/drivers/net/phy/Makefile
13 @@ -1,7 +1,7 @@
14 # Makefile for Linux PHY drivers and MDIO bus drivers
15
16 libphy-y := phy.o phy_device.o mdio_bus.o mdio_device.o \
17 - phy-core.o
18 + phy-c45.o phy-core.o
19 libphy-$(CONFIG_SWPHY) += swphy.o
20
21 obj-$(CONFIG_MDIO_BOARDINFO) += mdio-boardinfo.o
22 --- /dev/null
23 +++ b/drivers/net/phy/phy-c45.c
24 @@ -0,0 +1,234 @@
25 +/*
26 + * Clause 45 PHY support
27 + */
28 +#include <linux/ethtool.h>
29 +#include <linux/export.h>
30 +#include <linux/mdio.h>
31 +#include <linux/mii.h>
32 +#include <linux/phy.h>
33 +
34 +/**
35 + * genphy_c45_setup_forced - configures a forced speed
36 + * @phydev: target phy_device struct
37 + */
38 +int genphy_c45_pma_setup_forced(struct phy_device *phydev)
39 +{
40 + int ctrl1, ctrl2, ret;
41 +
42 + /* Half duplex is not supported */
43 + if (phydev->duplex != DUPLEX_FULL)
44 + return -EINVAL;
45 +
46 + ctrl1 = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_CTRL1);
47 + if (ctrl1 < 0)
48 + return ctrl1;
49 +
50 + ctrl2 = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_CTRL2);
51 + if (ctrl2 < 0)
52 + return ctrl2;
53 +
54 + ctrl1 &= ~MDIO_CTRL1_SPEEDSEL;
55 + /* PMA/PMD type selection is 1.7.5:0 not 1.7.3:0. See 45.2.1.6.1. */
56 + ctrl2 &= ~(MDIO_PMA_CTRL2_TYPE | 0x30);
57 +
58 + switch (phydev->speed) {
59 + case SPEED_10:
60 + ctrl2 |= MDIO_PMA_CTRL2_10BT;
61 + break;
62 + case SPEED_100:
63 + ctrl1 |= MDIO_PMA_CTRL1_SPEED100;
64 + ctrl2 |= MDIO_PMA_CTRL2_100BTX;
65 + break;
66 + case SPEED_1000:
67 + ctrl1 |= MDIO_PMA_CTRL1_SPEED1000;
68 + /* Assume 1000base-T */
69 + ctrl2 |= MDIO_PMA_CTRL2_1000BT;
70 + break;
71 + case SPEED_10000:
72 + ctrl1 |= MDIO_CTRL1_SPEED10G;
73 + /* Assume 10Gbase-T */
74 + ctrl2 |= MDIO_PMA_CTRL2_10GBT;
75 + break;
76 + default:
77 + return -EINVAL;
78 + }
79 +
80 + ret = phy_write_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_CTRL1, ctrl1);
81 + if (ret < 0)
82 + return ret;
83 +
84 + return phy_write_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_CTRL2, ctrl2);
85 +}
86 +EXPORT_SYMBOL_GPL(genphy_c45_pma_setup_forced);
87 +
88 +/**
89 + * genphy_c45_an_disable_aneg - disable auto-negotiation
90 + * @phydev: target phy_device struct
91 + *
92 + * Disable auto-negotiation in the Clause 45 PHY. The link parameters
93 + * parameters are controlled through the PMA/PMD MMD registers.
94 + *
95 + * Returns zero on success, negative errno code on failure.
96 + */
97 +int genphy_c45_an_disable_aneg(struct phy_device *phydev)
98 +{
99 + int val;
100 +
101 + val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1);
102 + if (val < 0)
103 + return val;
104 +
105 + val &= ~(MDIO_AN_CTRL1_ENABLE | MDIO_AN_CTRL1_RESTART);
106 +
107 + return phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1, val);
108 +}
109 +EXPORT_SYMBOL_GPL(genphy_c45_an_disable_aneg);
110 +
111 +/**
112 + * genphy_c45_restart_aneg - Enable and restart auto-negotiation
113 + * @phydev: target phy_device struct
114 + *
115 + * This assumes that the auto-negotiation MMD is present.
116 + *
117 + * Enable and restart auto-negotiation.
118 + */
119 +int genphy_c45_restart_aneg(struct phy_device *phydev)
120 +{
121 + int val;
122 +
123 + val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1);
124 + if (val < 0)
125 + return val;
126 +
127 + val |= MDIO_AN_CTRL1_ENABLE | MDIO_AN_CTRL1_RESTART;
128 +
129 + return phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1, val);
130 +}
131 +EXPORT_SYMBOL_GPL(genphy_c45_restart_aneg);
132 +
133 +/**
134 + * genphy_c45_aneg_done - return auto-negotiation complete status
135 + * @phydev: target phy_device struct
136 + *
137 + * This assumes that the auto-negotiation MMD is present.
138 + *
139 + * Reads the status register from the auto-negotiation MMD, returning:
140 + * - positive if auto-negotiation is complete
141 + * - negative errno code on error
142 + * - zero otherwise
143 + */
144 +int genphy_c45_aneg_done(struct phy_device *phydev)
145 +{
146 + int val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_STAT1);
147 +
148 + return val < 0 ? val : val & MDIO_AN_STAT1_COMPLETE ? 1 : 0;
149 +}
150 +EXPORT_SYMBOL_GPL(genphy_c45_aneg_done);
151 +
152 +/**
153 + * genphy_c45_read_link - read the overall link status from the MMDs
154 + * @phydev: target phy_device struct
155 + * @mmd_mask: MMDs to read status from
156 + *
157 + * Read the link status from the specified MMDs, and if they all indicate
158 + * that the link is up, return positive. If an error is encountered,
159 + * a negative errno will be returned, otherwise zero.
160 + */
161 +int genphy_c45_read_link(struct phy_device *phydev, u32 mmd_mask)
162 +{
163 + int val, devad;
164 + bool link = true;
165 +
166 + while (mmd_mask) {
167 + devad = __ffs(mmd_mask);
168 + mmd_mask &= ~BIT(devad);
169 +
170 + val = phy_read_mmd(phydev, devad, MDIO_STAT1);
171 + if (val < 0)
172 + return val;
173 +
174 + /* Read twice because link state is latched and a
175 + * read moves the current state into the register
176 + */
177 + val = phy_read_mmd(phydev, devad, MDIO_STAT1);
178 + if (val < 0)
179 + return val;
180 +
181 + if (!(val & MDIO_STAT1_LSTATUS))
182 + link = false;
183 + }
184 +
185 + return link;
186 +}
187 +EXPORT_SYMBOL_GPL(genphy_c45_read_link);
188 +
189 +/**
190 + * genphy_c45_read_lpa - read the link partner advertisment and pause
191 + * @phydev: target phy_device struct
192 + *
193 + * Read the Clause 45 defined base (7.19) and 10G (7.33) status registers,
194 + * filling in the link partner advertisment, pause and asym_pause members
195 + * in @phydev. This assumes that the auto-negotiation MMD is present, and
196 + * the backplane bit (7.48.0) is clear. Clause 45 PHY drivers are expected
197 + * to fill in the remainder of the link partner advert from vendor registers.
198 + */
199 +int genphy_c45_read_lpa(struct phy_device *phydev)
200 +{
201 + int val;
202 +
203 + /* Read the link partner's base page advertisment */
204 + val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_LPA);
205 + if (val < 0)
206 + return val;
207 +
208 + phydev->lp_advertising = mii_lpa_to_ethtool_lpa_t(val);
209 + phydev->pause = val & LPA_PAUSE_CAP ? 1 : 0;
210 + phydev->asym_pause = val & LPA_PAUSE_ASYM ? 1 : 0;
211 +
212 + /* Read the link partner's 10G advertisment */
213 + val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_STAT);
214 + if (val < 0)
215 + return val;
216 +
217 + if (val & MDIO_AN_10GBT_STAT_LP10G)
218 + phydev->lp_advertising |= ADVERTISED_10000baseT_Full;
219 +
220 + return 0;
221 +}
222 +EXPORT_SYMBOL_GPL(genphy_c45_read_lpa);
223 +
224 +/**
225 + * genphy_c45_read_pma - read link speed etc from PMA
226 + * @phydev: target phy_device struct
227 + */
228 +int genphy_c45_read_pma(struct phy_device *phydev)
229 +{
230 + int val;
231 +
232 + val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_CTRL1);
233 + if (val < 0)
234 + return val;
235 +
236 + switch (val & MDIO_CTRL1_SPEEDSEL) {
237 + case 0:
238 + phydev->speed = SPEED_10;
239 + break;
240 + case MDIO_PMA_CTRL1_SPEED100:
241 + phydev->speed = SPEED_100;
242 + break;
243 + case MDIO_PMA_CTRL1_SPEED1000:
244 + phydev->speed = SPEED_1000;
245 + break;
246 + case MDIO_CTRL1_SPEED10G:
247 + phydev->speed = SPEED_10000;
248 + break;
249 + default:
250 + phydev->speed = SPEED_UNKNOWN;
251 + break;
252 + }
253 +
254 + phydev->duplex = DUPLEX_FULL;
255 +
256 + return 0;
257 +}
258 +EXPORT_SYMBOL_GPL(genphy_c45_read_pma);
259 --- a/drivers/net/phy/phy_device.c
260 +++ b/drivers/net/phy/phy_device.c
261 @@ -1452,27 +1452,19 @@ EXPORT_SYMBOL(genphy_read_status);
262
263 static int gen10g_read_status(struct phy_device *phydev)
264 {
265 - int devad, reg;
266 u32 mmd_mask = phydev->c45_ids.devices_in_package;
267 -
268 - phydev->link = 1;
269 + int ret;
270
271 /* For now just lie and say it's 10G all the time */
272 phydev->speed = SPEED_10000;
273 phydev->duplex = DUPLEX_FULL;
274
275 - for (devad = 0; mmd_mask; devad++, mmd_mask = mmd_mask >> 1) {
276 - if (!(mmd_mask & 1))
277 - continue;
278 -
279 - /* Read twice because link state is latched and a
280 - * read moves the current state into the register
281 - */
282 - phy_read_mmd(phydev, devad, MDIO_STAT1);
283 - reg = phy_read_mmd(phydev, devad, MDIO_STAT1);
284 - if (reg < 0 || !(reg & MDIO_STAT1_LSTATUS))
285 - phydev->link = 0;
286 - }
287 + /* Avoid reading the vendor MMDs */
288 + mmd_mask &= ~(BIT(MDIO_MMD_VEND1) | BIT(MDIO_MMD_VEND2));
289 +
290 + ret = genphy_c45_read_link(phydev, mmd_mask);
291 +
292 + phydev->link = ret > 0 ? 1 : 0;
293
294 return 0;
295 }
296 --- a/include/linux/phy.h
297 +++ b/include/linux/phy.h
298 @@ -817,6 +817,8 @@ static inline const char *phydev_name(co
299 void phy_attached_print(struct phy_device *phydev, const char *fmt, ...)
300 __printf(2, 3);
301 void phy_attached_info(struct phy_device *phydev);
302 +
303 +/* Clause 22 PHY */
304 int genphy_config_init(struct phy_device *phydev);
305 int genphy_setup_forced(struct phy_device *phydev);
306 int genphy_restart_aneg(struct phy_device *phydev);
307 @@ -831,6 +833,16 @@ static inline int genphy_no_soft_reset(s
308 {
309 return 0;
310 }
311 +
312 +/* Clause 45 PHY */
313 +int genphy_c45_restart_aneg(struct phy_device *phydev);
314 +int genphy_c45_aneg_done(struct phy_device *phydev);
315 +int genphy_c45_read_link(struct phy_device *phydev, u32 mmd_mask);
316 +int genphy_c45_read_lpa(struct phy_device *phydev);
317 +int genphy_c45_read_pma(struct phy_device *phydev);
318 +int genphy_c45_pma_setup_forced(struct phy_device *phydev);
319 +int genphy_c45_an_disable_aneg(struct phy_device *phydev);
320 +
321 void phy_driver_unregister(struct phy_driver *drv);
322 void phy_drivers_unregister(struct phy_driver *drv, int n);
323 int phy_driver_register(struct phy_driver *new_driver, struct module *owner);