1
  $   ˆÂÁ„-8/Àa–Ým_J*j"Tâ€Á9pM©‹FÿÄ ?÷     /* SPDX-License-Identifier: GPL-2.0-only */
/*
 * linux/mdio.h: definitions for MDIO (clause 45) transceivers
 * Copyright 2006-2009 Solarflare Communications Inc.
 */
#ifndef __LINUX_MDIO_H__
#define __LINUX_MDIO_H__

#include <uapi/linux/mdio.h>
#include <linux/bitfield.h>
#include <linux/mod_devicetable.h>

/* Or MII_ADDR_C45 into regnum for read/write on mii_bus to enable the 21 bit
 * IEEE 802.3ae clause 45 addressing mode used by 10GIGE phy chips.
 */
#define MII_ADDR_C45		(1<<30)
#define MII_DEVADDR_C45_SHIFT	16
#define MII_DEVADDR_C45_MASK	GENMASK(20, 16)
#define MII_REGADDR_C45_MASK	GENMASK(15, 0)

struct gpio_desc;
struct mii_bus;
struct reset_control;

/* Multiple levels of nesting are possible. However typically this is
 * limited to nested DSA like layer, a MUX layer, and the normal
 * user. Instead of trying to handle the general case, just define
 * these cases.
 */
enum mdio_mutex_lock_class {
	MDIO_MUTEX_NORMAL,
	MDIO_MUTEX_MUX,
	MDIO_MUTEX_NESTED,
};

struct mdio_device {
	struct device dev;

	struct mii_bus *bus;
	char modalias[MDIO_NAME_SIZE];

	int (*bus_match)(struct device *dev, const struct device_driver *drv);
	void (*device_free)(struct mdio_device *mdiodev);
	void (*device_remove)(struct mdio_device *mdiodev);

	/* Bus address of the MDIO device (0-31) */
	int addr;
	int flags;
	int reset_state;
	struct gpio_desc *reset_gpio;
	struct reset_control *reset_ctrl;
	unsigned int reset_assert_delay;
	unsigned int reset_deassert_delay;
};

#define to_mdio_device(__dev)	container_of_const(__dev, struct mdio_device, dev)

/* struct mdio_driver_common: Common to all MDIO drivers */
struct mdio_driver_common {
	struct device_driver driver;
	int flags;
};
#define MDIO_DEVICE_FLAG_PHY		1

#define to_mdio_common_driver(__drv_c)	container_of_const(__drv_c, struct mdio_driver_common,	\
							   driver)

/* struct mdio_driver: Generic MDIO driver */
struct mdio_driver {
	struct mdio_driver_common mdiodrv;

	/*
	 * Called during discovery.  Used to set
	 * up device-specific structures, if any
	 */
	int (*probe)(struct mdio_device *mdiodev);

	/* Clears up any memory if needed */
	void (*remove)(struct mdio_device *mdiodev);

	/* Quiesces the device on system shutdown, turns off interrupts etc */
	void (*shutdown)(struct mdio_device *mdiodev);
};

#define to_mdio_driver(__drv_m)	container_of_const(to_mdio_common_driver(__drv_m),	\
						   struct mdio_driver, mdiodrv)

/* device driver data */
static inline void mdiodev_set_drvdata(struct mdio_device *mdio, void *data)
{
	dev_set_drvdata(&mdio->dev, data);
}

static inline void *mdiodev_get_drvdata(struct mdio_device *mdio)
{
	return dev_get_drvdata(&mdio->dev);
}

void mdio_device_free(struct mdio_device *mdiodev);
struct mdio_device *mdio_device_create(struct mii_bus *bus, int addr);
int mdio_device_register(struct mdio_device *mdiodev);
void mdio_device_remove(struct mdio_device *mdiodev);
void mdio_device_reset(struct mdio_device *mdiodev, int value);
int mdio_driver_register(struct mdio_driver *drv);
void mdio_driver_unregister(struct mdio_driver *drv);

static inline void mdio_device_get(struct mdio_device *mdiodev)
{
	get_device(&mdiodev->dev);
}

static inline void mdio_device_put(struct mdio_device *mdiodev)
{
	mdio_device_free(mdiodev);
}

static inline bool mdio_phy_id_is_c45(int phy_id)
{
	return (phy_id & MDIO_PHY_ID_C45) && !(phy_id & ~MDIO_PHY_ID_C45_MASK);
}

static inline __u16 mdio_phy_id_prtad(int phy_id)
{
	return (phy_id & MDIO_PHY_ID_PRTAD) >> 5;
}

static inline __u16 mdio_phy_id_devad(int phy_id)
{
	return phy_id & MDIO_PHY_ID_DEVAD;
}

/**
 * struct mdio_if_info - Ethernet controller MDIO interface
 * @prtad: PRTAD of the PHY (%MDIO_PRTAD_NONE if not present/unknown)
 * @mmds: Mask of MMDs expected to be present in the PHY.  This must be
 *	non-zero unless @prtad = %MDIO_PRTAD_NONE.
 * @mode_support: MDIO modes supported.  If %MDIO_SUPPORTS_C22 is set then
 *	MII register access will be passed through with @devad =
 *	%MDIO_DEVAD_NONE.  If %MDIO_EMULATE_C22 is set then access to
 *