drivers/net/phy/mxl-gpy.c

Source file repositories/reference/linux-study-clean/drivers/net/phy/mxl-gpy.c

File Facts

System
Linux kernel
Corpus path
drivers/net/phy/mxl-gpy.c
Extension
.c
Size
41461 bytes
Lines
1504
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct gpy_priv {
	/* serialize mailbox acesses */
	struct mutex mbox_lock;

	u8 fw_major;
	u8 fw_minor;
	u32 wolopts;
	u64 rx_errors;

	/* It takes 3 seconds to fully switch out of loopback mode before
	 * it can safely re-enter loopback mode. Record the time when
	 * loopback is disabled. Check and wait if necessary before loopback
	 * is enabled.
	 */
	u64 lb_dis_to;
};

static const struct {
	int major;
	int minor;
} ver_need_sgmii_reaneg[] = {
	{7, 0x6D},
	{8, 0x6D},
	{9, 0x73},
};

#if IS_ENABLED(CONFIG_HWMON)
/* The original translation formulae of the temperature (in degrees of Celsius)
 * are as follows:
 *
 *   T = -2.5761e-11*(N^4) + 9.7332e-8*(N^3) + -1.9165e-4*(N^2) +
 *       3.0762e-1*(N^1) + -5.2156e1
 *
 * where [-52.156, 137.961]C and N = [0, 1023].
 *
 * They must be accordingly altered to be suitable for the integer arithmetics.
 * The technique is called 'factor redistribution', which just makes sure the
 * multiplications and divisions are made so to have a result of the operations
 * within the integer numbers limit. In addition we need to translate the
 * formulae to accept millidegrees of Celsius. Here what it looks like after
 * the alterations:
 *
 *   T = -25761e-12*(N^4) + 97332e-9*(N^3) + -191650e-6*(N^2) +
 *       307620e-3*(N^1) + -52156
 *
 * where T = [-52156, 137961]mC and N = [0, 1023].
 */
static const struct polynomial poly_N_to_temp = {
	.terms = {
		{4,  -25761, 1000, 1},
		{3,   97332, 1000, 1},
		{2, -191650, 1000, 1},
		{1,  307620, 1000, 1},
		{0,  -52156,    1, 1}
	}
};

static int gpy_hwmon_read(struct device *dev,
			  enum hwmon_sensor_types type,
			  u32 attr, int channel, long *value)
{
	struct phy_device *phydev = dev_get_drvdata(dev);
	int ret;

	ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, VSPEC1_TEMP_STA);
	if (ret < 0)
		return ret;
	if (!ret)
		return -ENODATA;

	*value = polynomial_calc(&poly_N_to_temp,
				 FIELD_GET(VSPEC1_TEMP_STA_DATA, ret));

	return 0;
}

static int mxl862x2_hwmon_read(struct device *dev,
			       enum hwmon_sensor_types type,
			       u32 attr, int channel, long *value)
{
	struct phy_device *phydev = dev_get_drvdata(dev);
	long tmp;
	int ret;

	ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, VSPEC1_TEMP_STA);
	if (ret < 0)
		return ret;
	if (!ret)
		return -ENODATA;

Annotation

Implementation Notes