drivers/hwmon/pmbus/fsp-3y.c

Source file repositories/reference/linux-study-clean/drivers/hwmon/pmbus/fsp-3y.c

File Facts

System
Linux kernel
Corpus path
drivers/hwmon/pmbus/fsp-3y.c
Extension
.c
Size
7391 bytes
Lines
294
Domain
Driver Families
Bucket
drivers/hwmon
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 fsp3y_data {
	struct pmbus_driver_info info;
	int chip;
	int page;

	bool vout_linear_11;
};

#define to_fsp3y_data(x) container_of(x, struct fsp3y_data, info)

static int page_log_to_page_real(int page_log, enum chips chip)
{
	switch (chip) {
	case ym2151e:
		switch (page_log) {
		case YM2151_PAGE_12V_LOG:
			return YM2151_PAGE_12V_REAL;
		case YM2151_PAGE_5VSB_LOG:
			return YM2151_PAGE_5VSB_REAL;
		}
		return -EINVAL;
	case yh5151e:
		switch (page_log) {
		case YH5151E_PAGE_12V_LOG:
			return YH5151E_PAGE_12V_REAL;
		case YH5151E_PAGE_5V_LOG:
			return YH5151E_PAGE_5V_REAL;
		case YH5151E_PAGE_3V3_LOG:
			return YH5151E_PAGE_3V3_REAL;
		}
		return -EINVAL;
	}

	return -EINVAL;
}

static int set_page(struct i2c_client *client, int page_log)
{
	const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
	struct fsp3y_data *data = to_fsp3y_data(info);
	int rv;
	int page_real;

	if (page_log < 0)
		return 0;

	page_real = page_log_to_page_real(page_log, data->chip);
	if (page_real < 0)
		return page_real;

	if (data->page != page_real) {
		rv = i2c_smbus_write_byte_data(client, PMBUS_PAGE, page_real);
		if (rv < 0)
			return rv;

		data->page = page_real;

		/*
		 * Testing showed that the device has a timing issue. After
		 * setting a page, it takes a while, before the device actually
		 * gives the correct values from the correct page. 20 ms was
		 * tested to be enough to not give wrong values (15 ms wasn't
		 * enough).
		 */
		usleep_range(20000, 30000);
	}

	return 0;
}

static int fsp3y_read_byte_data(struct i2c_client *client, int page, int reg)
{
	const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
	struct fsp3y_data *data = to_fsp3y_data(info);
	int rv;

	/*
	 * Inject an exponent for non-compliant YH5151-E.
	 */
	if (data->vout_linear_11 && reg == PMBUS_VOUT_MODE)
		return 0x1A;

	rv = set_page(client, page);
	if (rv < 0)
		return rv;

	return i2c_smbus_read_byte_data(client, reg);
}

static int fsp3y_read_word_data(struct i2c_client *client, int page, int phase, int reg)

Annotation

Implementation Notes