drivers/hwmon/pmbus/ucd9000.c

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

File Facts

System
Linux kernel
Corpus path
drivers/hwmon/pmbus/ucd9000.c
Extension
.c
Size
16176 bytes
Lines
649
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 ucd9000_debugfs_show_mfr_status_fops = {
	.llseek = noop_llseek,
	.read = ucd9000_debugfs_read_mfr_status,
	.open = simple_open,
};

static int ucd9000_init_debugfs(struct i2c_client *client,
				const struct i2c_device_id *mid,
				struct ucd9000_data *data)
{
	struct dentry *debugfs;
	struct ucd9000_debugfs_entry *entries;
	int i, gpi_count;
	char name[UCD9000_DEBUGFS_NAME_LEN];

	debugfs = pmbus_get_debugfs_dir(client);
	if (!debugfs)
		return -ENOENT;

	data->debugfs = debugfs_create_dir(client->name, debugfs);

	/*
	 * Of the chips this driver supports, only the UCD9090, UCD90160,
	 * UCD90320, and UCD90910 report GPI faults in their MFR_STATUS
	 * register, so only create the GPI fault debugfs attributes for those
	 * chips.
	 */
	if (mid->driver_data == ucd9090 || mid->driver_data == ucd90160 ||
	    mid->driver_data == ucd90320 || mid->driver_data == ucd90910) {
		gpi_count = mid->driver_data == ucd90320 ? UCD90320_GPI_COUNT
							 : UCD9000_GPI_COUNT;
		entries = devm_kcalloc(&client->dev,
				       gpi_count, sizeof(*entries),
				       GFP_KERNEL);
		if (!entries)
			return -ENOMEM;

		for (i = 0; i < gpi_count; i++) {
			entries[i].client = client;
			entries[i].index = i;
			scnprintf(name, UCD9000_DEBUGFS_NAME_LEN,
				  "gpi%d_alarm", i + 1);
			debugfs_create_file(name, 0444, data->debugfs,
					    &entries[i],
					    &ucd9000_debugfs_mfr_status_bit);
		}
	}

	scnprintf(name, UCD9000_DEBUGFS_NAME_LEN, "mfr_status");
	debugfs_create_file(name, 0444, data->debugfs, client,
			    &ucd9000_debugfs_show_mfr_status_fops);

	return 0;
}
#else
static int ucd9000_init_debugfs(struct i2c_client *client,
				const struct i2c_device_id *mid,
				struct ucd9000_data *data)
{
	return 0;
}
#endif /* CONFIG_DEBUG_FS */

static int ucd9000_probe(struct i2c_client *client)
{
	u8 block_buffer[I2C_SMBUS_BLOCK_MAX + 1];
	struct ucd9000_data *data;
	struct pmbus_driver_info *info;
	const struct i2c_device_id *mid;
	enum chips chip;
	int i, ret;

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

	ret = i2c_smbus_read_block_data(client, UCD9000_DEVICE_ID,
					block_buffer);
	if (ret < 0) {
		dev_err(&client->dev, "Failed to read device ID\n");
		return ret;
	}
	block_buffer[ret] = '\0';
	dev_info(&client->dev, "Device ID %s\n", block_buffer);

	for (mid = ucd9000_id; mid->name[0]; mid++) {
		if (!strncasecmp(mid->name, block_buffer, strlen(mid->name)))
			break;
	}

Annotation

Implementation Notes