drivers/hwmon/pmbus/q54sj108a2.c

Source file repositories/reference/linux-study-clean/drivers/hwmon/pmbus/q54sj108a2.c

File Facts

System
Linux kernel
Corpus path
drivers/hwmon/pmbus/q54sj108a2.c
Extension
.c
Size
12092 bytes
Lines
436
Domain
Driver Families
Bucket
drivers/hwmon
Inferred role
Driver Families: operation-table or driver-model contract
Status
pattern 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

static const struct file_operations q54sj108a2_fops = {
	.llseek = noop_llseek,
	.read = q54sj108a2_debugfs_read,
	.write = q54sj108a2_debugfs_write,
	.open = simple_open,
};

static const struct i2c_device_id q54sj108a2_id[] = {
	{ .name = "q54sj108a2", .driver_data = q54sj108a2 },
	{ .name = "q54sn120a1", .driver_data = q54sj108a2 },
	{ .name = "q54sw120a7", .driver_data = q54sj108a2 },
	{ }
};

MODULE_DEVICE_TABLE(i2c, q54sj108a2_id);

static int q54sj108a2_probe(struct i2c_client *client)
{
	struct device *dev = &client->dev;
	u8 buf[I2C_SMBUS_BLOCK_MAX + 1];
	const struct i2c_device_id *mid;
	enum chips chip_id;
	int ret, i;
	struct dentry *debugfs;
	struct dentry *q54sj108a2_dir;
	struct q54sj108a2_data *psu;

	if (!i2c_check_functionality(client->adapter,
				     I2C_FUNC_SMBUS_BYTE_DATA |
				     I2C_FUNC_SMBUS_WORD_DATA |
				     I2C_FUNC_SMBUS_BLOCK_DATA))
		return -ENODEV;

	chip_id = (enum chips)(uintptr_t)i2c_get_match_data(client);

	ret = i2c_smbus_read_block_data(client, PMBUS_MFR_ID, buf);
	if (ret < 0) {
		dev_err(&client->dev, "Failed to read Manufacturer ID\n");
		return ret;
	}
	if (ret != 6 || strncmp(buf, "DELTA", 5)) {
		buf[ret] = '\0';
		dev_err(dev, "Unsupported Manufacturer ID '%s'\n", buf);
		return -ENODEV;
	}

	/*
	 * The chips support reading PMBUS_MFR_MODEL.
	 */
	ret = i2c_smbus_read_block_data(client, PMBUS_MFR_MODEL, buf);
	if (ret < 0) {
		dev_err(dev, "Failed to read Manufacturer Model\n");
		return ret;
	}
	buf[ret] = '\0';
	for (mid = q54sj108a2_id; mid->name[0]; mid++) {
		if (!strncasecmp(mid->name, buf, strlen(mid->name)))
			break;
	}
	if (!mid->name[0]) {
		dev_err(dev, "Unsupported Manufacturer Model '%s'\n", buf);
		return -ENODEV;
	}

	ret = i2c_smbus_read_block_data(client, PMBUS_MFR_REVISION, buf);
	if (ret < 0) {
		dev_err(dev, "Failed to read Manufacturer Revision\n");
		return ret;
	}
	/*
	 * accept manufacturer revision with optional NUL byte
	 */
	if (!(ret == 4 || ret == 5) || buf[0] != 'S') {
		buf[ret] = '\0';
		dev_err(dev, "Unsupported Manufacturer Revision '%s'\n", buf);
		return -ENODEV;
	}

	ret = pmbus_do_probe(client, &q54sj108a2_info[chip_id]);
	if (ret)
		return ret;

	psu = devm_kzalloc(&client->dev, sizeof(*psu), GFP_KERNEL);
	if (!psu)
		return 0;

	psu->client = client;

	debugfs = pmbus_get_debugfs_dir(client);

Annotation

Implementation Notes