diff options
Diffstat (limited to 'include/linux/phy.h')
| -rw-r--r-- | include/linux/phy.h | 281 | 
1 files changed, 241 insertions, 40 deletions
diff --git a/include/linux/phy.h b/include/linux/phy.h index 7da5fa84595..68041446c45 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -1,6 +1,4 @@  /* - * include/linux/phy.h - *   * Framework and drivers for configuring and reading different PHYs   * Based on code in sungem_phy.c and gianfar_phy.c   * @@ -19,27 +17,35 @@  #define __PHY_H  #include <linux/spinlock.h> -#include <linux/device.h>  #include <linux/ethtool.h>  #include <linux/mii.h>  #include <linux/timer.h>  #include <linux/workqueue.h>  #include <linux/mod_devicetable.h> -#include <asm/atomic.h> +#include <linux/atomic.h> -#define PHY_BASIC_FEATURES	(SUPPORTED_10baseT_Half | \ -				 SUPPORTED_10baseT_Full | \ -				 SUPPORTED_100baseT_Half | \ -				 SUPPORTED_100baseT_Full | \ -				 SUPPORTED_Autoneg | \ +#define PHY_DEFAULT_FEATURES	(SUPPORTED_Autoneg | \  				 SUPPORTED_TP | \  				 SUPPORTED_MII) -#define PHY_GBIT_FEATURES	(PHY_BASIC_FEATURES | \ -				 SUPPORTED_1000baseT_Half | \ +#define PHY_10BT_FEATURES	(SUPPORTED_10baseT_Half | \ +				 SUPPORTED_10baseT_Full) + +#define PHY_100BT_FEATURES	(SUPPORTED_100baseT_Half | \ +				 SUPPORTED_100baseT_Full) + +#define PHY_1000BT_FEATURES	(SUPPORTED_1000baseT_Half | \  				 SUPPORTED_1000baseT_Full) +#define PHY_BASIC_FEATURES	(PHY_10BT_FEATURES | \ +				 PHY_100BT_FEATURES | \ +				 PHY_DEFAULT_FEATURES) + +#define PHY_GBIT_FEATURES	(PHY_BASIC_FEATURES | \ +				 PHY_1000BT_FEATURES) + +  /*   * Set phydev->irq to PHY_POLL if interrupts are not supported,   * or not desired for this PHY.  Set to PHY_IGNORE_INTERRUPT if @@ -50,21 +56,74 @@  #define PHY_HAS_INTERRUPT	0x00000001  #define PHY_HAS_MAGICANEG	0x00000002 +#define PHY_IS_INTERNAL		0x00000004  /* Interface Mode definitions */  typedef enum { +	PHY_INTERFACE_MODE_NA,  	PHY_INTERFACE_MODE_MII,  	PHY_INTERFACE_MODE_GMII,  	PHY_INTERFACE_MODE_SGMII,  	PHY_INTERFACE_MODE_TBI, +	PHY_INTERFACE_MODE_REVMII,  	PHY_INTERFACE_MODE_RMII,  	PHY_INTERFACE_MODE_RGMII,  	PHY_INTERFACE_MODE_RGMII_ID,  	PHY_INTERFACE_MODE_RGMII_RXID,  	PHY_INTERFACE_MODE_RGMII_TXID, -	PHY_INTERFACE_MODE_RTBI +	PHY_INTERFACE_MODE_RTBI, +	PHY_INTERFACE_MODE_SMII, +	PHY_INTERFACE_MODE_XGMII, +	PHY_INTERFACE_MODE_MOCA, +	PHY_INTERFACE_MODE_QSGMII, +	PHY_INTERFACE_MODE_MAX,  } phy_interface_t; +/** + * It maps 'enum phy_interface_t' found in include/linux/phy.h + * into the device tree binding of 'phy-mode', so that Ethernet + * device driver can get phy interface from device tree. + */ +static inline const char *phy_modes(phy_interface_t interface) +{ +	switch (interface) { +	case PHY_INTERFACE_MODE_NA: +		return ""; +	case PHY_INTERFACE_MODE_MII: +		return "mii"; +	case PHY_INTERFACE_MODE_GMII: +		return "gmii"; +	case PHY_INTERFACE_MODE_SGMII: +		return "sgmii"; +	case PHY_INTERFACE_MODE_TBI: +		return "tbi"; +	case PHY_INTERFACE_MODE_REVMII: +		return "rev-mii"; +	case PHY_INTERFACE_MODE_RMII: +		return "rmii"; +	case PHY_INTERFACE_MODE_RGMII: +		return "rgmii"; +	case PHY_INTERFACE_MODE_RGMII_ID: +		return "rgmii-id"; +	case PHY_INTERFACE_MODE_RGMII_RXID: +		return "rgmii-rxid"; +	case PHY_INTERFACE_MODE_RGMII_TXID: +		return "rgmii-txid"; +	case PHY_INTERFACE_MODE_RTBI: +		return "rtbi"; +	case PHY_INTERFACE_MODE_SMII: +		return "smii"; +	case PHY_INTERFACE_MODE_XGMII: +		return "xgmii"; +	case PHY_INTERFACE_MODE_MOCA: +		return "moca"; +	case PHY_INTERFACE_MODE_QSGMII: +		return "qsgmii"; +	default: +		return "unknown"; +	} +} +  #define PHY_INIT_TIMEOUT	100000  #define PHY_STATE_TIME		1 @@ -86,6 +145,9 @@ typedef enum {     IEEE 802.3ae clause 45 addressing mode used by 10GIGE phy chips. */  #define MII_ADDR_C45 (1<<30) +struct device; +struct sk_buff; +  /*   * The Bus class for PHYs.  Devices which provide access to   * PHYs should register using this structure @@ -127,10 +189,22 @@ struct mii_bus {  };  #define to_mii_bus(d) container_of(d, struct mii_bus, dev) -struct mii_bus *mdiobus_alloc(void); +struct mii_bus *mdiobus_alloc_size(size_t); +static inline struct mii_bus *mdiobus_alloc(void) +{ +	return mdiobus_alloc_size(0); +} +  int mdiobus_register(struct mii_bus *bus);  void mdiobus_unregister(struct mii_bus *bus);  void mdiobus_free(struct mii_bus *bus); +struct mii_bus *devm_mdiobus_alloc_size(struct device *dev, int sizeof_priv); +static inline struct mii_bus *devm_mdiobus_alloc(struct device *dev) +{ +	return devm_mdiobus_alloc_size(dev, 0); +} + +void devm_mdiobus_free(struct device *dev, struct mii_bus *bus);  struct phy_device *mdiobus_scan(struct mii_bus *bus, int addr);  int mdiobus_read(struct mii_bus *bus, int addr, u32 regnum);  int mdiobus_write(struct mii_bus *bus, int addr, u32 regnum, u16 val); @@ -220,7 +294,7 @@ int mdiobus_write(struct mii_bus *bus, int addr, u32 regnum, u16 val);   * - phy_stop moves to HALTED   */  enum phy_state { -	PHY_DOWN=0, +	PHY_DOWN = 0,  	PHY_STARTING,  	PHY_READY,  	PHY_PENDING, @@ -234,7 +308,15 @@ enum phy_state {  	PHY_RESUMING  }; -struct sk_buff; +/** + * struct phy_c45_device_ids - 802.3-c45 Device Identifiers + * @devices_in_package: Bit vector of devices present. + * @device_ids: The device identifer for each present device. + */ +struct phy_c45_device_ids { +	u32 devices_in_package; +	u32 device_ids[8]; +};  /* phy_device: An instance of a PHY   * @@ -242,6 +324,9 @@ struct sk_buff;   * bus: Pointer to the bus this PHY is on   * dev: driver model device structure for this PHY   * phy_id: UID for this device found during discovery + * c45_ids: 802.3-c45 Device Identifers if is_c45. + * is_c45:  Set to true if this phy uses clause 45 addressing. + * is_internal: Set to true if this phy is internal to a MAC.   * state: state of the PHY for management purposes   * dev_flags: Device-specific flags used by the PHY driver.   * addr: Bus address of PHY @@ -253,11 +338,9 @@ struct sk_buff;   * attached_dev: The attached enet driver's device instance ptr   * adjust_link: Callback for the enet controller to respond to   * changes in the link state. - * adjust_state: Callback for the enet driver to respond to - * changes in the state machine.   * - * speed, duplex, pause, supported, advertising, and - * autoneg are used like in mii_if_info + * speed, duplex, pause, supported, advertising, lp_advertising, + * and autoneg are used like in mii_if_info   *   * interrupts currently only supports enabled or disabled,   * but could be changed in the future to support enabling @@ -277,6 +360,11 @@ struct phy_device {  	u32 phy_id; +	struct phy_c45_device_ids c45_ids; +	bool is_c45; +	bool is_internal; +	bool has_fixups; +  	enum phy_state state;  	u32 dev_flags; @@ -305,6 +393,7 @@ struct phy_device {  	/* See mii.h for more info */  	u32 supported;  	u32 advertising; +	u32 lp_advertising;  	int autoneg; @@ -330,8 +419,6 @@ struct phy_device {  	struct net_device *attached_dev;  	void (*adjust_link)(struct net_device *dev); - -	void (*adjust_state)(struct net_device *dev);  };  #define to_phy_device(d) container_of(d, struct phy_device, dev) @@ -363,6 +450,11 @@ struct phy_driver {  	u32 flags;  	/* +	 * Called to issue a PHY software reset +	 */ +	int (*soft_reset)(struct phy_device *phydev); + +	/*  	 * Called to initialize the PHY,  	 * including after a reset  	 */ @@ -386,6 +478,9 @@ struct phy_driver {  	 */  	int (*config_aneg)(struct phy_device *phydev); +	/* Determines the auto negotiation result */ +	int (*aneg_done)(struct phy_device *phydev); +  	/* Determines the negotiated speed and duplex */  	int (*read_status)(struct phy_device *phydev); @@ -404,6 +499,15 @@ struct phy_driver {  	/* Clears up any memory if needed */  	void (*remove)(struct phy_device *phydev); +	/* Returns true if this is a suitable driver for the given +	 * phydev.  If NULL, matching is based on phy_id and +	 * phy_id_mask. +	 */ +	int (*match_phy_device)(struct phy_device *phydev); + +	/* Handles ethtool queries for hardware time stamping. */ +	int (*ts_info)(struct phy_device *phydev, struct ethtool_ts_info *ti); +  	/* Handles SIOCSHWTSTAMP ioctl for hardware time stamping. */  	int  (*hwtstamp)(struct phy_device *phydev, struct ifreq *ifr); @@ -418,12 +522,29 @@ struct phy_driver {  	/*  	 * Requests a Tx timestamp for 'skb'. The phy driver promises -	 * to deliver it to the socket's error queue as soon as a +	 * to deliver it using skb_complete_tx_timestamp() as soon as a  	 * timestamp becomes available. One of the PTP_CLASS_ values  	 * is passed in 'type'.  	 */  	void (*txtstamp)(struct phy_device *dev, struct sk_buff *skb, int type); +	/* Some devices (e.g. qnap TS-119P II) require PHY register changes to +	 * enable Wake on LAN, so set_wol is provided to be called in the +	 * ethernet driver's set_wol function. */ +	int (*set_wol)(struct phy_device *dev, struct ethtool_wolinfo *wol); + +	/* See set_wol, but for checking whether Wake on LAN is enabled. */ +	void (*get_wol)(struct phy_device *dev, struct ethtool_wolinfo *wol); + +	/* +	 * Called to inform a PHY device driver when the core is about to +	 * change the link state. This callback is supposed to be used as +	 * fixup hook for drivers that need to take action when the link +	 * state changes. Drivers are by no means allowed to mess with the +	 * PHY device structure in their implementations. +	 */ +	void (*link_change_notify)(struct phy_device *dev); +  	struct device_driver driver;  };  #define to_phy_driver(d) container_of(d, struct phy_driver, driver) @@ -441,6 +562,24 @@ struct phy_fixup {  };  /** + * phy_read_mmd - Convenience function for reading a register + * from an MMD on a given PHY. + * @phydev: The phy_device struct + * @devad: The MMD to read from + * @regnum: The register on the MMD to read + * + * Same rules as for phy_read(); + */ +static inline int phy_read_mmd(struct phy_device *phydev, int devad, u32 regnum) +{ +	if (!phydev->is_c45) +		return -EOPNOTSUPP; + +	return mdiobus_read(phydev->bus, phydev->addr, +			    MII_ADDR_C45 | (devad << 16) | (regnum & 0xffff)); +} + +/**   * phy_read - Convenience function for reading a given PHY register   * @phydev: the phy_device struct   * @regnum: register number to read @@ -469,19 +608,67 @@ static inline int phy_write(struct phy_device *phydev, u32 regnum, u16 val)  	return mdiobus_write(phydev->bus, phydev->addr, regnum, val);  } -int get_phy_id(struct mii_bus *bus, int addr, u32 *phy_id); -struct phy_device* get_phy_device(struct mii_bus *bus, int addr); +/** + * phy_interrupt_is_valid - Convenience function for testing a given PHY irq + * @phydev: the phy_device struct + * + * NOTE: must be kept in sync with addition/removal of PHY_POLL and + * PHY_IGNORE_INTERRUPT + */ +static inline bool phy_interrupt_is_valid(struct phy_device *phydev) +{ +	return phydev->irq != PHY_POLL && phydev->irq != PHY_IGNORE_INTERRUPT; +} + +/** + * phy_is_internal - Convenience function for testing if a PHY is internal + * @phydev: the phy_device struct + */ +static inline bool phy_is_internal(struct phy_device *phydev) +{ +	return phydev->is_internal; +} + +/** + * phy_write_mmd - Convenience function for writing a register + * on an MMD on a given PHY. + * @phydev: The phy_device struct + * @devad: The MMD to read from + * @regnum: The register on the MMD to read + * @val: value to write to @regnum + * + * Same rules as for phy_write(); + */ +static inline int phy_write_mmd(struct phy_device *phydev, int devad, +				u32 regnum, u16 val) +{ +	if (!phydev->is_c45) +		return -EOPNOTSUPP; + +	regnum = MII_ADDR_C45 | ((devad & 0x1f) << 16) | (regnum & 0xffff); + +	return mdiobus_write(phydev->bus, phydev->addr, regnum, val); +} + +struct phy_device *phy_device_create(struct mii_bus *bus, int addr, int phy_id, +				     bool is_c45, +				     struct phy_c45_device_ids *c45_ids); +struct phy_device *get_phy_device(struct mii_bus *bus, int addr, bool is_c45);  int phy_device_register(struct phy_device *phy);  int phy_init_hw(struct phy_device *phydev); -struct phy_device * phy_attach(struct net_device *dev, -		const char *bus_id, u32 flags, phy_interface_t interface); +int phy_suspend(struct phy_device *phydev); +int phy_resume(struct phy_device *phydev); +struct phy_device *phy_attach(struct net_device *dev, const char *bus_id, +			      phy_interface_t interface);  struct phy_device *phy_find_first(struct mii_bus *bus); +int phy_attach_direct(struct net_device *dev, struct phy_device *phydev, +		      u32 flags, phy_interface_t interface);  int phy_connect_direct(struct net_device *dev, struct phy_device *phydev, -		void (*handler)(struct net_device *), u32 flags, -		phy_interface_t interface); -struct phy_device * phy_connect(struct net_device *dev, const char *bus_id, -		void (*handler)(struct net_device *), u32 flags, -		phy_interface_t interface); +		       void (*handler)(struct net_device *), +		       phy_interface_t interface); +struct phy_device *phy_connect(struct net_device *dev, const char *bus_id, +			       void (*handler)(struct net_device *), +			       phy_interface_t interface);  void phy_disconnect(struct phy_device *phydev);  void phy_detach(struct phy_device *phydev);  void phy_start(struct phy_device *phydev); @@ -490,37 +677,51 @@ int phy_start_aneg(struct phy_device *phydev);  int phy_stop_interrupts(struct phy_device *phydev); -static inline int phy_read_status(struct phy_device *phydev) { +static inline int phy_read_status(struct phy_device *phydev) +{  	return phydev->drv->read_status(phydev);  } +int genphy_config_init(struct phy_device *phydev); +int genphy_setup_forced(struct phy_device *phydev);  int genphy_restart_aneg(struct phy_device *phydev);  int genphy_config_aneg(struct phy_device *phydev); +int genphy_aneg_done(struct phy_device *phydev);  int genphy_update_link(struct phy_device *phydev);  int genphy_read_status(struct phy_device *phydev);  int genphy_suspend(struct phy_device *phydev);  int genphy_resume(struct phy_device *phydev); +int genphy_soft_reset(struct phy_device *phydev);  void phy_driver_unregister(struct phy_driver *drv); +void phy_drivers_unregister(struct phy_driver *drv, int n);  int phy_driver_register(struct phy_driver *new_driver); +int phy_drivers_register(struct phy_driver *new_driver, int n);  void phy_state_machine(struct work_struct *work); -void phy_start_machine(struct phy_device *phydev, -		void (*handler)(struct net_device *)); +void phy_change(struct work_struct *work); +void phy_mac_interrupt(struct phy_device *phydev, int new_link); +void phy_start_machine(struct phy_device *phydev);  void phy_stop_machine(struct phy_device *phydev);  int phy_ethtool_sset(struct phy_device *phydev, struct ethtool_cmd *cmd);  int phy_ethtool_gset(struct phy_device *phydev, struct ethtool_cmd *cmd); -int phy_mii_ioctl(struct phy_device *phydev, -		struct ifreq *ifr, int cmd); +int phy_mii_ioctl(struct phy_device *phydev, struct ifreq *ifr, int cmd);  int phy_start_interrupts(struct phy_device *phydev);  void phy_print_status(struct phy_device *phydev);  void phy_device_free(struct phy_device *phydev);  int phy_register_fixup(const char *bus_id, u32 phy_uid, u32 phy_uid_mask, -		int (*run)(struct phy_device *)); +		       int (*run)(struct phy_device *));  int phy_register_fixup_for_id(const char *bus_id, -		int (*run)(struct phy_device *)); +			      int (*run)(struct phy_device *));  int phy_register_fixup_for_uid(u32 phy_uid, u32 phy_uid_mask, -		int (*run)(struct phy_device *)); -int phy_scan_fixups(struct phy_device *phydev); +			       int (*run)(struct phy_device *)); + +int phy_init_eee(struct phy_device *phydev, bool clk_stop_enable); +int phy_get_eee_err(struct phy_device *phydev); +int phy_ethtool_set_eee(struct phy_device *phydev, struct ethtool_eee *data); +int phy_ethtool_get_eee(struct phy_device *phydev, struct ethtool_eee *data); +int phy_ethtool_set_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol); +void phy_ethtool_get_wol(struct phy_device *phydev, +			 struct ethtool_wolinfo *wol);  int __init mdio_bus_init(void);  void mdio_bus_exit(void);  | 
