1219974Smav/* SPDX-License-Identifier: GPL-2.0-only */ 2219974Smav/* 3219974Smav * linux/mdio.h: definitions for MDIO (clause 45) transceivers 4219974Smav * Copyright 2006-2009 Solarflare Communications Inc. 5219974Smav */ 6219974Smav#ifndef __LINUX_MDIO_H__ 7219974Smav#define __LINUX_MDIO_H__ 8219974Smav 9219974Smav#include <uapi/linux/mdio.h> 10219974Smav#include <linux/bitfield.h> 11219974Smav#include <linux/mod_devicetable.h> 12219974Smav 13219974Smavstruct gpio_desc; 14219974Smavstruct mii_bus; 15219974Smavstruct reset_control; 16219974Smav 17219974Smav/* Multiple levels of nesting are possible. However typically this is 18219974Smav * limited to nested DSA like layer, a MUX layer, and the normal 19219974Smav * user. Instead of trying to handle the general case, just define 20219974Smav * these cases. 21219974Smav */ 22219974Smavenum mdio_mutex_lock_class { 23219974Smav MDIO_MUTEX_NORMAL, 24219974Smav MDIO_MUTEX_MUX, 25219974Smav MDIO_MUTEX_NESTED, 26219974Smav}; 27219974Smav 28219974Smavstruct mdio_device { 29219974Smav struct device dev; 30219974Smav 31219974Smav struct mii_bus *bus; 32219974Smav char modalias[MDIO_NAME_SIZE]; 33219974Smav 34219974Smav int (*bus_match)(struct device *dev, struct device_driver *drv); 35219974Smav void (*device_free)(struct mdio_device *mdiodev); 36219974Smav void (*device_remove)(struct mdio_device *mdiodev); 37219974Smav 38223921Sae /* Bus address of the MDIO device (0-31) */ 39219974Smav int addr; 40219974Smav int flags; 41219974Smav int reset_state; 42219974Smav struct gpio_desc *reset_gpio; 43219974Smav struct reset_control *reset_ctrl; 44219974Smav unsigned int reset_assert_delay; 45219974Smav unsigned int reset_deassert_delay; 46219974Smav}; 47219974Smav 48219974Smavstatic inline struct mdio_device *to_mdio_device(const struct device *dev) 49219974Smav{ 50219974Smav return container_of(dev, struct mdio_device, dev); 51219974Smav} 52219974Smav 53219974Smav/* struct mdio_driver_common: Common to all MDIO drivers */ 54219974Smavstruct mdio_driver_common { 55240465Smav struct device_driver driver; 56267992Shselasky int flags; 57240465Smav}; 58219974Smav#define MDIO_DEVICE_FLAG_PHY 1 59267992Shselasky 60219974Smavstatic inline struct mdio_driver_common * 61220790Smavto_mdio_common_driver(const struct device_driver *driver) 62267992Shselasky{ 63219974Smav return container_of(driver, struct mdio_driver_common, driver); 64219974Smav} 65267992Shselasky 66219974Smav/* struct mdio_driver: Generic MDIO driver */ 67219974Smavstruct mdio_driver { 68219974Smav struct mdio_driver_common mdiodrv; 69267992Shselasky 70219974Smav /* 71219974Smav * Called during discovery. Used to set 72219974Smav * up device-specific structures, if any 73267992Shselasky */ 74219974Smav int (*probe)(struct mdio_device *mdiodev); 75219974Smav 76267992Shselasky /* Clears up any memory if needed */ 77219974Smav void (*remove)(struct mdio_device *mdiodev); 78219974Smav 79267992Shselasky /* Quiesces the device on system shutdown, turns off interrupts etc */ 80219974Smav void (*shutdown)(struct mdio_device *mdiodev); 81219974Smav}; 82267992Shselasky 83219974Smavstatic inline struct mdio_driver * 84219974Smavto_mdio_driver(const struct device_driver *driver) 85219974Smav{ 86219974Smav return container_of(to_mdio_common_driver(driver), struct mdio_driver, 87219974Smav mdiodrv); 88219974Smav} 89219974Smav 90219974Smav/* device driver data */ 91219974Smavstatic inline void mdiodev_set_drvdata(struct mdio_device *mdio, void *data) 92219974Smav{ 93219974Smav dev_set_drvdata(&mdio->dev, data); 94219974Smav} 95219974Smav 96219974Smavstatic inline void *mdiodev_get_drvdata(struct mdio_device *mdio) 97219974Smav{ 98219974Smav return dev_get_drvdata(&mdio->dev); 99219974Smav} 100219974Smav 101242314Smavvoid mdio_device_free(struct mdio_device *mdiodev); 102219974Smavstruct mdio_device *mdio_device_create(struct mii_bus *bus, int addr); 103242314Smavint mdio_device_register(struct mdio_device *mdiodev); 104219974Smavvoid mdio_device_remove(struct mdio_device *mdiodev); 105219974Smavvoid mdio_device_reset(struct mdio_device *mdiodev, int value); 106219974Smavint mdio_driver_register(struct mdio_driver *drv); 107219974Smavvoid mdio_driver_unregister(struct mdio_driver *drv); 108219974Smavint mdio_device_bus_match(struct device *dev, struct device_driver *drv); 109219974Smav 110219974Smavstatic inline void mdio_device_get(struct mdio_device *mdiodev) 111219974Smav{ 112219974Smav get_device(&mdiodev->dev); 113219974Smav} 114219974Smav 115219974Smavstatic inline void mdio_device_put(struct mdio_device *mdiodev) 116219974Smav{ 117219974Smav mdio_device_free(mdiodev); 118219974Smav} 119219974Smav 120219974Smavstatic inline bool mdio_phy_id_is_c45(int phy_id) 121219974Smav{ 122219974Smav return (phy_id & MDIO_PHY_ID_C45) && !(phy_id & ~MDIO_PHY_ID_C45_MASK); 123219974Smav} 124219974Smav 125219974Smavstatic inline __u16 mdio_phy_id_prtad(int phy_id) 126219974Smav{ 127219974Smav return (phy_id & MDIO_PHY_ID_PRTAD) >> 5; 128219974Smav} 129219974Smav 130219974Smavstatic inline __u16 mdio_phy_id_devad(int phy_id) 131219974Smav{ 132219974Smav return phy_id & MDIO_PHY_ID_DEVAD; 133219974Smav} 134219974Smav 135219974Smav/** 136219974Smav * struct mdio_if_info - Ethernet controller MDIO interface 137219974Smav * @prtad: PRTAD of the PHY (%MDIO_PRTAD_NONE if not present/unknown) 138219974Smav * @mmds: Mask of MMDs expected to be present in the PHY. This must be 139219974Smav * non-zero unless @prtad = %MDIO_PRTAD_NONE. 140219974Smav * @mode_support: MDIO modes supported. If %MDIO_SUPPORTS_C22 is set then 141219974Smav * MII register access will be passed through with @devad = 142219974Smav * %MDIO_DEVAD_NONE. If %MDIO_EMULATE_C22 is set then access to 143219974Smav * commonly used clause 22 registers will be translated into 144219974Smav * clause 45 registers. 145219974Smav * @dev: Net device structure 146219974Smav * @mdio_read: Register read function; returns value or negative error code 147219974Smav * @mdio_write: Register write function; returns 0 or negative error code 148219974Smav */ 149219974Smavstruct mdio_if_info { 150219974Smav int prtad; 151219974Smav u32 mmds; 152219974Smav unsigned mode_support; 153219974Smav 154219974Smav struct net_device *dev; 155219974Smav int (*mdio_read)(struct net_device *dev, int prtad, int devad, 156245326Smav u16 addr); 157245326Smav int (*mdio_write)(struct net_device *dev, int prtad, int devad, 158219974Smav u16 addr, u16 val); 159219974Smav}; 160219974Smav 161219974Smav#define MDIO_PRTAD_NONE (-1) 162219974Smav#define MDIO_DEVAD_NONE (-1) 163219974Smav#define MDIO_SUPPORTS_C22 1 164219974Smav#define MDIO_SUPPORTS_C45 2 165219974Smav#define MDIO_EMULATE_C22 4 166219974Smav 167219974Smavstruct ethtool_cmd; 168219974Smavstruct ethtool_pauseparam; 169219974Smavextern int mdio45_probe(struct mdio_if_info *mdio, int prtad); 170219974Smavextern int mdio_set_flag(const struct mdio_if_info *mdio, 171219974Smav int prtad, int devad, u16 addr, int mask, 172219974Smav bool sense); 173219974Smavextern int mdio45_links_ok(const struct mdio_if_info *mdio, u32 mmds); 174219974Smavextern int mdio45_nway_restart(const struct mdio_if_info *mdio); 175219974Smavextern void mdio45_ethtool_gset_npage(const struct mdio_if_info *mdio, 176219974Smav struct ethtool_cmd *ecmd, 177219974Smav u32 npage_adv, u32 npage_lpa); 178219974Smavextern void 179219974Smavmdio45_ethtool_ksettings_get_npage(const struct mdio_if_info *mdio, 180219974Smav struct ethtool_link_ksettings *cmd, 181219974Smav u32 npage_adv, u32 npage_lpa); 182219974Smav 183219974Smav/** 184219974Smav * mdio45_ethtool_gset - get settings for ETHTOOL_GSET 185219974Smav * @mdio: MDIO interface 186219974Smav * @ecmd: Ethtool request structure 187219974Smav * 188219974Smav * Since the CSRs for auto-negotiation using next pages are not fully 189219974Smav * standardised, this function does not attempt to decode them. Use 190219974Smav * mdio45_ethtool_gset_npage() to specify advertisement bits from next 191219974Smav * pages. 192219974Smav */ 193219974Smavstatic inline void mdio45_ethtool_gset(const struct mdio_if_info *mdio, 194219974Smav struct ethtool_cmd *ecmd) 195219974Smav{ 196219974Smav mdio45_ethtool_gset_npage(mdio, ecmd, 0, 0); 197219974Smav} 198219974Smav 199219974Smav/** 200219974Smav * mdio45_ethtool_ksettings_get - get settings for ETHTOOL_GLINKSETTINGS 201219974Smav * @mdio: MDIO interface 202219974Smav * @cmd: Ethtool request structure 203219974Smav * 204219974Smav * Since the CSRs for auto-negotiation using next pages are not fully 205219974Smav * standardised, this function does not attempt to decode them. Use 206219974Smav * mdio45_ethtool_ksettings_get_npage() to specify advertisement bits 207219974Smav * from next pages. 208219974Smav */ 209219974Smavstatic inline void 210219974Smavmdio45_ethtool_ksettings_get(const struct mdio_if_info *mdio, 211219974Smav struct ethtool_link_ksettings *cmd) 212219974Smav{ 213219974Smav mdio45_ethtool_ksettings_get_npage(mdio, cmd, 0, 0); 214219974Smav} 215219974Smav 216219974Smavextern int mdio_mii_ioctl(const struct mdio_if_info *mdio, 217219974Smav struct mii_ioctl_data *mii_data, int cmd); 218239175Smav 219239175Smav/** 220219974Smav * mmd_eee_cap_to_ethtool_sup_t 221219974Smav * @eee_cap: value of the MMD EEE Capability register 222219974Smav * 223219974Smav * A small helper function that translates MMD EEE Capability (3.20) bits 224219974Smav * to ethtool supported settings. 225219974Smav */ 226219974Smavstatic inline u32 mmd_eee_cap_to_ethtool_sup_t(u16 eee_cap) 227219974Smav{ 228219974Smav u32 supported = 0; 229219974Smav 230219974Smav if (eee_cap & MDIO_EEE_100TX) 231219974Smav supported |= SUPPORTED_100baseT_Full; 232219974Smav if (eee_cap & MDIO_EEE_1000T) 233219974Smav supported |= SUPPORTED_1000baseT_Full; 234219974Smav if (eee_cap & MDIO_EEE_10GT) 235219974Smav supported |= SUPPORTED_10000baseT_Full; 236219974Smav if (eee_cap & MDIO_EEE_1000KX) 237219974Smav supported |= SUPPORTED_1000baseKX_Full; 238219974Smav if (eee_cap & MDIO_EEE_10GKX4) 239219974Smav supported |= SUPPORTED_10000baseKX4_Full; 240219974Smav if (eee_cap & MDIO_EEE_10GKR) 241219974Smav supported |= SUPPORTED_10000baseKR_Full; 242219974Smav 243219974Smav return supported; 244219974Smav} 245219974Smav 246219974Smav/** 247219974Smav * mmd_eee_adv_to_ethtool_adv_t 248219974Smav * @eee_adv: value of the MMD EEE Advertisement/Link Partner Ability registers 249219974Smav * 250219974Smav * A small helper function that translates the MMD EEE Advertisment (7.60) 251219974Smav * and MMD EEE Link Partner Ability (7.61) bits to ethtool advertisement 252219974Smav * settings. 253219974Smav */ 254219974Smavstatic inline u32 mmd_eee_adv_to_ethtool_adv_t(u16 eee_adv) 255219974Smav{ 256219974Smav u32 adv = 0; 257219974Smav 258219974Smav if (eee_adv & MDIO_EEE_100TX) 259219974Smav adv |= ADVERTISED_100baseT_Full; 260219974Smav if (eee_adv & MDIO_EEE_1000T) 261219974Smav adv |= ADVERTISED_1000baseT_Full; 262219974Smav if (eee_adv & MDIO_EEE_10GT) 263219974Smav adv |= ADVERTISED_10000baseT_Full; 264219974Smav if (eee_adv & MDIO_EEE_1000KX) 265219974Smav adv |= ADVERTISED_1000baseKX_Full; 266219974Smav if (eee_adv & MDIO_EEE_10GKX4) 267219974Smav adv |= ADVERTISED_10000baseKX4_Full; 268219974Smav if (eee_adv & MDIO_EEE_10GKR) 269219974Smav adv |= ADVERTISED_10000baseKR_Full; 270219974Smav 271219974Smav return adv; 272219974Smav} 273219974Smav 274219974Smav/** 275219974Smav * ethtool_adv_to_mmd_eee_adv_t 276219974Smav * @adv: the ethtool advertisement settings 277219974Smav * 278219974Smav * A small helper function that translates ethtool advertisement settings 279234603Smav * to EEE advertisements for the MMD EEE Advertisement (7.60) and 280234603Smav * MMD EEE Link Partner Ability (7.61) registers. 281234603Smav */ 282234603Smavstatic inline u16 ethtool_adv_to_mmd_eee_adv_t(u32 adv) 283219974Smav{ 284219974Smav u16 reg = 0; 285234603Smav 286234610Smav if (adv & ADVERTISED_100baseT_Full) 287234603Smav reg |= MDIO_EEE_100TX; 288234610Smav if (adv & ADVERTISED_1000baseT_Full) 289219974Smav reg |= MDIO_EEE_1000T; 290219974Smav if (adv & ADVERTISED_10000baseT_Full) 291234458Smav reg |= MDIO_EEE_10GT; 292234603Smav if (adv & ADVERTISED_1000baseKX_Full) 293234458Smav reg |= MDIO_EEE_1000KX; 294234603Smav if (adv & ADVERTISED_10000baseKX4_Full) 295234458Smav reg |= MDIO_EEE_10GKX4; 296234603Smav if (adv & ADVERTISED_10000baseKR_Full) 297234458Smav reg |= MDIO_EEE_10GKR; 298234603Smav 299219974Smav return reg; 300219974Smav} 301234603Smav 302234603Smav/** 303234603Smav * linkmode_adv_to_mii_10gbt_adv_t 304234603Smav * @advertising: the linkmode advertisement settings 305234603Smav * 306234603Smav * A small helper function that translates linkmode advertisement 307234603Smav * settings to phy autonegotiation advertisements for the C45 308234603Smav * 10GBASE-T AN CONTROL (7.32) register. 309219974Smav */ 310234603Smavstatic inline u32 linkmode_adv_to_mii_10gbt_adv_t(unsigned long *advertising) 311234603Smav{ 312234603Smav u32 result = 0; 313234603Smav 314234603Smav if (linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, 315234603Smav advertising)) 316234603Smav result |= MDIO_AN_10GBT_CTRL_ADV2_5G; 317234603Smav if (linkmode_test_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT, 318234603Smav advertising)) 319234603Smav result |= MDIO_AN_10GBT_CTRL_ADV5G; 320219974Smav if (linkmode_test_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT, 321234603Smav advertising)) 322234603Smav result |= MDIO_AN_10GBT_CTRL_ADV10G; 323234603Smav 324234603Smav return result; 325219974Smav} 326219974Smav 327219974Smav/** 328219974Smav * mii_10gbt_stat_mod_linkmode_lpa_t 329219974Smav * @advertising: target the linkmode advertisement settings 330219974Smav * @lpa: value of the C45 10GBASE-T AN STATUS register 331234603Smav * 332234603Smav * A small helper function that translates C45 10GBASE-T AN STATUS register bits 333234603Smav * to linkmode advertisement settings. Other bits in advertising aren't changed. 334234603Smav */ 335234603Smavstatic inline void mii_10gbt_stat_mod_linkmode_lpa_t(unsigned long *advertising, 336234603Smav u32 lpa) 337234603Smav{ 338234603Smav linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, 339219974Smav advertising, lpa & MDIO_AN_10GBT_STAT_LP2_5G); 340219974Smav linkmode_mod_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT, 341234603Smav advertising, lpa & MDIO_AN_10GBT_STAT_LP5G); 342234603Smav linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT, 343234603Smav advertising, lpa & MDIO_AN_10GBT_STAT_LP10G); 344234603Smav} 345234603Smav 346234603Smav/** 347234603Smav * mii_t1_adv_l_mod_linkmode_t 348234603Smav * @advertising: target the linkmode advertisement settings 349219974Smav * @lpa: value of the BASE-T1 Autonegotiation Advertisement [15:0] Register 350234603Smav * 351234603Smav * A small helper function that translates BASE-T1 Autonegotiation 352234603Smav * Advertisement [15:0] Register bits to linkmode advertisement settings. 353234603Smav * Other bits in advertising aren't changed. 354234603Smav */ 355234603Smavstatic inline void mii_t1_adv_l_mod_linkmode_t(unsigned long *advertising, u32 lpa) 356234603Smav{ 357234603Smav linkmode_mod_bit(ETHTOOL_LINK_MODE_Pause_BIT, advertising, 358234603Smav lpa & MDIO_AN_T1_ADV_L_PAUSE_CAP); 359234603Smav linkmode_mod_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, advertising, 360219974Smav lpa & MDIO_AN_T1_ADV_L_PAUSE_ASYM); 361219974Smav} 362219974Smav 363219974Smav/** 364219974Smav * mii_t1_adv_m_mod_linkmode_t 365219974Smav * @advertising: target the linkmode advertisement settings 366219974Smav * @lpa: value of the BASE-T1 Autonegotiation Advertisement [31:16] Register 367219974Smav * 368219974Smav * A small helper function that translates BASE-T1 Autonegotiation 369219974Smav * Advertisement [31:16] Register bits to linkmode advertisement settings. 370219974Smav * Other bits in advertising aren't changed. 371219974Smav */ 372219974Smavstatic inline void mii_t1_adv_m_mod_linkmode_t(unsigned long *advertising, u32 lpa) 373219974Smav{ 374219974Smav linkmode_mod_bit(ETHTOOL_LINK_MODE_10baseT1L_Full_BIT, 375234603Smav advertising, lpa & MDIO_AN_T1_ADV_M_B10L); 376219974Smav linkmode_mod_bit(ETHTOOL_LINK_MODE_100baseT1_Full_BIT, 377234603Smav advertising, lpa & MDIO_AN_T1_ADV_M_100BT1); 378234993Smav linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT1_Full_BIT, 379234603Smav advertising, lpa & MDIO_AN_T1_ADV_M_1000BT1); 380234603Smav} 381234993Smav 382234603Smav/** 383219974Smav * linkmode_adv_to_mii_t1_adv_l_t 384234603Smav * @advertising: the linkmode advertisement settings 385234993Smav * 386234603Smav * A small helper function that translates linkmode advertisement 387234603Smav * settings to phy autonegotiation advertisements for the 388234993Smav * BASE-T1 Autonegotiation Advertisement [15:0] Register. 389234603Smav */ 390219974Smavstatic inline u32 linkmode_adv_to_mii_t1_adv_l_t(unsigned long *advertising) 391234458Smav{ 392234603Smav u32 result = 0; 393234458Smav 394234458Smav if (linkmode_test_bit(ETHTOOL_LINK_MODE_Pause_BIT, advertising)) 395234458Smav result |= MDIO_AN_T1_ADV_L_PAUSE_CAP; 396234603Smav if (linkmode_test_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, advertising)) 397234458Smav result |= MDIO_AN_T1_ADV_L_PAUSE_ASYM; 398234458Smav 399234603Smav return result; 400234458Smav} 401234458Smav 402234603Smav/** 403219974Smav * linkmode_adv_to_mii_t1_adv_m_t 404234603Smav * @advertising: the linkmode advertisement settings 405234603Smav * 406234603Smav * A small helper function that translates linkmode advertisement 407234603Smav * settings to phy autonegotiation advertisements for the 408234603Smav * BASE-T1 Autonegotiation Advertisement [31:16] Register. 409234603Smav */ 410234603Smavstatic inline u32 linkmode_adv_to_mii_t1_adv_m_t(unsigned long *advertising) 411234603Smav{ 412234603Smav u32 result = 0; 413234603Smav 414234603Smav if (linkmode_test_bit(ETHTOOL_LINK_MODE_10baseT1L_Full_BIT, advertising)) 415234603Smav result |= MDIO_AN_T1_ADV_M_B10L; 416234603Smav if (linkmode_test_bit(ETHTOOL_LINK_MODE_100baseT1_Full_BIT, advertising)) 417234603Smav result |= MDIO_AN_T1_ADV_M_100BT1; 418234603Smav if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT1_Full_BIT, advertising)) 419234603Smav result |= MDIO_AN_T1_ADV_M_1000BT1; 420234603Smav 421234603Smav return result; 422234603Smav} 423234603Smav 424234603Smav/** 425234603Smav * mii_eee_cap1_mod_linkmode_t() 426234603Smav * @adv: target the linkmode advertisement settings 427234603Smav * @val: register value 428234603Smav * 429234603Smav * A function that translates value of following registers to the linkmode: 430234603Smav * IEEE 802.3-2018 45.2.3.10 "EEE control and capability 1" register (3.20) 431219974Smav * IEEE 802.3-2018 45.2.7.13 "EEE advertisement 1" register (7.60) 432234603Smav * IEEE 802.3-2018 45.2.7.14 "EEE link partner ability 1" register (7.61) 433234603Smav */ 434234603Smavstatic inline void mii_eee_cap1_mod_linkmode_t(unsigned long *adv, u32 val) 435234603Smav{ 436234603Smav linkmode_mod_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, 437219974Smav adv, val & MDIO_EEE_100TX); 438219974Smav linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, 439219974Smav adv, val & MDIO_EEE_1000T); 440234603Smav linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT, 441219974Smav adv, val & MDIO_EEE_10GT); 442234603Smav linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseKX_Full_BIT, 443234603Smav adv, val & MDIO_EEE_1000KX); 444234603Smav linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT, 445234603Smav adv, val & MDIO_EEE_10GKX4); 446234603Smav linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseKR_Full_BIT, 447234603Smav adv, val & MDIO_EEE_10GKR); 448234603Smav} 449234603Smav 450234603Smav/** 451234603Smav * mii_eee_cap2_mod_linkmode_sup_t() 452234603Smav * @adv: target the linkmode settings 453234603Smav * @val: register value 454219974Smav * 455234603Smav * A function that translates value of following registers to the linkmode: 456234603Smav * IEEE 802.3-2022 45.2.3.11 "EEE control and capability 2" register (3.21) 457234603Smav */ 458234603Smavstatic inline void mii_eee_cap2_mod_linkmode_sup_t(unsigned long *adv, u32 val) 459234603Smav{ 460234603Smav linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, 461234603Smav adv, val & MDIO_EEE_2_5GT); 462234603Smav linkmode_mod_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT, 463234603Smav adv, val & MDIO_EEE_5GT); 464234603Smav} 465234603Smav 466234603Smav/** 467234603Smav * mii_eee_cap2_mod_linkmode_adv_t() 468234603Smav * @adv: target the linkmode advertisement settings 469234603Smav * @val: register value 470234603Smav * 471234603Smav * A function that translates value of following registers to the linkmode: 472234603Smav * IEEE 802.3-2022 45.2.7.16 "EEE advertisement 2" register (7.62) 473234603Smav * IEEE 802.3-2022 45.2.7.17 "EEE link partner ability 2" register (7.63) 474234603Smav * Note: Currently this function is the same as mii_eee_cap2_mod_linkmode_sup_t. 475234603Smav * For certain, not yet supported, modes however the bits differ. 476234603Smav * Therefore create separate functions already. 477234603Smav */ 478234603Smavstatic inline void mii_eee_cap2_mod_linkmode_adv_t(unsigned long *adv, u32 val) 479234603Smav{ 480219974Smav linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, 481219974Smav adv, val & MDIO_EEE_2_5GT); 482219974Smav linkmode_mod_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT, 483219974Smav adv, val & MDIO_EEE_5GT); 484219974Smav} 485219974Smav 486219974Smav/** 487219974Smav * linkmode_to_mii_eee_cap1_t() 488219974Smav * @adv: the linkmode advertisement settings 489219974Smav * 490219974Smav * A function that translates linkmode to value for IEEE 802.3-2018 45.2.7.13 491219974Smav * "EEE advertisement 1" register (7.60) 492219974Smav */ 493219974Smavstatic inline u32 linkmode_to_mii_eee_cap1_t(unsigned long *adv) 494242323Smav{ 495242323Smav u32 result = 0; 496242323Smav 497242323Smav if (linkmode_test_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, adv)) 498242323Smav result |= MDIO_EEE_100TX; 499242323Smav if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, adv)) 500242323Smav result |= MDIO_EEE_1000T; 501242323Smav if (linkmode_test_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT, adv)) 502242323Smav result |= MDIO_EEE_10GT; 503242323Smav if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseKX_Full_BIT, adv)) 504242323Smav result |= MDIO_EEE_1000KX; 505242323Smav if (linkmode_test_bit(ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT, adv)) 506242323Smav result |= MDIO_EEE_10GKX4; 507242323Smav if (linkmode_test_bit(ETHTOOL_LINK_MODE_10000baseKR_Full_BIT, adv)) 508242323Smav result |= MDIO_EEE_10GKR; 509242323Smav 510242323Smav return result; 511242323Smav} 512242323Smav 513242323Smav/** 514242323Smav * linkmode_to_mii_eee_cap2_t() 515242323Smav * @adv: the linkmode advertisement settings 516242323Smav * 517242323Smav * A function that translates linkmode to value for IEEE 802.3-2022 45.2.7.16 518242323Smav * "EEE advertisement 2" register (7.62) 519242323Smav */ 520242323Smavstatic inline u32 linkmode_to_mii_eee_cap2_t(unsigned long *adv) 521242323Smav{ 522219974Smav u32 result = 0; 523219974Smav 524219974Smav if (linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, adv)) 525219974Smav result |= MDIO_EEE_2_5GT; 526219974Smav if (linkmode_test_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT, adv)) 527219974Smav result |= MDIO_EEE_5GT; 528219974Smav 529219974Smav return result; 530245326Smav} 531245363Smav 532245326Smav/** 533219974Smav * mii_10base_t1_adv_mod_linkmode_t() 534219974Smav * @adv: linkmode advertisement settings 535219974Smav * @val: register value 536219974Smav * 537219974Smav * A function that translates IEEE 802.3cg-2019 45.2.7.26 "10BASE-T1 AN status" 538219974Smav * register (7.527) value to the linkmode. 539219974Smav */ 540219974Smavstatic inline void mii_10base_t1_adv_mod_linkmode_t(unsigned long *adv, u16 val) 541219974Smav{ 542219974Smav linkmode_mod_bit(ETHTOOL_LINK_MODE_10baseT1L_Full_BIT, 543219974Smav adv, val & MDIO_AN_10BT1_AN_CTRL_ADV_EEE_T1L); 544219974Smav} 545219974Smav 546219974Smav/** 547219974Smav * linkmode_adv_to_mii_10base_t1_t() 548219974Smav * @adv: linkmode advertisement settings 549219974Smav * 550219974Smav * A function that translates the linkmode to IEEE 802.3cg-2019 45.2.7.25 551219974Smav * "10BASE-T1 AN control" register (7.526) value. 552219974Smav */ 553219974Smavstatic inline u32 linkmode_adv_to_mii_10base_t1_t(unsigned long *adv) 554219974Smav{ 555219974Smav u32 result = 0; 556219974Smav 557219974Smav if (linkmode_test_bit(ETHTOOL_LINK_MODE_10baseT1L_Full_BIT, adv)) 558219974Smav result |= MDIO_AN_10BT1_AN_CTRL_ADV_EEE_T1L; 559219974Smav 560219974Smav return result; 561219974Smav} 562219974Smav 563219974Smav/** 564219974Smav * mii_c73_mod_linkmode - convert a Clause 73 advertisement to linkmodes 565219974Smav * @adv: linkmode advertisement setting 566219974Smav * @lpa: array of three u16s containing the advertisement 567219974Smav * 568219974Smav * Convert an IEEE 802.3 Clause 73 advertisement to ethtool link modes. 569219974Smav */ 570219974Smavstatic inline void mii_c73_mod_linkmode(unsigned long *adv, u16 *lpa) 571219974Smav{ 572219974Smav linkmode_mod_bit(ETHTOOL_LINK_MODE_Pause_BIT, 573219974Smav adv, lpa[0] & MDIO_AN_C73_0_PAUSE); 574219974Smav linkmode_mod_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, 575219974Smav adv, lpa[0] & MDIO_AN_C73_0_ASM_DIR); 576219974Smav linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseKX_Full_BIT, 577219974Smav adv, lpa[1] & MDIO_AN_C73_1_1000BASE_KX); 578219974Smav linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT, 579219974Smav adv, lpa[1] & MDIO_AN_C73_1_10GBASE_KX4); 580219974Smav linkmode_mod_bit(ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT, 581219974Smav adv, lpa[1] & MDIO_AN_C73_1_40GBASE_KR4); 582219974Smav linkmode_mod_bit(ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT, 583219974Smav adv, lpa[1] & MDIO_AN_C73_1_40GBASE_CR4); 584219974Smav /* 100GBASE_CR10 and 100GBASE_KP4 not implemented */ 585219974Smav linkmode_mod_bit(ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT, 586219974Smav adv, lpa[1] & MDIO_AN_C73_1_100GBASE_KR4); 587219974Smav linkmode_mod_bit(ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT, 588219974Smav adv, lpa[1] & MDIO_AN_C73_1_100GBASE_CR4); 589219974Smav /* 25GBASE_R_S not implemented */ 590219974Smav /* The 25GBASE_R bit can be used for 25Gbase KR or CR modes */ 591219974Smav linkmode_mod_bit(ETHTOOL_LINK_MODE_25000baseKR_Full_BIT, 592219974Smav adv, lpa[1] & MDIO_AN_C73_1_25GBASE_R); 593219974Smav linkmode_mod_bit(ETHTOOL_LINK_MODE_25000baseCR_Full_BIT, 594219974Smav adv, lpa[1] & MDIO_AN_C73_1_25GBASE_R); 595219974Smav linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseKR_Full_BIT, 596219974Smav adv, lpa[1] & MDIO_AN_C73_1_10GBASE_KR); 597219974Smav linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseX_Full_BIT, 598219974Smav adv, lpa[2] & MDIO_AN_C73_2_2500BASE_KX); 599219974Smav /* 5GBASE_KR not implemented */ 600219974Smav} 601219974Smav 602219974Smavint __mdiobus_read(struct mii_bus *bus, int addr, u32 regnum); 603219974Smavint __mdiobus_write(struct mii_bus *bus, int addr, u32 regnum, u16 val); 604219974Smavint __mdiobus_modify(struct mii_bus *bus, int addr, u32 regnum, u16 mask, 605219974Smav u16 set); 606219974Smavint __mdiobus_modify_changed(struct mii_bus *bus, int addr, u32 regnum, 607219974Smav u16 mask, u16 set); 608219974Smav 609219974Smavint mdiobus_read(struct mii_bus *bus, int addr, u32 regnum); 610219974Smavint mdiobus_read_nested(struct mii_bus *bus, int addr, u32 regnum); 611219974Smavint mdiobus_write(struct mii_bus *bus, int addr, u32 regnum, u16 val); 612219974Smavint mdiobus_write_nested(struct mii_bus *bus, int addr, u32 regnum, u16 val); 613219974Smavint mdiobus_modify(struct mii_bus *bus, int addr, u32 regnum, u16 mask, 614219974Smav u16 set); 615219974Smavint mdiobus_modify_changed(struct mii_bus *bus, int addr, u32 regnum, 616219974Smav u16 mask, u16 set); 617219974Smavint __mdiobus_c45_read(struct mii_bus *bus, int addr, int devad, u32 regnum); 618219974Smavint mdiobus_c45_read(struct mii_bus *bus, int addr, int devad, u32 regnum); 619219974Smavint mdiobus_c45_read_nested(struct mii_bus *bus, int addr, int devad, 620219974Smav u32 regnum); 621219974Smavint __mdiobus_c45_write(struct mii_bus *bus, int addr, int devad, u32 regnum, 622219974Smav u16 val); 623219974Smavint mdiobus_c45_write(struct mii_bus *bus, int addr, int devad, u32 regnum, 624219974Smav u16 val); 625219974Smavint mdiobus_c45_write_nested(struct mii_bus *bus, int addr, int devad, 626219974Smav u32 regnum, u16 val); 627219974Smavint mdiobus_c45_modify(struct mii_bus *bus, int addr, int devad, u32 regnum, 628219974Smav u16 mask, u16 set); 629219974Smav 630219974Smavint mdiobus_c45_modify_changed(struct mii_bus *bus, int addr, int devad, 631219974Smav u32 regnum, u16 mask, u16 set); 632219974Smav 633219974Smavstatic inline int __mdiodev_read(struct mdio_device *mdiodev, u32 regnum) 634219974Smav{ 635219974Smav return __mdiobus_read(mdiodev->bus, mdiodev->addr, regnum); 636219974Smav} 637219974Smav 638219974Smavstatic inline int __mdiodev_write(struct mdio_device *mdiodev, u32 regnum, 639219974Smav u16 val) 640219974Smav{ 641219974Smav return __mdiobus_write(mdiodev->bus, mdiodev->addr, regnum, val); 642219974Smav} 643219974Smav 644219974Smavstatic inline int __mdiodev_modify(struct mdio_device *mdiodev, u32 regnum, 645219974Smav u16 mask, u16 set) 646219974Smav{ 647219974Smav return __mdiobus_modify(mdiodev->bus, mdiodev->addr, regnum, mask, set); 648219974Smav} 649219974Smav 650219974Smavstatic inline int __mdiodev_modify_changed(struct mdio_device *mdiodev, 651219974Smav u32 regnum, u16 mask, u16 set) 652219974Smav{ 653219974Smav return __mdiobus_modify_changed(mdiodev->bus, mdiodev->addr, regnum, 654219974Smav mask, set); 655219974Smav} 656219974Smav 657219974Smavstatic inline int mdiodev_read(struct mdio_device *mdiodev, u32 regnum) 658219974Smav{ 659219974Smav return mdiobus_read(mdiodev->bus, mdiodev->addr, regnum); 660219974Smav} 661219974Smav 662219974Smavstatic inline int mdiodev_write(struct mdio_device *mdiodev, u32 regnum, 663219974Smav u16 val) 664219974Smav{ 665219974Smav return mdiobus_write(mdiodev->bus, mdiodev->addr, regnum, val); 666219974Smav} 667219974Smav 668219974Smavstatic inline int mdiodev_modify(struct mdio_device *mdiodev, u32 regnum, 669219974Smav u16 mask, u16 set) 670219974Smav{ 671219974Smav return mdiobus_modify(mdiodev->bus, mdiodev->addr, regnum, mask, set); 672219974Smav} 673219974Smav 674219974Smavstatic inline int mdiodev_modify_changed(struct mdio_device *mdiodev, 675219974Smav u32 regnum, u16 mask, u16 set) 676219974Smav{ 677219974Smav return mdiobus_modify_changed(mdiodev->bus, mdiodev->addr, regnum, 678219974Smav mask, set); 679219974Smav} 680219974Smav 681219974Smavstatic inline int mdiodev_c45_modify(struct mdio_device *mdiodev, int devad, 682219974Smav u32 regnum, u16 mask, u16 set) 683219974Smav{ 684219974Smav return mdiobus_c45_modify(mdiodev->bus, mdiodev->addr, devad, regnum, 685219974Smav mask, set); 686219974Smav} 687219974Smav 688219974Smavstatic inline int mdiodev_c45_modify_changed(struct mdio_device *mdiodev, 689219974Smav int devad, u32 regnum, u16 mask, 690219974Smav u16 set) 691219974Smav{ 692219974Smav return mdiobus_c45_modify_changed(mdiodev->bus, mdiodev->addr, devad, 693219974Smav regnum, mask, set); 694219974Smav} 695219974Smav 696219974Smavstatic inline int mdiodev_c45_read(struct mdio_device *mdiodev, int devad, 697219974Smav u16 regnum) 698219974Smav{ 699219974Smav return mdiobus_c45_read(mdiodev->bus, mdiodev->addr, devad, regnum); 700219974Smav} 701219974Smav 702219974Smavstatic inline int mdiodev_c45_write(struct mdio_device *mdiodev, u32 devad, 703219974Smav u16 regnum, u16 val) 704219974Smav{ 705219974Smav return mdiobus_c45_write(mdiodev->bus, mdiodev->addr, devad, regnum, 706219974Smav val); 707219974Smav} 708219974Smav 709219974Smavint mdiobus_register_device(struct mdio_device *mdiodev); 710219974Smavint mdiobus_unregister_device(struct mdio_device *mdiodev); 711219974Smavbool mdiobus_is_registered_device(struct mii_bus *bus, int addr); 712219974Smavstruct phy_device *mdiobus_get_phy(struct mii_bus *bus, int addr); 713219974Smav 714219974Smav/** 715219974Smav * mdio_module_driver() - Helper macro for registering mdio drivers 716219974Smav * @_mdio_driver: driver to register 717219974Smav * 718219974Smav * Helper macro for MDIO drivers which do not do anything special in module 719219974Smav * init/exit. Each module may only use this macro once, and calling it 720219974Smav * replaces module_init() and module_exit(). 721219974Smav */ 722219974Smav#define mdio_module_driver(_mdio_driver) \ 723219974Smavstatic int __init mdio_module_init(void) \ 724219974Smav{ \ 725219974Smav return mdio_driver_register(&_mdio_driver); \ 726219974Smav} \ 727219974Smavmodule_init(mdio_module_init); \ 728219974Smavstatic void __exit mdio_module_exit(void) \ 729219974Smav{ \ 730219974Smav mdio_driver_unregister(&_mdio_driver); \ 731219974Smav} \ 732219974Smavmodule_exit(mdio_module_exit) 733219974Smav 734219974Smav#endif /* __LINUX_MDIO_H__ */ 735219974Smav