/* SPDX-License-Identifier: GPL-2.0-or-later */

#ifndef __PHY_PORT_H
#define __PHY_PORT_H

#include <linux/ethtool.h>
#include <linux/types.h>
#include <linux/phy.h>

struct phy_port;


enum phy_port_parent {
	PHY_PORT_PHY,
};

struct phy_port_ops {
	
	void (*link_up)(struct phy_port *port);
	void (*link_down)(struct phy_port *port);

	
	int (*configure_mii)(struct phy_port *port, bool enable, phy_interface_t interface);
};


struct phy_port {
	struct list_head head;
	enum phy_port_parent parent_type;
	union {
		struct phy_device *phy;
	};

	const struct phy_port_ops *ops;

	int pairs;
	unsigned long mediums;
	__ETHTOOL_DECLARE_LINK_MODE_MASK(supported);
	DECLARE_PHY_INTERFACE_MASK(interfaces);

	unsigned int not_described:1;
	unsigned int active:1;
	unsigned int is_mii:1;
	unsigned int is_sfp:1;
};

struct phy_port *phy_port_alloc(void);
void phy_port_destroy(struct phy_port *port);

static inline struct phy_device *port_phydev(struct phy_port *port)
{
	return port->phy;
}

struct phy_port *phy_of_parse_port(struct device_node *dn);

static inline bool phy_port_is_copper(struct phy_port *port)
{
	return port->mediums == BIT(ETHTOOL_LINK_MEDIUM_BASET);
}

static inline bool phy_port_is_fiber(struct phy_port *port)
{
	return !!(port->mediums & ETHTOOL_MEDIUM_FIBER_BITS);
}

void phy_port_update_supported(struct phy_port *port);
int phy_port_restrict_mediums(struct phy_port *port, unsigned long mediums);

int phy_port_get_type(struct phy_port *port);

#endif
