blob: 8ea5b0d1331611ffb6c1aebb3498ec5127c1f8ca [file] [log] [blame]
Sergei Shtylyov2f53e902014-01-05 03:17:06 +03001/* Framework for configuring and reading PHY devices
Andy Fleming00db8182005-07-30 19:31:23 -04002 * Based on code in sungem_phy.c and gianfar_phy.c
3 *
4 * Author: Andy Fleming
5 *
6 * Copyright (c) 2004 Freescale Semiconductor, Inc.
Maciej W. Rozycki0ac49522007-09-28 22:42:14 -07007 * Copyright (c) 2006, 2007 Maciej W. Rozycki
Andy Fleming00db8182005-07-30 19:31:23 -04008 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version.
13 *
14 */
Joe Perches8d242482012-06-09 07:49:07 +000015
16#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
17
Andy Fleming00db8182005-07-30 19:31:23 -040018#include <linux/kernel.h>
Andy Fleming00db8182005-07-30 19:31:23 -040019#include <linux/string.h>
20#include <linux/errno.h>
21#include <linux/unistd.h>
Andy Fleming00db8182005-07-30 19:31:23 -040022#include <linux/interrupt.h>
23#include <linux/init.h>
24#include <linux/delay.h>
25#include <linux/netdevice.h>
26#include <linux/etherdevice.h>
27#include <linux/skbuff.h>
Andy Fleming00db8182005-07-30 19:31:23 -040028#include <linux/mm.h>
29#include <linux/module.h>
Andy Fleming00db8182005-07-30 19:31:23 -040030#include <linux/mii.h>
31#include <linux/ethtool.h>
32#include <linux/phy.h>
Maciej W. Rozycki3c3070d2006-10-03 16:18:35 +010033#include <linux/timer.h>
34#include <linux/workqueue.h>
Giuseppe CAVALLAROa59a4d12012-06-27 21:14:38 +000035#include <linux/mdio.h>
Sergei Shtylyov2f53e902014-01-05 03:17:06 +030036#include <linux/io.h>
37#include <linux/uaccess.h>
Arun Sharma600634972011-07-26 16:09:06 -070038#include <linux/atomic.h>
Sergei Shtylyov2f53e902014-01-05 03:17:06 +030039
Andy Fleming00db8182005-07-30 19:31:23 -040040#include <asm/irq.h>
Andy Fleming00db8182005-07-30 19:31:23 -040041
Randy Dunlapb3df0da2007-03-06 02:41:48 -080042/**
43 * phy_print_status - Convenience function to print out the current phy status
44 * @phydev: the phy_device struct
Andy Fleminge1393452005-08-24 18:46:21 -050045 */
46void phy_print_status(struct phy_device *phydev)
47{
Sergei Shtylyov2f53e902014-01-05 03:17:06 +030048 if (phydev->link) {
Joe Perches8d242482012-06-09 07:49:07 +000049 pr_info("%s - Link is Up - %d/%s\n",
50 dev_name(&phydev->dev),
51 phydev->speed,
52 DUPLEX_FULL == phydev->duplex ? "Full" : "Half");
Sergei Shtylyov2f53e902014-01-05 03:17:06 +030053 } else {
Joe Perches8d242482012-06-09 07:49:07 +000054 pr_info("%s - Link is Down\n", dev_name(&phydev->dev));
Sergei Shtylyov2f53e902014-01-05 03:17:06 +030055 }
Andy Fleminge1393452005-08-24 18:46:21 -050056}
57EXPORT_SYMBOL(phy_print_status);
Andy Fleming00db8182005-07-30 19:31:23 -040058
Randy Dunlapb3df0da2007-03-06 02:41:48 -080059/**
Randy Dunlapb3df0da2007-03-06 02:41:48 -080060 * phy_clear_interrupt - Ack the phy device's interrupt
61 * @phydev: the phy_device struct
62 *
63 * If the @phydev driver has an ack_interrupt function, call it to
64 * ack and clear the phy device's interrupt.
65 *
66 * Returns 0 on success on < 0 on error.
67 */
stephen hemminger89ff05e2010-10-21 08:37:41 +000068static int phy_clear_interrupt(struct phy_device *phydev)
Andy Fleming00db8182005-07-30 19:31:23 -040069{
Andy Fleming00db8182005-07-30 19:31:23 -040070 if (phydev->drv->ack_interrupt)
Sergei Shtylyove62a7682014-01-05 03:21:52 +030071 return phydev->drv->ack_interrupt(phydev);
Andy Fleming00db8182005-07-30 19:31:23 -040072
Sergei Shtylyove62a7682014-01-05 03:21:52 +030073 return 0;
Andy Fleming00db8182005-07-30 19:31:23 -040074}
75
Randy Dunlapb3df0da2007-03-06 02:41:48 -080076/**
77 * phy_config_interrupt - configure the PHY device for the requested interrupts
78 * @phydev: the phy_device struct
79 * @interrupts: interrupt flags to configure for this @phydev
80 *
81 * Returns 0 on success on < 0 on error.
82 */
stephen hemminger89ff05e2010-10-21 08:37:41 +000083static int phy_config_interrupt(struct phy_device *phydev, u32 interrupts)
Andy Fleming00db8182005-07-30 19:31:23 -040084{
Andy Fleming00db8182005-07-30 19:31:23 -040085 phydev->interrupts = interrupts;
86 if (phydev->drv->config_intr)
Sergei Shtylyove62a7682014-01-05 03:21:52 +030087 return phydev->drv->config_intr(phydev);
Andy Fleming00db8182005-07-30 19:31:23 -040088
Sergei Shtylyove62a7682014-01-05 03:21:52 +030089 return 0;
Andy Fleming00db8182005-07-30 19:31:23 -040090}
91
92
Randy Dunlapb3df0da2007-03-06 02:41:48 -080093/**
94 * phy_aneg_done - return auto-negotiation status
95 * @phydev: target phy_device struct
Andy Fleming00db8182005-07-30 19:31:23 -040096 *
Randy Dunlapb3df0da2007-03-06 02:41:48 -080097 * Description: Reads the status register and returns 0 either if
Andy Fleming00db8182005-07-30 19:31:23 -040098 * auto-negotiation is incomplete, or if there was an error.
99 * Returns BMSR_ANEGCOMPLETE if auto-negotiation is done.
100 */
101static inline int phy_aneg_done(struct phy_device *phydev)
102{
103 int retval;
104
105 retval = phy_read(phydev, MII_BMSR);
106
107 return (retval < 0) ? retval : (retval & BMSR_ANEGCOMPLETE);
108}
109
Andy Fleming00db8182005-07-30 19:31:23 -0400110/* A structure for mapping a particular speed and duplex
Sergei Shtylyov2f53e902014-01-05 03:17:06 +0300111 * combination to a particular SUPPORTED and ADVERTISED value
112 */
Andy Fleming00db8182005-07-30 19:31:23 -0400113struct phy_setting {
114 int speed;
115 int duplex;
116 u32 setting;
117};
118
119/* A mapping of all SUPPORTED settings to speed/duplex */
Arjan van de Venf71e1302006-03-03 21:33:57 -0500120static const struct phy_setting settings[] = {
Andy Fleming00db8182005-07-30 19:31:23 -0400121 {
122 .speed = 10000,
123 .duplex = DUPLEX_FULL,
124 .setting = SUPPORTED_10000baseT_Full,
125 },
126 {
127 .speed = SPEED_1000,
128 .duplex = DUPLEX_FULL,
129 .setting = SUPPORTED_1000baseT_Full,
130 },
131 {
132 .speed = SPEED_1000,
133 .duplex = DUPLEX_HALF,
134 .setting = SUPPORTED_1000baseT_Half,
135 },
136 {
137 .speed = SPEED_100,
138 .duplex = DUPLEX_FULL,
139 .setting = SUPPORTED_100baseT_Full,
140 },
141 {
142 .speed = SPEED_100,
143 .duplex = DUPLEX_HALF,
144 .setting = SUPPORTED_100baseT_Half,
145 },
146 {
147 .speed = SPEED_10,
148 .duplex = DUPLEX_FULL,
149 .setting = SUPPORTED_10baseT_Full,
150 },
151 {
152 .speed = SPEED_10,
153 .duplex = DUPLEX_HALF,
154 .setting = SUPPORTED_10baseT_Half,
155 },
156};
157
Denis Chengff8ac602007-09-02 18:30:18 +0800158#define MAX_NUM_SETTINGS ARRAY_SIZE(settings)
Andy Fleming00db8182005-07-30 19:31:23 -0400159
Randy Dunlapb3df0da2007-03-06 02:41:48 -0800160/**
161 * phy_find_setting - find a PHY settings array entry that matches speed & duplex
162 * @speed: speed to match
163 * @duplex: duplex to match
Andy Fleming00db8182005-07-30 19:31:23 -0400164 *
Randy Dunlapb3df0da2007-03-06 02:41:48 -0800165 * Description: Searches the settings array for the setting which
Andy Fleming00db8182005-07-30 19:31:23 -0400166 * matches the desired speed and duplex, and returns the index
167 * of that setting. Returns the index of the last setting if
168 * none of the others match.
169 */
170static inline int phy_find_setting(int speed, int duplex)
171{
172 int idx = 0;
173
174 while (idx < ARRAY_SIZE(settings) &&
Sergei Shtylyov2f53e902014-01-05 03:17:06 +0300175 (settings[idx].speed != speed || settings[idx].duplex != duplex))
Andy Fleming00db8182005-07-30 19:31:23 -0400176 idx++;
177
178 return idx < MAX_NUM_SETTINGS ? idx : MAX_NUM_SETTINGS - 1;
179}
180
Randy Dunlapb3df0da2007-03-06 02:41:48 -0800181/**
182 * phy_find_valid - find a PHY setting that matches the requested features mask
183 * @idx: The first index in settings[] to search
184 * @features: A mask of the valid settings
Andy Fleming00db8182005-07-30 19:31:23 -0400185 *
Randy Dunlapb3df0da2007-03-06 02:41:48 -0800186 * Description: Returns the index of the first valid setting less
Andy Fleming00db8182005-07-30 19:31:23 -0400187 * than or equal to the one pointed to by idx, as determined by
188 * the mask in features. Returns the index of the last setting
189 * if nothing else matches.
190 */
191static inline int phy_find_valid(int idx, u32 features)
192{
193 while (idx < MAX_NUM_SETTINGS && !(settings[idx].setting & features))
194 idx++;
195
196 return idx < MAX_NUM_SETTINGS ? idx : MAX_NUM_SETTINGS - 1;
197}
198
Randy Dunlapb3df0da2007-03-06 02:41:48 -0800199/**
200 * phy_sanitize_settings - make sure the PHY is set to supported speed and duplex
201 * @phydev: the target phy_device struct
Andy Fleming00db8182005-07-30 19:31:23 -0400202 *
Randy Dunlapb3df0da2007-03-06 02:41:48 -0800203 * Description: Make sure the PHY is set to supported speeds and
Andy Fleming00db8182005-07-30 19:31:23 -0400204 * duplexes. Drop down by one in this order: 1000/FULL,
Randy Dunlapb3df0da2007-03-06 02:41:48 -0800205 * 1000/HALF, 100/FULL, 100/HALF, 10/FULL, 10/HALF.
Andy Fleming00db8182005-07-30 19:31:23 -0400206 */
stephen hemminger89ff05e2010-10-21 08:37:41 +0000207static void phy_sanitize_settings(struct phy_device *phydev)
Andy Fleming00db8182005-07-30 19:31:23 -0400208{
209 u32 features = phydev->supported;
210 int idx;
211
212 /* Sanitize settings based on PHY capabilities */
213 if ((features & SUPPORTED_Autoneg) == 0)
Domen Puncer163642a2007-08-07 12:12:41 +0200214 phydev->autoneg = AUTONEG_DISABLE;
Andy Fleming00db8182005-07-30 19:31:23 -0400215
216 idx = phy_find_valid(phy_find_setting(phydev->speed, phydev->duplex),
217 features);
218
219 phydev->speed = settings[idx].speed;
220 phydev->duplex = settings[idx].duplex;
221}
Andy Fleming00db8182005-07-30 19:31:23 -0400222
Randy Dunlapb3df0da2007-03-06 02:41:48 -0800223/**
224 * phy_ethtool_sset - generic ethtool sset function, handles all the details
225 * @phydev: target phy_device struct
226 * @cmd: ethtool_cmd
Andy Fleming00db8182005-07-30 19:31:23 -0400227 *
228 * A few notes about parameter checking:
229 * - We don't set port or transceiver, so we don't care what they
230 * were set to.
231 * - phy_start_aneg() will make sure forced settings are sane, and
232 * choose the next best ones from the ones selected, so we don't
Randy Dunlapb3df0da2007-03-06 02:41:48 -0800233 * care if ethtool tries to give us bad values.
Andy Fleming00db8182005-07-30 19:31:23 -0400234 */
235int phy_ethtool_sset(struct phy_device *phydev, struct ethtool_cmd *cmd)
236{
David Decotigny25db0332011-04-27 18:32:39 +0000237 u32 speed = ethtool_cmd_speed(cmd);
238
Andy Fleming00db8182005-07-30 19:31:23 -0400239 if (cmd->phy_address != phydev->addr)
240 return -EINVAL;
241
Sergei Shtylyov2f53e902014-01-05 03:17:06 +0300242 /* We make sure that we don't pass unsupported values in to the PHY */
Andy Fleming00db8182005-07-30 19:31:23 -0400243 cmd->advertising &= phydev->supported;
244
245 /* Verify the settings we care about. */
246 if (cmd->autoneg != AUTONEG_ENABLE && cmd->autoneg != AUTONEG_DISABLE)
247 return -EINVAL;
248
249 if (cmd->autoneg == AUTONEG_ENABLE && cmd->advertising == 0)
250 return -EINVAL;
251
Joe Perches8e95a202009-12-03 07:58:21 +0000252 if (cmd->autoneg == AUTONEG_DISABLE &&
David Decotigny25db0332011-04-27 18:32:39 +0000253 ((speed != SPEED_1000 &&
254 speed != SPEED_100 &&
255 speed != SPEED_10) ||
Joe Perches8e95a202009-12-03 07:58:21 +0000256 (cmd->duplex != DUPLEX_HALF &&
257 cmd->duplex != DUPLEX_FULL)))
Andy Fleming00db8182005-07-30 19:31:23 -0400258 return -EINVAL;
259
260 phydev->autoneg = cmd->autoneg;
261
David Decotigny25db0332011-04-27 18:32:39 +0000262 phydev->speed = speed;
Andy Fleming00db8182005-07-30 19:31:23 -0400263
264 phydev->advertising = cmd->advertising;
265
266 if (AUTONEG_ENABLE == cmd->autoneg)
267 phydev->advertising |= ADVERTISED_Autoneg;
268 else
269 phydev->advertising &= ~ADVERTISED_Autoneg;
270
271 phydev->duplex = cmd->duplex;
272
273 /* Restart the PHY */
274 phy_start_aneg(phydev);
275
276 return 0;
277}
Kumar Gala9f6d55d2007-01-20 16:38:26 -0600278EXPORT_SYMBOL(phy_ethtool_sset);
Andy Fleming00db8182005-07-30 19:31:23 -0400279
280int phy_ethtool_gset(struct phy_device *phydev, struct ethtool_cmd *cmd)
281{
282 cmd->supported = phydev->supported;
283
284 cmd->advertising = phydev->advertising;
Florian Fainelli114002b2013-12-06 13:01:30 -0800285 cmd->lp_advertising = phydev->lp_advertising;
Andy Fleming00db8182005-07-30 19:31:23 -0400286
David Decotigny70739492011-04-27 18:32:40 +0000287 ethtool_cmd_speed_set(cmd, phydev->speed);
Andy Fleming00db8182005-07-30 19:31:23 -0400288 cmd->duplex = phydev->duplex;
289 cmd->port = PORT_MII;
290 cmd->phy_address = phydev->addr;
Florian Fainelli4284b6a2013-05-23 01:11:12 +0000291 cmd->transceiver = phy_is_internal(phydev) ?
292 XCVR_INTERNAL : XCVR_EXTERNAL;
Andy Fleming00db8182005-07-30 19:31:23 -0400293 cmd->autoneg = phydev->autoneg;
294
295 return 0;
296}
Kumar Gala9f6d55d2007-01-20 16:38:26 -0600297EXPORT_SYMBOL(phy_ethtool_gset);
Andy Fleming00db8182005-07-30 19:31:23 -0400298
Randy Dunlapb3df0da2007-03-06 02:41:48 -0800299/**
300 * phy_mii_ioctl - generic PHY MII ioctl interface
301 * @phydev: the phy_device struct
Randy Dunlap00c7d922010-08-09 13:41:59 +0000302 * @ifr: &struct ifreq for socket ioctl's
Randy Dunlapb3df0da2007-03-06 02:41:48 -0800303 * @cmd: ioctl cmd to execute
304 *
305 * Note that this function is currently incompatible with the
Andy Fleming00db8182005-07-30 19:31:23 -0400306 * PHYCONTROL layer. It changes registers without regard to
Randy Dunlapb3df0da2007-03-06 02:41:48 -0800307 * current state. Use at own risk.
Andy Fleming00db8182005-07-30 19:31:23 -0400308 */
Sergei Shtylyov2f53e902014-01-05 03:17:06 +0300309int phy_mii_ioctl(struct phy_device *phydev, struct ifreq *ifr, int cmd)
Andy Fleming00db8182005-07-30 19:31:23 -0400310{
Richard Cochran28b04112010-07-17 08:48:55 +0000311 struct mii_ioctl_data *mii_data = if_mii(ifr);
Andy Fleming00db8182005-07-30 19:31:23 -0400312 u16 val = mii_data->val_in;
313
314 switch (cmd) {
315 case SIOCGMIIPHY:
316 mii_data->phy_id = phydev->addr;
Lennert Buytenhekc6d6a512008-09-18 03:06:52 +0000317 /* fall through */
318
Andy Fleming00db8182005-07-30 19:31:23 -0400319 case SIOCGMIIREG:
Peter Korsgaardaf1dc132011-03-10 06:52:13 +0000320 mii_data->val_out = mdiobus_read(phydev->bus, mii_data->phy_id,
321 mii_data->reg_num);
Sergei Shtylyove62a7682014-01-05 03:21:52 +0300322 return 0;
Andy Fleming00db8182005-07-30 19:31:23 -0400323
324 case SIOCSMIIREG:
Andy Fleming00db8182005-07-30 19:31:23 -0400325 if (mii_data->phy_id == phydev->addr) {
Florian Fainellie1093742013-12-17 21:38:12 -0800326 switch (mii_data->reg_num) {
Andy Fleming00db8182005-07-30 19:31:23 -0400327 case MII_BMCR:
Sergei Shtylyov2f53e902014-01-05 03:17:06 +0300328 if ((val & (BMCR_RESET | BMCR_ANENABLE)) == 0)
Andy Fleming00db8182005-07-30 19:31:23 -0400329 phydev->autoneg = AUTONEG_DISABLE;
330 else
331 phydev->autoneg = AUTONEG_ENABLE;
Sergei Shtylyov2f53e902014-01-05 03:17:06 +0300332 if (!phydev->autoneg && (val & BMCR_FULLDPLX))
Andy Fleming00db8182005-07-30 19:31:23 -0400333 phydev->duplex = DUPLEX_FULL;
334 else
335 phydev->duplex = DUPLEX_HALF;
Sergei Shtylyov2f53e902014-01-05 03:17:06 +0300336 if (!phydev->autoneg && (val & BMCR_SPEED1000))
Shan Lu024a0a32007-03-06 02:42:03 -0800337 phydev->speed = SPEED_1000;
Sergei Shtylyov2f53e902014-01-05 03:17:06 +0300338 else if (!phydev->autoneg &&
339 (val & BMCR_SPEED100))
Shan Lu024a0a32007-03-06 02:42:03 -0800340 phydev->speed = SPEED_100;
Andy Fleming00db8182005-07-30 19:31:23 -0400341 break;
342 case MII_ADVERTISE:
343 phydev->advertising = val;
344 break;
345 default:
346 /* do nothing */
347 break;
348 }
349 }
350
Peter Korsgaardaf1dc132011-03-10 06:52:13 +0000351 mdiobus_write(phydev->bus, mii_data->phy_id,
352 mii_data->reg_num, val);
353
Joe Perches8e95a202009-12-03 07:58:21 +0000354 if (mii_data->reg_num == MII_BMCR &&
Florian Fainelli2613f952013-12-06 13:01:31 -0800355 val & BMCR_RESET)
Sergei Shtylyove62a7682014-01-05 03:21:52 +0300356 return phy_init_hw(phydev);
357 return 0;
David Woodhousedda93b482007-11-28 19:56:34 +0000358
Richard Cochranc1f19b52010-07-17 08:49:36 +0000359 case SIOCSHWTSTAMP:
360 if (phydev->drv->hwtstamp)
361 return phydev->drv->hwtstamp(phydev, ifr);
362 /* fall through */
363
David Woodhousedda93b482007-11-28 19:56:34 +0000364 default:
Lennert Buytenhekc6d6a512008-09-18 03:06:52 +0000365 return -EOPNOTSUPP;
Andy Fleming00db8182005-07-30 19:31:23 -0400366 }
Andy Fleming00db8182005-07-30 19:31:23 -0400367}
Domen Puncer680e9fe2007-09-17 22:21:40 +0200368EXPORT_SYMBOL(phy_mii_ioctl);
Andy Fleming00db8182005-07-30 19:31:23 -0400369
Randy Dunlapb3df0da2007-03-06 02:41:48 -0800370/**
371 * phy_start_aneg - start auto-negotiation for this PHY device
372 * @phydev: the phy_device struct
Andy Fleminge1393452005-08-24 18:46:21 -0500373 *
Randy Dunlapb3df0da2007-03-06 02:41:48 -0800374 * Description: Sanitizes the settings (if we're not autonegotiating
375 * them), and then calls the driver's config_aneg function.
376 * If the PHYCONTROL Layer is operating, we change the state to
377 * reflect the beginning of Auto-negotiation or forcing.
Andy Fleminge1393452005-08-24 18:46:21 -0500378 */
379int phy_start_aneg(struct phy_device *phydev)
380{
381 int err;
382
Nate Case35b5f6b2008-01-29 10:05:09 -0600383 mutex_lock(&phydev->lock);
Andy Fleminge1393452005-08-24 18:46:21 -0500384
385 if (AUTONEG_DISABLE == phydev->autoneg)
386 phy_sanitize_settings(phydev);
387
388 err = phydev->drv->config_aneg(phydev);
389
Andy Fleminge1393452005-08-24 18:46:21 -0500390 if (err < 0)
391 goto out_unlock;
392
393 if (phydev->state != PHY_HALTED) {
394 if (AUTONEG_ENABLE == phydev->autoneg) {
395 phydev->state = PHY_AN;
396 phydev->link_timeout = PHY_AN_TIMEOUT;
397 } else {
398 phydev->state = PHY_FORCING;
399 phydev->link_timeout = PHY_FORCE_TIMEOUT;
400 }
401 }
402
403out_unlock:
Nate Case35b5f6b2008-01-29 10:05:09 -0600404 mutex_unlock(&phydev->lock);
Andy Fleminge1393452005-08-24 18:46:21 -0500405 return err;
406}
407EXPORT_SYMBOL(phy_start_aneg);
408
409
Randy Dunlapb3df0da2007-03-06 02:41:48 -0800410/**
411 * phy_start_machine - start PHY state machine tracking
412 * @phydev: the phy_device struct
413 * @handler: callback function for state change notifications
Andy Fleming00db8182005-07-30 19:31:23 -0400414 *
Randy Dunlapb3df0da2007-03-06 02:41:48 -0800415 * Description: The PHY infrastructure can run a state machine
Andy Fleming00db8182005-07-30 19:31:23 -0400416 * which tracks whether the PHY is starting up, negotiating,
417 * etc. This function starts the timer which tracks the state
Randy Dunlapb3df0da2007-03-06 02:41:48 -0800418 * of the PHY. If you want to be notified when the state changes,
419 * pass in the callback @handler, otherwise, pass NULL. If you
Andy Fleming00db8182005-07-30 19:31:23 -0400420 * want to maintain your own state machine, do not call this
Randy Dunlapb3df0da2007-03-06 02:41:48 -0800421 * function.
422 */
Andy Fleming00db8182005-07-30 19:31:23 -0400423void phy_start_machine(struct phy_device *phydev,
Sergei Shtylyov2f53e902014-01-05 03:17:06 +0300424 void (*handler)(struct net_device *))
Andy Fleming00db8182005-07-30 19:31:23 -0400425{
426 phydev->adjust_state = handler;
427
Viresh Kumarbbb47bd2013-04-24 17:12:55 +0530428 queue_delayed_work(system_power_efficient_wq, &phydev->state_queue, HZ);
Andy Fleming00db8182005-07-30 19:31:23 -0400429}
430
Randy Dunlapb3df0da2007-03-06 02:41:48 -0800431/**
432 * phy_stop_machine - stop the PHY state machine tracking
433 * @phydev: target phy_device struct
Andy Fleming00db8182005-07-30 19:31:23 -0400434 *
Randy Dunlapb3df0da2007-03-06 02:41:48 -0800435 * Description: Stops the state machine timer, sets the state to UP
Sergei Shtylylov817acf52006-07-26 00:53:53 +0400436 * (unless it wasn't up yet). This function must be called BEFORE
Andy Fleming00db8182005-07-30 19:31:23 -0400437 * phy_detach.
438 */
439void phy_stop_machine(struct phy_device *phydev)
440{
Marcin Slusarza390d1f2009-03-13 15:41:19 -0700441 cancel_delayed_work_sync(&phydev->state_queue);
Andy Fleming00db8182005-07-30 19:31:23 -0400442
Nate Case35b5f6b2008-01-29 10:05:09 -0600443 mutex_lock(&phydev->lock);
Andy Fleming00db8182005-07-30 19:31:23 -0400444 if (phydev->state > PHY_UP)
445 phydev->state = PHY_UP;
Nate Case35b5f6b2008-01-29 10:05:09 -0600446 mutex_unlock(&phydev->lock);
Andy Fleming00db8182005-07-30 19:31:23 -0400447
Andy Fleming00db8182005-07-30 19:31:23 -0400448 phydev->adjust_state = NULL;
449}
450
Randy Dunlapb3df0da2007-03-06 02:41:48 -0800451/**
Randy Dunlapb3df0da2007-03-06 02:41:48 -0800452 * phy_error - enter HALTED state for this PHY device
453 * @phydev: target phy_device struct
Andy Fleming00db8182005-07-30 19:31:23 -0400454 *
455 * Moves the PHY to the HALTED state in response to a read
456 * or write error, and tells the controller the link is down.
457 * Must not be called from interrupt context, or while the
458 * phydev->lock is held.
459 */
Andy Fleming9b9a8bf2008-05-02 13:00:51 -0500460static void phy_error(struct phy_device *phydev)
Andy Fleming00db8182005-07-30 19:31:23 -0400461{
Nate Case35b5f6b2008-01-29 10:05:09 -0600462 mutex_lock(&phydev->lock);
Andy Fleming00db8182005-07-30 19:31:23 -0400463 phydev->state = PHY_HALTED;
Nate Case35b5f6b2008-01-29 10:05:09 -0600464 mutex_unlock(&phydev->lock);
Andy Fleming00db8182005-07-30 19:31:23 -0400465}
466
Randy Dunlapb3df0da2007-03-06 02:41:48 -0800467/**
468 * phy_interrupt - PHY interrupt handler
469 * @irq: interrupt line
470 * @phy_dat: phy_device pointer
Andy Fleminge1393452005-08-24 18:46:21 -0500471 *
Randy Dunlapb3df0da2007-03-06 02:41:48 -0800472 * Description: When a PHY interrupt occurs, the handler disables
Andy Fleminge1393452005-08-24 18:46:21 -0500473 * interrupts, and schedules a work task to clear the interrupt.
474 */
David Howells7d12e782006-10-05 14:55:46 +0100475static irqreturn_t phy_interrupt(int irq, void *phy_dat)
Andy Fleminge1393452005-08-24 18:46:21 -0500476{
477 struct phy_device *phydev = phy_dat;
478
Maciej W. Rozycki3c3070d2006-10-03 16:18:35 +0100479 if (PHY_HALTED == phydev->state)
480 return IRQ_NONE; /* It can't be ours. */
481
Andy Fleminge1393452005-08-24 18:46:21 -0500482 /* The MDIO bus is not allowed to be written in interrupt
483 * context, so we need to disable the irq here. A work
484 * queue will write the PHY to disable and clear the
Sergei Shtylyov2f53e902014-01-05 03:17:06 +0300485 * interrupt, and then reenable the irq line.
486 */
Andy Fleminge1393452005-08-24 18:46:21 -0500487 disable_irq_nosync(irq);
Maciej W. Rozycki0ac49522007-09-28 22:42:14 -0700488 atomic_inc(&phydev->irq_disable);
Andy Fleminge1393452005-08-24 18:46:21 -0500489
Viresh Kumarbbb47bd2013-04-24 17:12:55 +0530490 queue_work(system_power_efficient_wq, &phydev->phy_queue);
Andy Fleminge1393452005-08-24 18:46:21 -0500491
492 return IRQ_HANDLED;
493}
494
Randy Dunlapb3df0da2007-03-06 02:41:48 -0800495/**
496 * phy_enable_interrupts - Enable the interrupts from the PHY side
497 * @phydev: target phy_device struct
498 */
stephen hemminger89ff05e2010-10-21 08:37:41 +0000499static int phy_enable_interrupts(struct phy_device *phydev)
Andy Fleming00db8182005-07-30 19:31:23 -0400500{
501 int err;
502
Andy Fleminge1393452005-08-24 18:46:21 -0500503 err = phy_clear_interrupt(phydev);
Andy Fleming00db8182005-07-30 19:31:23 -0400504
Andy Fleminge1393452005-08-24 18:46:21 -0500505 if (err < 0)
506 return err;
Andy Fleming00db8182005-07-30 19:31:23 -0400507
Andy Fleminge1393452005-08-24 18:46:21 -0500508 err = phy_config_interrupt(phydev, PHY_INTERRUPT_ENABLED);
Andy Fleming00db8182005-07-30 19:31:23 -0400509
510 return err;
511}
Andy Fleming00db8182005-07-30 19:31:23 -0400512
Randy Dunlapb3df0da2007-03-06 02:41:48 -0800513/**
514 * phy_disable_interrupts - Disable the PHY interrupts from the PHY side
515 * @phydev: target phy_device struct
516 */
stephen hemminger89ff05e2010-10-21 08:37:41 +0000517static int phy_disable_interrupts(struct phy_device *phydev)
Andy Fleming00db8182005-07-30 19:31:23 -0400518{
519 int err;
520
521 /* Disable PHY interrupts */
522 err = phy_config_interrupt(phydev, PHY_INTERRUPT_DISABLED);
523
524 if (err)
525 goto phy_err;
526
527 /* Clear the interrupt */
528 err = phy_clear_interrupt(phydev);
529
530 if (err)
531 goto phy_err;
532
533 return 0;
534
535phy_err:
536 phy_error(phydev);
537
538 return err;
539}
Andy Fleminge1393452005-08-24 18:46:21 -0500540
Randy Dunlapb3df0da2007-03-06 02:41:48 -0800541/**
542 * phy_start_interrupts - request and enable interrupts for a PHY device
543 * @phydev: target phy_device struct
Andy Fleminge1393452005-08-24 18:46:21 -0500544 *
Randy Dunlapb3df0da2007-03-06 02:41:48 -0800545 * Description: Request the interrupt for the given PHY.
546 * If this fails, then we set irq to PHY_POLL.
Andy Fleminge1393452005-08-24 18:46:21 -0500547 * Otherwise, we enable the interrupts in the PHY.
Andy Fleminge1393452005-08-24 18:46:21 -0500548 * This should only be called with a valid IRQ number.
Randy Dunlapb3df0da2007-03-06 02:41:48 -0800549 * Returns 0 on success or < 0 on error.
Andy Fleminge1393452005-08-24 18:46:21 -0500550 */
551int phy_start_interrupts(struct phy_device *phydev)
552{
Maciej W. Rozycki0ac49522007-09-28 22:42:14 -0700553 atomic_set(&phydev->irq_disable, 0);
Andy Fleminge1393452005-08-24 18:46:21 -0500554 if (request_irq(phydev->irq, phy_interrupt,
Thomas Gleixner1fb9df52006-07-01 19:29:39 -0700555 IRQF_SHARED,
Andy Fleminge1393452005-08-24 18:46:21 -0500556 "phy_interrupt",
557 phydev) < 0) {
Joe Perches8d242482012-06-09 07:49:07 +0000558 pr_warn("%s: Can't get IRQ %d (PHY)\n",
559 phydev->bus->name, phydev->irq);
Andy Fleminge1393452005-08-24 18:46:21 -0500560 phydev->irq = PHY_POLL;
561 return 0;
562 }
563
Sergei Shtylyove62a7682014-01-05 03:21:52 +0300564 return phy_enable_interrupts(phydev);
Andy Fleminge1393452005-08-24 18:46:21 -0500565}
566EXPORT_SYMBOL(phy_start_interrupts);
567
Randy Dunlapb3df0da2007-03-06 02:41:48 -0800568/**
569 * phy_stop_interrupts - disable interrupts from a PHY device
570 * @phydev: target phy_device struct
571 */
Andy Fleminge1393452005-08-24 18:46:21 -0500572int phy_stop_interrupts(struct phy_device *phydev)
573{
574 int err;
575
576 err = phy_disable_interrupts(phydev);
577
578 if (err)
579 phy_error(phydev);
580
Maciej W. Rozycki0ac49522007-09-28 22:42:14 -0700581 free_irq(phydev->irq, phydev);
582
Sergei Shtylyov2f53e902014-01-05 03:17:06 +0300583 /* Cannot call flush_scheduled_work() here as desired because
Maciej W. Rozycki0ac49522007-09-28 22:42:14 -0700584 * of rtnl_lock(), but we do not really care about what would
585 * be done, except from enable_irq(), so cancel any work
586 * possibly pending and take care of the matter below.
Maciej W. Rozycki3c3070d2006-10-03 16:18:35 +0100587 */
Oleg Nesterov28e53bd2007-05-09 02:34:22 -0700588 cancel_work_sync(&phydev->phy_queue);
Sergei Shtylyov2f53e902014-01-05 03:17:06 +0300589 /* If work indeed has been cancelled, disable_irq() will have
Maciej W. Rozycki0ac49522007-09-28 22:42:14 -0700590 * been left unbalanced from phy_interrupt() and enable_irq()
591 * has to be called so that other devices on the line work.
592 */
593 while (atomic_dec_return(&phydev->irq_disable) >= 0)
594 enable_irq(phydev->irq);
Andy Fleminge1393452005-08-24 18:46:21 -0500595
596 return err;
597}
598EXPORT_SYMBOL(phy_stop_interrupts);
599
600
Randy Dunlapb3df0da2007-03-06 02:41:48 -0800601/**
602 * phy_change - Scheduled by the phy_interrupt/timer to handle PHY changes
603 * @work: work_struct that describes the work to be done
604 */
Florian Fainelli5ea94e72013-05-19 22:53:43 +0000605void phy_change(struct work_struct *work)
Andy Fleminge1393452005-08-24 18:46:21 -0500606{
David Howellsc4028952006-11-22 14:57:56 +0000607 struct phy_device *phydev =
608 container_of(work, struct phy_device, phy_queue);
Andy Fleminge1393452005-08-24 18:46:21 -0500609
Anatolij Gustschina8729eb2009-04-07 02:01:42 +0000610 if (phydev->drv->did_interrupt &&
611 !phydev->drv->did_interrupt(phydev))
612 goto ignore;
613
Sergei Shtylyove62a7682014-01-05 03:21:52 +0300614 if (phy_disable_interrupts(phydev))
Andy Fleminge1393452005-08-24 18:46:21 -0500615 goto phy_err;
616
Nate Case35b5f6b2008-01-29 10:05:09 -0600617 mutex_lock(&phydev->lock);
Andy Fleminge1393452005-08-24 18:46:21 -0500618 if ((PHY_RUNNING == phydev->state) || (PHY_NOLINK == phydev->state))
619 phydev->state = PHY_CHANGELINK;
Nate Case35b5f6b2008-01-29 10:05:09 -0600620 mutex_unlock(&phydev->lock);
Andy Fleminge1393452005-08-24 18:46:21 -0500621
Maciej W. Rozycki0ac49522007-09-28 22:42:14 -0700622 atomic_dec(&phydev->irq_disable);
Andy Fleminge1393452005-08-24 18:46:21 -0500623 enable_irq(phydev->irq);
624
625 /* Reenable interrupts */
Sergei Shtylyove62a7682014-01-05 03:21:52 +0300626 if (PHY_HALTED != phydev->state &&
627 phy_config_interrupt(phydev, PHY_INTERRUPT_ENABLED))
Andy Fleminge1393452005-08-24 18:46:21 -0500628 goto irq_enable_err;
629
Marcin Slusarza390d1f2009-03-13 15:41:19 -0700630 /* reschedule state queue work to run as soon as possible */
631 cancel_delayed_work_sync(&phydev->state_queue);
Viresh Kumarbbb47bd2013-04-24 17:12:55 +0530632 queue_delayed_work(system_power_efficient_wq, &phydev->state_queue, 0);
Trent Piepho0acb2832008-10-08 15:46:57 -0700633
Andy Fleminge1393452005-08-24 18:46:21 -0500634 return;
635
Anatolij Gustschina8729eb2009-04-07 02:01:42 +0000636ignore:
637 atomic_dec(&phydev->irq_disable);
638 enable_irq(phydev->irq);
639 return;
640
Andy Fleminge1393452005-08-24 18:46:21 -0500641irq_enable_err:
642 disable_irq(phydev->irq);
Maciej W. Rozycki0ac49522007-09-28 22:42:14 -0700643 atomic_inc(&phydev->irq_disable);
Andy Fleminge1393452005-08-24 18:46:21 -0500644phy_err:
645 phy_error(phydev);
646}
647
Randy Dunlapb3df0da2007-03-06 02:41:48 -0800648/**
649 * phy_stop - Bring down the PHY link, and stop checking the status
650 * @phydev: target phy_device struct
651 */
Andy Fleminge1393452005-08-24 18:46:21 -0500652void phy_stop(struct phy_device *phydev)
653{
Nate Case35b5f6b2008-01-29 10:05:09 -0600654 mutex_lock(&phydev->lock);
Andy Fleminge1393452005-08-24 18:46:21 -0500655
656 if (PHY_HALTED == phydev->state)
657 goto out_unlock;
658
Florian Fainelli2c7b4922013-05-19 22:53:42 +0000659 if (phy_interrupt_is_valid(phydev)) {
Andy Fleminge1393452005-08-24 18:46:21 -0500660 /* Disable PHY Interrupts */
661 phy_config_interrupt(phydev, PHY_INTERRUPT_DISABLED);
Andy Fleminge1393452005-08-24 18:46:21 -0500662
Maciej W. Rozycki3c3070d2006-10-03 16:18:35 +0100663 /* Clear any pending interrupts */
664 phy_clear_interrupt(phydev);
665 }
Andy Fleminge1393452005-08-24 18:46:21 -0500666
Maciej W. Rozycki6daf6532007-09-28 22:42:15 -0700667 phydev->state = PHY_HALTED;
668
Andy Fleminge1393452005-08-24 18:46:21 -0500669out_unlock:
Nate Case35b5f6b2008-01-29 10:05:09 -0600670 mutex_unlock(&phydev->lock);
Maciej W. Rozycki3c3070d2006-10-03 16:18:35 +0100671
Sergei Shtylyov2f53e902014-01-05 03:17:06 +0300672 /* Cannot call flush_scheduled_work() here as desired because
Maciej W. Rozycki3c3070d2006-10-03 16:18:35 +0100673 * of rtnl_lock(), but PHY_HALTED shall guarantee phy_change()
674 * will not reenable interrupts.
675 */
Andy Fleminge1393452005-08-24 18:46:21 -0500676}
Sergei Shtylyov2f53e902014-01-05 03:17:06 +0300677EXPORT_SYMBOL(phy_stop);
Andy Fleminge1393452005-08-24 18:46:21 -0500678
679
Randy Dunlapb3df0da2007-03-06 02:41:48 -0800680/**
681 * phy_start - start or restart a PHY device
682 * @phydev: target phy_device struct
Andy Fleminge1393452005-08-24 18:46:21 -0500683 *
Randy Dunlapb3df0da2007-03-06 02:41:48 -0800684 * Description: Indicates the attached device's readiness to
Andy Fleminge1393452005-08-24 18:46:21 -0500685 * handle PHY-related work. Used during startup to start the
686 * PHY, and after a call to phy_stop() to resume operation.
687 * Also used to indicate the MDIO bus has cleared an error
688 * condition.
689 */
690void phy_start(struct phy_device *phydev)
691{
Nate Case35b5f6b2008-01-29 10:05:09 -0600692 mutex_lock(&phydev->lock);
Andy Fleminge1393452005-08-24 18:46:21 -0500693
694 switch (phydev->state) {
Florian Fainellie1093742013-12-17 21:38:12 -0800695 case PHY_STARTING:
696 phydev->state = PHY_PENDING;
697 break;
698 case PHY_READY:
699 phydev->state = PHY_UP;
700 break;
701 case PHY_HALTED:
702 phydev->state = PHY_RESUMING;
703 default:
704 break;
Andy Fleminge1393452005-08-24 18:46:21 -0500705 }
Nate Case35b5f6b2008-01-29 10:05:09 -0600706 mutex_unlock(&phydev->lock);
Andy Fleminge1393452005-08-24 18:46:21 -0500707}
Andy Fleminge1393452005-08-24 18:46:21 -0500708EXPORT_SYMBOL(phy_start);
Jeff Garzik67c4f3f2005-08-11 02:07:25 -0400709
Nate Case35b5f6b2008-01-29 10:05:09 -0600710/**
711 * phy_state_machine - Handle the state machine
712 * @work: work_struct that describes the work to be done
Nate Case35b5f6b2008-01-29 10:05:09 -0600713 */
Anton Vorontsov4f9c85a2010-01-18 05:37:16 +0000714void phy_state_machine(struct work_struct *work)
Andy Fleming00db8182005-07-30 19:31:23 -0400715{
Jean Delvarebf6aede2009-04-02 16:56:54 -0700716 struct delayed_work *dwork = to_delayed_work(work);
Nate Case35b5f6b2008-01-29 10:05:09 -0600717 struct phy_device *phydev =
Marcin Slusarza390d1f2009-03-13 15:41:19 -0700718 container_of(dwork, struct phy_device, state_queue);
Sebastian Hesselbarthbe9dad12013-12-13 10:20:29 +0100719 int needs_aneg = 0, do_suspend = 0;
Andy Fleming00db8182005-07-30 19:31:23 -0400720 int err = 0;
721
Nate Case35b5f6b2008-01-29 10:05:09 -0600722 mutex_lock(&phydev->lock);
Andy Fleming00db8182005-07-30 19:31:23 -0400723
724 if (phydev->adjust_state)
725 phydev->adjust_state(phydev->attached_dev);
726
Florian Fainellie1093742013-12-17 21:38:12 -0800727 switch (phydev->state) {
728 case PHY_DOWN:
729 case PHY_STARTING:
730 case PHY_READY:
731 case PHY_PENDING:
732 break;
733 case PHY_UP:
734 needs_aneg = 1;
735
736 phydev->link_timeout = PHY_AN_TIMEOUT;
737
738 break;
739 case PHY_AN:
740 err = phy_read_status(phydev);
741
742 if (err < 0)
Andy Fleming00db8182005-07-30 19:31:23 -0400743 break;
Florian Fainellie1093742013-12-17 21:38:12 -0800744
Sergei Shtylyov2f53e902014-01-05 03:17:06 +0300745 /* If the link is down, give up on negotiation for now */
Florian Fainellie1093742013-12-17 21:38:12 -0800746 if (!phydev->link) {
747 phydev->state = PHY_NOLINK;
748 netif_carrier_off(phydev->attached_dev);
749 phydev->adjust_link(phydev->attached_dev);
750 break;
751 }
752
Sergei Shtylyov2f53e902014-01-05 03:17:06 +0300753 /* Check if negotiation is done. Break if there's an error */
Florian Fainellie1093742013-12-17 21:38:12 -0800754 err = phy_aneg_done(phydev);
755 if (err < 0)
756 break;
757
758 /* If AN is done, we're running */
759 if (err > 0) {
760 phydev->state = PHY_RUNNING;
761 netif_carrier_on(phydev->attached_dev);
762 phydev->adjust_link(phydev->attached_dev);
763
764 } else if (0 == phydev->link_timeout--) {
Andy Fleming00db8182005-07-30 19:31:23 -0400765 needs_aneg = 1;
Sergei Shtylyov2f53e902014-01-05 03:17:06 +0300766 /* If we have the magic_aneg bit, we try again */
Florian Fainellie1093742013-12-17 21:38:12 -0800767 if (phydev->drv->flags & PHY_HAS_MAGICANEG)
768 break;
769 }
770 break;
771 case PHY_NOLINK:
772 err = phy_read_status(phydev);
Andy Fleming00db8182005-07-30 19:31:23 -0400773
Florian Fainellie1093742013-12-17 21:38:12 -0800774 if (err)
Andy Fleming00db8182005-07-30 19:31:23 -0400775 break;
Andy Fleming6b655522006-10-16 16:19:17 -0500776
Florian Fainellie1093742013-12-17 21:38:12 -0800777 if (phydev->link) {
778 phydev->state = PHY_RUNNING;
779 netif_carrier_on(phydev->attached_dev);
780 phydev->adjust_link(phydev->attached_dev);
781 }
782 break;
783 case PHY_FORCING:
784 err = genphy_update_link(phydev);
Andy Fleming6b655522006-10-16 16:19:17 -0500785
Florian Fainellie1093742013-12-17 21:38:12 -0800786 if (err)
787 break;
Andy Fleming6b655522006-10-16 16:19:17 -0500788
Florian Fainellie1093742013-12-17 21:38:12 -0800789 if (phydev->link) {
790 phydev->state = PHY_RUNNING;
791 netif_carrier_on(phydev->attached_dev);
792 } else {
793 if (0 == phydev->link_timeout--)
794 needs_aneg = 1;
795 }
796
797 phydev->adjust_link(phydev->attached_dev);
798 break;
799 case PHY_RUNNING:
800 /* Only register a CHANGE if we are
801 * polling or ignoring interrupts
802 */
803 if (!phy_interrupt_is_valid(phydev))
804 phydev->state = PHY_CHANGELINK;
805 break;
806 case PHY_CHANGELINK:
807 err = phy_read_status(phydev);
808
809 if (err)
810 break;
811
812 if (phydev->link) {
813 phydev->state = PHY_RUNNING;
814 netif_carrier_on(phydev->attached_dev);
815 } else {
816 phydev->state = PHY_NOLINK;
817 netif_carrier_off(phydev->attached_dev);
818 }
819
820 phydev->adjust_link(phydev->attached_dev);
821
822 if (phy_interrupt_is_valid(phydev))
823 err = phy_config_interrupt(phydev,
Sergei Shtylyov2f53e902014-01-05 03:17:06 +0300824 PHY_INTERRUPT_ENABLED);
Florian Fainellie1093742013-12-17 21:38:12 -0800825 break;
826 case PHY_HALTED:
827 if (phydev->link) {
828 phydev->link = 0;
829 netif_carrier_off(phydev->attached_dev);
830 phydev->adjust_link(phydev->attached_dev);
831 do_suspend = 1;
832 }
833 break;
834 case PHY_RESUMING:
835
836 err = phy_clear_interrupt(phydev);
837
838 if (err)
839 break;
840
Sergei Shtylyov2f53e902014-01-05 03:17:06 +0300841 err = phy_config_interrupt(phydev, PHY_INTERRUPT_ENABLED);
Florian Fainellie1093742013-12-17 21:38:12 -0800842
843 if (err)
844 break;
845
846 if (AUTONEG_ENABLE == phydev->autoneg) {
Andy Fleming00db8182005-07-30 19:31:23 -0400847 err = phy_aneg_done(phydev);
848 if (err < 0)
849 break;
850
Florian Fainellie1093742013-12-17 21:38:12 -0800851 /* err > 0 if AN is done.
Sergei Shtylyov2f53e902014-01-05 03:17:06 +0300852 * Otherwise, it's 0, and we're still waiting for AN
853 */
Andy Fleming00db8182005-07-30 19:31:23 -0400854 if (err > 0) {
Wade Farnsworth42caa072009-07-01 13:00:34 +0000855 err = phy_read_status(phydev);
856 if (err)
857 break;
858
859 if (phydev->link) {
860 phydev->state = PHY_RUNNING;
861 netif_carrier_on(phydev->attached_dev);
Sergei Shtylyov2f53e902014-01-05 03:17:06 +0300862 } else {
Wade Farnsworth42caa072009-07-01 13:00:34 +0000863 phydev->state = PHY_NOLINK;
Sergei Shtylyov2f53e902014-01-05 03:17:06 +0300864 }
Wade Farnsworth42caa072009-07-01 13:00:34 +0000865 phydev->adjust_link(phydev->attached_dev);
Florian Fainellie1093742013-12-17 21:38:12 -0800866 } else {
867 phydev->state = PHY_AN;
868 phydev->link_timeout = PHY_AN_TIMEOUT;
Wade Farnsworth42caa072009-07-01 13:00:34 +0000869 }
Florian Fainellie1093742013-12-17 21:38:12 -0800870 } else {
871 err = phy_read_status(phydev);
872 if (err)
873 break;
874
875 if (phydev->link) {
876 phydev->state = PHY_RUNNING;
877 netif_carrier_on(phydev->attached_dev);
Sergei Shtylyov2f53e902014-01-05 03:17:06 +0300878 } else {
Florian Fainellie1093742013-12-17 21:38:12 -0800879 phydev->state = PHY_NOLINK;
Sergei Shtylyov2f53e902014-01-05 03:17:06 +0300880 }
Florian Fainellie1093742013-12-17 21:38:12 -0800881 phydev->adjust_link(phydev->attached_dev);
882 }
883 break;
Andy Fleming00db8182005-07-30 19:31:23 -0400884 }
885
Nate Case35b5f6b2008-01-29 10:05:09 -0600886 mutex_unlock(&phydev->lock);
Andy Fleming00db8182005-07-30 19:31:23 -0400887
888 if (needs_aneg)
889 err = phy_start_aneg(phydev);
890
Sebastian Hesselbarthbe9dad12013-12-13 10:20:29 +0100891 if (do_suspend)
892 phy_suspend(phydev);
893
Andy Fleming00db8182005-07-30 19:31:23 -0400894 if (err < 0)
895 phy_error(phydev);
896
Viresh Kumarbbb47bd2013-04-24 17:12:55 +0530897 queue_delayed_work(system_power_efficient_wq, &phydev->state_queue,
Sergei Shtylyov2f53e902014-01-05 03:17:06 +0300898 PHY_STATE_TIME * HZ);
Nate Case35b5f6b2008-01-29 10:05:09 -0600899}
Giuseppe CAVALLAROa59a4d12012-06-27 21:14:38 +0000900
Florian Fainelli5ea94e72013-05-19 22:53:43 +0000901void phy_mac_interrupt(struct phy_device *phydev, int new_link)
902{
903 cancel_work_sync(&phydev->phy_queue);
904 phydev->link = new_link;
905 schedule_work(&phydev->phy_queue);
906}
907EXPORT_SYMBOL(phy_mac_interrupt);
908
Giuseppe CAVALLAROa59a4d12012-06-27 21:14:38 +0000909static inline void mmd_phy_indirect(struct mii_bus *bus, int prtad, int devad,
910 int addr)
911{
912 /* Write the desired MMD Devad */
913 bus->write(bus, addr, MII_MMD_CTRL, devad);
914
915 /* Write the desired MMD register address */
916 bus->write(bus, addr, MII_MMD_DATA, prtad);
917
918 /* Select the Function : DATA with no post increment */
919 bus->write(bus, addr, MII_MMD_CTRL, (devad | MII_MMD_CTRL_NOINCR));
920}
921
922/**
923 * phy_read_mmd_indirect - reads data from the MMD registers
924 * @bus: the target MII bus
925 * @prtad: MMD Address
926 * @devad: MMD DEVAD
927 * @addr: PHY address on the MII bus
928 *
929 * Description: it reads data from the MMD registers (clause 22 to access to
930 * clause 45) of the specified phy address.
931 * To read these register we have:
932 * 1) Write reg 13 // DEVAD
933 * 2) Write reg 14 // MMD Address
934 * 3) Write reg 13 // MMD Data Command for MMD DEVAD
935 * 3) Read reg 14 // Read MMD data
936 */
937static int phy_read_mmd_indirect(struct mii_bus *bus, int prtad, int devad,
938 int addr)
939{
Giuseppe CAVALLAROa59a4d12012-06-27 21:14:38 +0000940 mmd_phy_indirect(bus, prtad, devad, addr);
941
942 /* Read the content of the MMD's selected register */
Sergei Shtylyove62a7682014-01-05 03:21:52 +0300943 return bus->read(bus, addr, MII_MMD_DATA);
Giuseppe CAVALLAROa59a4d12012-06-27 21:14:38 +0000944}
945
946/**
947 * phy_write_mmd_indirect - writes data to the MMD registers
948 * @bus: the target MII bus
949 * @prtad: MMD Address
950 * @devad: MMD DEVAD
951 * @addr: PHY address on the MII bus
952 * @data: data to write in the MMD register
953 *
954 * Description: Write data from the MMD registers of the specified
955 * phy address.
956 * To write these register we have:
957 * 1) Write reg 13 // DEVAD
958 * 2) Write reg 14 // MMD Address
959 * 3) Write reg 13 // MMD Data Command for MMD DEVAD
960 * 3) Write reg 14 // Write MMD data
961 */
962static void phy_write_mmd_indirect(struct mii_bus *bus, int prtad, int devad,
963 int addr, u32 data)
964{
965 mmd_phy_indirect(bus, prtad, devad, addr);
966
967 /* Write the data into MMD's selected register */
968 bus->write(bus, addr, MII_MMD_DATA, data);
969}
970
Giuseppe CAVALLAROa59a4d12012-06-27 21:14:38 +0000971/**
972 * phy_init_eee - init and check the EEE feature
973 * @phydev: target phy_device struct
974 * @clk_stop_enable: PHY may stop the clock during LPI
975 *
976 * Description: it checks if the Energy-Efficient Ethernet (EEE)
977 * is supported by looking at the MMD registers 3.20 and 7.60/61
978 * and it programs the MMD register 3.0 setting the "Clock stop enable"
979 * bit if required.
980 */
981int phy_init_eee(struct phy_device *phydev, bool clk_stop_enable)
982{
Giuseppe CAVALLAROa59a4d12012-06-27 21:14:38 +0000983 /* According to 802.3az,the EEE is supported only in full duplex-mode.
984 * Also EEE feature is active when core is operating with MII, GMII
985 * or RGMII.
986 */
987 if ((phydev->duplex == DUPLEX_FULL) &&
988 ((phydev->interface == PHY_INTERFACE_MODE_MII) ||
989 (phydev->interface == PHY_INTERFACE_MODE_GMII) ||
990 (phydev->interface == PHY_INTERFACE_MODE_RGMII))) {
991 int eee_lp, eee_cap, eee_adv;
992 u32 lp, cap, adv;
993 int idx, status;
994
995 /* Read phy status to properly get the right settings */
996 status = phy_read_status(phydev);
997 if (status)
998 return status;
999
1000 /* First check if the EEE ability is supported */
1001 eee_cap = phy_read_mmd_indirect(phydev->bus, MDIO_PCS_EEE_ABLE,
1002 MDIO_MMD_PCS, phydev->addr);
1003 if (eee_cap < 0)
1004 return eee_cap;
1005
Allan, Bruce Wb32607d2012-08-20 04:55:29 +00001006 cap = mmd_eee_cap_to_ethtool_sup_t(eee_cap);
Giuseppe CAVALLAROa59a4d12012-06-27 21:14:38 +00001007 if (!cap)
Sergei Shtylyove62a7682014-01-05 03:21:52 +03001008 return -EPROTONOSUPPORT;
Giuseppe CAVALLAROa59a4d12012-06-27 21:14:38 +00001009
1010 /* Check which link settings negotiated and verify it in
1011 * the EEE advertising registers.
1012 */
1013 eee_lp = phy_read_mmd_indirect(phydev->bus, MDIO_AN_EEE_LPABLE,
1014 MDIO_MMD_AN, phydev->addr);
1015 if (eee_lp < 0)
1016 return eee_lp;
1017
1018 eee_adv = phy_read_mmd_indirect(phydev->bus, MDIO_AN_EEE_ADV,
1019 MDIO_MMD_AN, phydev->addr);
1020 if (eee_adv < 0)
1021 return eee_adv;
1022
Allan, Bruce Wb32607d2012-08-20 04:55:29 +00001023 adv = mmd_eee_adv_to_ethtool_adv_t(eee_adv);
1024 lp = mmd_eee_adv_to_ethtool_adv_t(eee_lp);
Giuseppe CAVALLAROa59a4d12012-06-27 21:14:38 +00001025 idx = phy_find_setting(phydev->speed, phydev->duplex);
Giuseppe CAVALLARO9a9c56c2013-05-26 21:31:28 +00001026 if (!(lp & adv & settings[idx].setting))
Sergei Shtylyove62a7682014-01-05 03:21:52 +03001027 return -EPROTONOSUPPORT;
Giuseppe CAVALLAROa59a4d12012-06-27 21:14:38 +00001028
1029 if (clk_stop_enable) {
1030 /* Configure the PHY to stop receiving xMII
1031 * clock while it is signaling LPI.
1032 */
1033 int val = phy_read_mmd_indirect(phydev->bus, MDIO_CTRL1,
1034 MDIO_MMD_PCS,
1035 phydev->addr);
1036 if (val < 0)
1037 return val;
1038
1039 val |= MDIO_PCS_CTRL1_CLKSTOP_EN;
1040 phy_write_mmd_indirect(phydev->bus, MDIO_CTRL1,
1041 MDIO_MMD_PCS, phydev->addr, val);
1042 }
1043
Sergei Shtylyove62a7682014-01-05 03:21:52 +03001044 return 0; /* EEE supported */
Giuseppe CAVALLAROa59a4d12012-06-27 21:14:38 +00001045 }
1046
Sergei Shtylyove62a7682014-01-05 03:21:52 +03001047 return -EPROTONOSUPPORT;
Giuseppe CAVALLAROa59a4d12012-06-27 21:14:38 +00001048}
1049EXPORT_SYMBOL(phy_init_eee);
1050
1051/**
1052 * phy_get_eee_err - report the EEE wake error count
1053 * @phydev: target phy_device struct
1054 *
1055 * Description: it is to report the number of time where the PHY
1056 * failed to complete its normal wake sequence.
1057 */
1058int phy_get_eee_err(struct phy_device *phydev)
1059{
1060 return phy_read_mmd_indirect(phydev->bus, MDIO_PCS_EEE_WK_ERR,
1061 MDIO_MMD_PCS, phydev->addr);
Giuseppe CAVALLAROa59a4d12012-06-27 21:14:38 +00001062}
1063EXPORT_SYMBOL(phy_get_eee_err);
1064
1065/**
1066 * phy_ethtool_get_eee - get EEE supported and status
1067 * @phydev: target phy_device struct
1068 * @data: ethtool_eee data
1069 *
1070 * Description: it reportes the Supported/Advertisement/LP Advertisement
1071 * capabilities.
1072 */
1073int phy_ethtool_get_eee(struct phy_device *phydev, struct ethtool_eee *data)
1074{
1075 int val;
1076
1077 /* Get Supported EEE */
1078 val = phy_read_mmd_indirect(phydev->bus, MDIO_PCS_EEE_ABLE,
1079 MDIO_MMD_PCS, phydev->addr);
1080 if (val < 0)
1081 return val;
Allan, Bruce Wb32607d2012-08-20 04:55:29 +00001082 data->supported = mmd_eee_cap_to_ethtool_sup_t(val);
Giuseppe CAVALLAROa59a4d12012-06-27 21:14:38 +00001083
1084 /* Get advertisement EEE */
1085 val = phy_read_mmd_indirect(phydev->bus, MDIO_AN_EEE_ADV,
1086 MDIO_MMD_AN, phydev->addr);
1087 if (val < 0)
1088 return val;
Allan, Bruce Wb32607d2012-08-20 04:55:29 +00001089 data->advertised = mmd_eee_adv_to_ethtool_adv_t(val);
Giuseppe CAVALLAROa59a4d12012-06-27 21:14:38 +00001090
1091 /* Get LP advertisement EEE */
1092 val = phy_read_mmd_indirect(phydev->bus, MDIO_AN_EEE_LPABLE,
1093 MDIO_MMD_AN, phydev->addr);
1094 if (val < 0)
1095 return val;
Allan, Bruce Wb32607d2012-08-20 04:55:29 +00001096 data->lp_advertised = mmd_eee_adv_to_ethtool_adv_t(val);
Giuseppe CAVALLAROa59a4d12012-06-27 21:14:38 +00001097
1098 return 0;
1099}
1100EXPORT_SYMBOL(phy_ethtool_get_eee);
1101
1102/**
1103 * phy_ethtool_set_eee - set EEE supported and status
1104 * @phydev: target phy_device struct
1105 * @data: ethtool_eee data
1106 *
1107 * Description: it is to program the Advertisement EEE register.
1108 */
1109int phy_ethtool_set_eee(struct phy_device *phydev, struct ethtool_eee *data)
1110{
1111 int val;
1112
Allan, Bruce Wb32607d2012-08-20 04:55:29 +00001113 val = ethtool_adv_to_mmd_eee_adv_t(data->advertised);
Giuseppe CAVALLAROa59a4d12012-06-27 21:14:38 +00001114 phy_write_mmd_indirect(phydev->bus, MDIO_AN_EEE_ADV, MDIO_MMD_AN,
1115 phydev->addr, val);
1116
1117 return 0;
1118}
1119EXPORT_SYMBOL(phy_ethtool_set_eee);
Michael Stapelberg42e836e2013-03-11 13:56:44 +00001120
1121int phy_ethtool_set_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol)
1122{
1123 if (phydev->drv->set_wol)
1124 return phydev->drv->set_wol(phydev, wol);
1125
1126 return -EOPNOTSUPP;
1127}
1128EXPORT_SYMBOL(phy_ethtool_set_wol);
1129
1130void phy_ethtool_get_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol)
1131{
1132 if (phydev->drv->get_wol)
1133 phydev->drv->get_wol(phydev, wol);
1134}
1135EXPORT_SYMBOL(phy_ethtool_get_wol);