linux/include/linux/mdio.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0-only */
   2/*
   3 * linux/mdio.h: definitions for MDIO (clause 45) transceivers
   4 * Copyright 2006-2009 Solarflare Communications Inc.
   5 */
   6#ifndef __LINUX_MDIO_H__
   7#define __LINUX_MDIO_H__
   8
   9#include <uapi/linux/mdio.h>
  10#include <linux/mod_devicetable.h>
  11
  12/* Or MII_ADDR_C45 into regnum for read/write on mii_bus to enable the 21 bit
  13 * IEEE 802.3ae clause 45 addressing mode used by 10GIGE phy chips.
  14 */
  15#define MII_ADDR_C45            (1<<30)
  16#define MII_DEVADDR_C45_SHIFT   16
  17#define MII_REGADDR_C45_MASK    GENMASK(15, 0)
  18
  19struct gpio_desc;
  20struct mii_bus;
  21struct reset_control;
  22
  23/* Multiple levels of nesting are possible. However typically this is
  24 * limited to nested DSA like layer, a MUX layer, and the normal
  25 * user. Instead of trying to handle the general case, just define
  26 * these cases.
  27 */
  28enum mdio_mutex_lock_class {
  29        MDIO_MUTEX_NORMAL,
  30        MDIO_MUTEX_MUX,
  31        MDIO_MUTEX_NESTED,
  32};
  33
  34struct mdio_device {
  35        struct device dev;
  36
  37        struct mii_bus *bus;
  38        char modalias[MDIO_NAME_SIZE];
  39
  40        int (*bus_match)(struct device *dev, struct device_driver *drv);
  41        void (*device_free)(struct mdio_device *mdiodev);
  42        void (*device_remove)(struct mdio_device *mdiodev);
  43
  44        /* Bus address of the MDIO device (0-31) */
  45        int addr;
  46        int flags;
  47        struct gpio_desc *reset_gpio;
  48        struct reset_control *reset_ctrl;
  49        unsigned int reset_assert_delay;
  50        unsigned int reset_deassert_delay;
  51};
  52
  53static inline struct mdio_device *to_mdio_device(const struct device *dev)
  54{
  55        return container_of(dev, struct mdio_device, dev);
  56}
  57
  58/* struct mdio_driver_common: Common to all MDIO drivers */
  59struct mdio_driver_common {
  60        struct device_driver driver;
  61        int flags;
  62};
  63#define MDIO_DEVICE_FLAG_PHY            1
  64
  65static inline struct mdio_driver_common *
  66to_mdio_common_driver(const struct device_driver *driver)
  67{
  68        return container_of(driver, struct mdio_driver_common, driver);
  69}
  70
  71/* struct mdio_driver: Generic MDIO driver */
  72struct mdio_driver {
  73        struct mdio_driver_common mdiodrv;
  74
  75        /*
  76         * Called during discovery.  Used to set
  77         * up device-specific structures, if any
  78         */
  79        int (*probe)(struct mdio_device *mdiodev);
  80
  81        /* Clears up any memory if needed */
  82        void (*remove)(struct mdio_device *mdiodev);
  83
  84        /* Quiesces the device on system shutdown, turns off interrupts etc */
  85        void (*shutdown)(struct mdio_device *mdiodev);
  86};
  87
  88static inline struct mdio_driver *
  89to_mdio_driver(const struct device_driver *driver)
  90{
  91        return container_of(to_mdio_common_driver(driver), struct mdio_driver,
  92                            mdiodrv);
  93}
  94
  95/* device driver data */
  96static inline void mdiodev_set_drvdata(struct mdio_device *mdio, void *data)
  97{
  98        dev_set_drvdata(&mdio->dev, data);
  99}
 100
 101static inline void *mdiodev_get_drvdata(struct mdio_device *mdio)
 102{
 103        return dev_get_drvdata(&mdio->dev);
 104}
 105
 106void mdio_device_free(struct mdio_device *mdiodev);
 107struct mdio_device *mdio_device_create(struct mii_bus *bus, int addr);
 108int mdio_device_register(struct mdio_device *mdiodev);
 109void mdio_device_remove(struct mdio_device *mdiodev);
 110void mdio_device_reset(struct mdio_device *mdiodev, int value);
 111int mdio_driver_register(struct mdio_driver *drv);
 112void mdio_driver_unregister(struct mdio_driver *drv);
 113int mdio_device_bus_match(struct device *dev, struct device_driver *drv);
 114
 115static inline bool mdio_phy_id_is_c45(int phy_id)
 116{
 117        return (phy_id & MDIO_PHY_ID_C45) && !(phy_id & ~MDIO_PHY_ID_C45_MASK);
 118}
 119
 120static inline __u16 mdio_phy_id_prtad(int phy_id)
 121{
 122        return (phy_id & MDIO_PHY_ID_PRTAD) >> 5;
 123}
 124
 125static inline __u16 mdio_phy_id_devad(int phy_id)
 126{
 127        return phy_id & MDIO_PHY_ID_DEVAD;
 128}
 129
 130/**
 131 * struct mdio_if_info - Ethernet controller MDIO interface
 132 * @prtad: PRTAD of the PHY (%MDIO_PRTAD_NONE if not present/unknown)
 133 * @mmds: Mask of MMDs expected to be present in the PHY.  This must be
 134 *      non-zero unless @prtad = %MDIO_PRTAD_NONE.
 135 * @mode_support: MDIO modes supported.  If %MDIO_SUPPORTS_C22 is set then
 136 *      MII register access will be passed through with @devad =
 137 *      %MDIO_DEVAD_NONE.  If %MDIO_EMULATE_C22 is set then access to
 138 *      commonly used clause 22 registers will be translated into
 139 *      clause 45 registers.
 140 * @dev: Net device structure
 141 * @mdio_read: Register read function; returns value or negative error code
 142 * @mdio_write: Register write function; returns 0 or negative error code
 143 */
 144struct mdio_if_info {
 145        int prtad;
 146        u32 mmds;
 147        unsigned mode_support;
 148
 149        struct net_device *dev;
 150        int (*mdio_read)(struct net_device *dev, int prtad, int devad,
 151                         u16 addr);
 152        int (*mdio_write)(struct net_device *dev, int prtad, int devad,
 153                          u16 addr, u16 val);
 154};
 155
 156#define MDIO_PRTAD_NONE                 (-1)
 157#define MDIO_DEVAD_NONE                 (-1)
 158#define MDIO_SUPPORTS_C22               1
 159#define MDIO_SUPPORTS_C45               2
 160#define MDIO_EMULATE_C22                4
 161
 162struct ethtool_cmd;
 163struct ethtool_pauseparam;
 164extern int mdio45_probe(struct mdio_if_info *mdio, int prtad);
 165extern int mdio_set_flag(const struct mdio_if_info *mdio,
 166                         int prtad, int devad, u16 addr, int mask,
 167                         bool sense);
 168extern int mdio45_links_ok(const struct mdio_if_info *mdio, u32 mmds);
 169extern int mdio45_nway_restart(const struct mdio_if_info *mdio);
 170extern void mdio45_ethtool_gset_npage(const struct mdio_if_info *mdio,
 171                                      struct ethtool_cmd *ecmd,
 172                                      u32 npage_adv, u32 npage_lpa);
 173extern void
 174mdio45_ethtool_ksettings_get_npage(const struct mdio_if_info *mdio,
 175                                   struct ethtool_link_ksettings *cmd,
 176                                   u32 npage_adv, u32 npage_lpa);
 177
 178/**
 179 * mdio45_ethtool_gset - get settings for ETHTOOL_GSET
 180 * @mdio: MDIO interface
 181 * @ecmd: Ethtool request structure
 182 *
 183 * Since the CSRs for auto-negotiation using next pages are not fully
 184 * standardised, this function does not attempt to decode them.  Use
 185 * mdio45_ethtool_gset_npage() to specify advertisement bits from next
 186 * pages.
 187 */
 188static inline void mdio45_ethtool_gset(const struct mdio_if_info *mdio,
 189                                       struct ethtool_cmd *ecmd)
 190{
 191        mdio45_ethtool_gset_npage(mdio, ecmd, 0, 0);
 192}
 193
 194/**
 195 * mdio45_ethtool_ksettings_get - get settings for ETHTOOL_GLINKSETTINGS
 196 * @mdio: MDIO interface
 197 * @cmd: Ethtool request structure
 198 *
 199 * Since the CSRs for auto-negotiation using next pages are not fully
 200 * standardised, this function does not attempt to decode them.  Use
 201 * mdio45_ethtool_ksettings_get_npage() to specify advertisement bits
 202 * from next pages.
 203 */
 204static inline void
 205mdio45_ethtool_ksettings_get(const struct mdio_if_info *mdio,
 206                             struct ethtool_link_ksettings *cmd)
 207{
 208        mdio45_ethtool_ksettings_get_npage(mdio, cmd, 0, 0);
 209}
 210
 211extern int mdio_mii_ioctl(const struct mdio_if_info *mdio,
 212                          struct mii_ioctl_data *mii_data, int cmd);
 213
 214/**
 215 * mmd_eee_cap_to_ethtool_sup_t
 216 * @eee_cap: value of the MMD EEE Capability register
 217 *
 218 * A small helper function that translates MMD EEE Capability (3.20) bits
 219 * to ethtool supported settings.
 220 */
 221static inline u32 mmd_eee_cap_to_ethtool_sup_t(u16 eee_cap)
 222{
 223        u32 supported = 0;
 224
 225        if (eee_cap & MDIO_EEE_100TX)
 226                supported |= SUPPORTED_100baseT_Full;
 227        if (eee_cap & MDIO_EEE_1000T)
 228                supported |= SUPPORTED_1000baseT_Full;
 229        if (eee_cap & MDIO_EEE_10GT)
 230                supported |= SUPPORTED_10000baseT_Full;
 231        if (eee_cap & MDIO_EEE_1000KX)
 232                supported |= SUPPORTED_1000baseKX_Full;
 233        if (eee_cap & MDIO_EEE_10GKX4)
 234                supported |= SUPPORTED_10000baseKX4_Full;
 235        if (eee_cap & MDIO_EEE_10GKR)
 236                supported |= SUPPORTED_10000baseKR_Full;
 237
 238        return supported;
 239}
 240
 241/**
 242 * mmd_eee_adv_to_ethtool_adv_t
 243 * @eee_adv: value of the MMD EEE Advertisement/Link Partner Ability registers
 244 *
 245 * A small helper function that translates the MMD EEE Advertisment (7.60)
 246 * and MMD EEE Link Partner Ability (7.61) bits to ethtool advertisement
 247 * settings.
 248 */
 249static inline u32 mmd_eee_adv_to_ethtool_adv_t(u16 eee_adv)
 250{
 251        u32 adv = 0;
 252
 253        if (eee_adv & MDIO_EEE_100TX)
 254                adv |= ADVERTISED_100baseT_Full;
 255        if (eee_adv & MDIO_EEE_1000T)
 256                adv |= ADVERTISED_1000baseT_Full;
 257        if (eee_adv & MDIO_EEE_10GT)
 258                adv |= ADVERTISED_10000baseT_Full;
 259        if (eee_adv & MDIO_EEE_1000KX)
 260                adv |= ADVERTISED_1000baseKX_Full;
 261        if (eee_adv & MDIO_EEE_10GKX4)
 262                adv |= ADVERTISED_10000baseKX4_Full;
 263        if (eee_adv & MDIO_EEE_10GKR)
 264                adv |= ADVERTISED_10000baseKR_Full;
 265
 266        return adv;
 267}
 268
 269/**
 270 * ethtool_adv_to_mmd_eee_adv_t
 271 * @adv: the ethtool advertisement settings
 272 *
 273 * A small helper function that translates ethtool advertisement settings
 274 * to EEE advertisements for the MMD EEE Advertisement (7.60) and
 275 * MMD EEE Link Partner Ability (7.61) registers.
 276 */
 277static inline u16 ethtool_adv_to_mmd_eee_adv_t(u32 adv)
 278{
 279        u16 reg = 0;
 280
 281        if (adv & ADVERTISED_100baseT_Full)
 282                reg |= MDIO_EEE_100TX;
 283        if (adv & ADVERTISED_1000baseT_Full)
 284                reg |= MDIO_EEE_1000T;
 285        if (adv & ADVERTISED_10000baseT_Full)
 286                reg |= MDIO_EEE_10GT;
 287        if (adv & ADVERTISED_1000baseKX_Full)
 288                reg |= MDIO_EEE_1000KX;
 289        if (adv & ADVERTISED_10000baseKX4_Full)
 290                reg |= MDIO_EEE_10GKX4;
 291        if (adv & ADVERTISED_10000baseKR_Full)
 292                reg |= MDIO_EEE_10GKR;
 293
 294        return reg;
 295}
 296
 297/**
 298 * linkmode_adv_to_mii_10gbt_adv_t
 299 * @advertising: the linkmode advertisement settings
 300 *
 301 * A small helper function that translates linkmode advertisement
 302 * settings to phy autonegotiation advertisements for the C45
 303 * 10GBASE-T AN CONTROL (7.32) register.
 304 */
 305static inline u32 linkmode_adv_to_mii_10gbt_adv_t(unsigned long *advertising)
 306{
 307        u32 result = 0;
 308
 309        if (linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
 310                              advertising))
 311                result |= MDIO_AN_10GBT_CTRL_ADV2_5G;
 312        if (linkmode_test_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT,
 313                              advertising))
 314                result |= MDIO_AN_10GBT_CTRL_ADV5G;
 315        if (linkmode_test_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
 316                              advertising))
 317                result |= MDIO_AN_10GBT_CTRL_ADV10G;
 318
 319        return result;
 320}
 321
 322/**
 323 * mii_10gbt_stat_mod_linkmode_lpa_t
 324 * @advertising: target the linkmode advertisement settings
 325 * @lpa: value of the C45 10GBASE-T AN STATUS register
 326 *
 327 * A small helper function that translates C45 10GBASE-T AN STATUS register bits
 328 * to linkmode advertisement settings. Other bits in advertising aren't changed.
 329 */
 330static inline void mii_10gbt_stat_mod_linkmode_lpa_t(unsigned long *advertising,
 331                                                     u32 lpa)
 332{
 333        linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
 334                         advertising, lpa & MDIO_AN_10GBT_STAT_LP2_5G);
 335        linkmode_mod_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT,
 336                         advertising, lpa & MDIO_AN_10GBT_STAT_LP5G);
 337        linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
 338                         advertising, lpa & MDIO_AN_10GBT_STAT_LP10G);
 339}
 340
 341int __mdiobus_read(struct mii_bus *bus, int addr, u32 regnum);
 342int __mdiobus_write(struct mii_bus *bus, int addr, u32 regnum, u16 val);
 343int __mdiobus_modify_changed(struct mii_bus *bus, int addr, u32 regnum,
 344                             u16 mask, u16 set);
 345
 346int mdiobus_read(struct mii_bus *bus, int addr, u32 regnum);
 347int mdiobus_read_nested(struct mii_bus *bus, int addr, u32 regnum);
 348int mdiobus_write(struct mii_bus *bus, int addr, u32 regnum, u16 val);
 349int mdiobus_write_nested(struct mii_bus *bus, int addr, u32 regnum, u16 val);
 350int mdiobus_modify(struct mii_bus *bus, int addr, u32 regnum, u16 mask,
 351                   u16 set);
 352
 353static inline u32 mdiobus_c45_addr(int devad, u16 regnum)
 354{
 355        return MII_ADDR_C45 | devad << MII_DEVADDR_C45_SHIFT | regnum;
 356}
 357
 358static inline int __mdiobus_c45_read(struct mii_bus *bus, int prtad, int devad,
 359                                     u16 regnum)
 360{
 361        return __mdiobus_read(bus, prtad, mdiobus_c45_addr(devad, regnum));
 362}
 363
 364static inline int __mdiobus_c45_write(struct mii_bus *bus, int prtad, int devad,
 365                                      u16 regnum, u16 val)
 366{
 367        return __mdiobus_write(bus, prtad, mdiobus_c45_addr(devad, regnum),
 368                               val);
 369}
 370
 371static inline int mdiobus_c45_read(struct mii_bus *bus, int prtad, int devad,
 372                                   u16 regnum)
 373{
 374        return mdiobus_read(bus, prtad, mdiobus_c45_addr(devad, regnum));
 375}
 376
 377static inline int mdiobus_c45_write(struct mii_bus *bus, int prtad, int devad,
 378                                    u16 regnum, u16 val)
 379{
 380        return mdiobus_write(bus, prtad, mdiobus_c45_addr(devad, regnum), val);
 381}
 382
 383int mdiobus_register_device(struct mdio_device *mdiodev);
 384int mdiobus_unregister_device(struct mdio_device *mdiodev);
 385bool mdiobus_is_registered_device(struct mii_bus *bus, int addr);
 386struct phy_device *mdiobus_get_phy(struct mii_bus *bus, int addr);
 387
 388/**
 389 * mdio_module_driver() - Helper macro for registering mdio drivers
 390 * @_mdio_driver: driver to register
 391 *
 392 * Helper macro for MDIO drivers which do not do anything special in module
 393 * init/exit. Each module may only use this macro once, and calling it
 394 * replaces module_init() and module_exit().
 395 */
 396#define mdio_module_driver(_mdio_driver)                                \
 397static int __init mdio_module_init(void)                                \
 398{                                                                       \
 399        return mdio_driver_register(&_mdio_driver);                     \
 400}                                                                       \
 401module_init(mdio_module_init);                                          \
 402static void __exit mdio_module_exit(void)                               \
 403{                                                                       \
 404        mdio_driver_unregister(&_mdio_driver);                          \
 405}                                                                       \
 406module_exit(mdio_module_exit)
 407
 408#endif /* __LINUX_MDIO_H__ */
 409