drivers/net/pse-pd/tps23881.c

Source file repositories/reference/linux-study-clean/drivers/net/pse-pd/tps23881.c

File Facts

System
Linux kernel
Corpus path
drivers/net/pse-pd/tps23881.c
Extension
.c
Size
38734 bytes
Lines
1563
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 tps23881_port_desc {
	u8 chan[2];
	bool is_4p;
	int pw_pol;
	bool exist;
};

struct tps23881_priv {
	struct i2c_client *client;
	struct pse_controller_dev pcdev;
	struct device_node *np;
	struct tps23881_port_desc port[TPS23881_MAX_CHANS];
};

static struct tps23881_priv *to_tps23881_priv(struct pse_controller_dev *pcdev)
{
	return container_of(pcdev, struct tps23881_priv, pcdev);
}

/*
 * Helper to extract a value from a u16 register value, which is made of two
 * u8 registers. The function calculates the bit offset based on the channel
 * and extracts the relevant bits using a provided field mask.
 *
 * @param reg_val: The u16 register value (composed of two u8 registers).
 * @param chan: The channel number (0-7).
 * @param field_offset: The base bit offset to apply (e.g., 0 or 4).
 * @param field_mask: The mask to apply to extract the required bits.
 * @return: The extracted value for the specific channel.
 */
static u16 tps23881_calc_val(u16 reg_val, u8 chan, u8 field_offset,
			     u16 field_mask)
{
	if (chan >= 4)
		reg_val >>= 8;

	return (reg_val >> field_offset) & field_mask;
}

/*
 * Helper to combine individual channel values into a u16 register value.
 * The function sets the value for a specific channel in the appropriate
 * position.
 *
 * @param reg_val: The current u16 register value.
 * @param chan: The channel number (0-7).
 * @param field_offset: The base bit offset to apply (e.g., 0 or 4).
 * @param field_mask: The mask to apply for the field (e.g., 0x0F).
 * @param field_val: The value to set for the specific channel (masked by
 *                   field_mask).
 * @return: The updated u16 register value with the channel value set.
 */
static u16 tps23881_set_val(u16 reg_val, u8 chan, u8 field_offset,
			    u16 field_mask, u16 field_val)
{
	field_val &= field_mask;

	if (chan < 4) {
		reg_val &= ~(field_mask << field_offset);
		reg_val |= (field_val << field_offset);
	} else {
		reg_val &= ~(field_mask << (field_offset + 8));
		reg_val |= (field_val << (field_offset + 8));
	}

	return reg_val;
}

static int
tps23881_pi_set_pw_pol_limit(struct tps23881_priv *priv, int id, u8 pw_pol,
			     bool is_4p)
{
	struct i2c_client *client = priv->client;
	int ret, reg;
	u16 val;
	u8 chan;

	chan = priv->port[id].chan[0];
	if (!is_4p) {
		reg = TPS23881_REG_2PAIR_POL1 + (chan % 4);
	} else {
		/* One chan is enough to configure the 4p PI power limit */
		if ((chan % 4) < 2)
			reg = TPS23881_REG_4PAIR_POL1;
		else
			reg = TPS23881_REG_4PAIR_POL1 + 1;
	}

	ret = i2c_smbus_read_word_data(client, reg);
	if (ret < 0)

Annotation

Implementation Notes