drivers/firmware/arm_scmi/driver.c

Source file repositories/reference/linux-study-clean/drivers/firmware/arm_scmi/driver.c

File Facts

System
Linux kernel
Corpus path
drivers/firmware/arm_scmi/driver.c
Extension
.c
Size
101389 bytes
Lines
3564
Domain
Driver Families
Bucket
drivers/firmware
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 fops_reset_counts = {
	.owner = THIS_MODULE,
	.open = simple_open,
	.write = reset_all_on_write,
};

static void scmi_debugfs_counters_setup(struct scmi_debug_info *dbg,
					struct dentry *trans)
{
	struct dentry *counters;
	int idx;

	counters = debugfs_create_dir("counters", trans);

	for (idx = 0; idx < SCMI_DEBUG_COUNTERS_LAST; idx++)
		debugfs_create_atomic_t(dbg_counter_strs[idx], 0600, counters,
					&dbg->counters[idx]);

	debugfs_create_file("reset", 0200, counters, dbg, &fops_reset_counts);
}

static void scmi_debugfs_common_cleanup(void *d)
{
	struct scmi_debug_info *dbg = d;

	if (!dbg)
		return;

	debugfs_remove_recursive(dbg->top_dentry);
	kfree(dbg->name);
	kfree(dbg->type);
}

static struct scmi_debug_info *scmi_debugfs_common_setup(struct scmi_info *info)
{
	char top_dir[16];
	struct dentry *trans, *top_dentry;
	struct scmi_debug_info *dbg;
	const char *c_ptr = NULL;

	dbg = devm_kzalloc(info->dev, sizeof(*dbg), GFP_KERNEL);
	if (!dbg)
		return NULL;

	dbg->name = kstrdup(of_node_full_name(info->dev->of_node), GFP_KERNEL);
	if (!dbg->name) {
		devm_kfree(info->dev, dbg);
		return NULL;
	}

	of_property_read_string(info->dev->of_node, "compatible", &c_ptr);
	dbg->type = kstrdup(c_ptr, GFP_KERNEL);
	if (!dbg->type) {
		kfree(dbg->name);
		devm_kfree(info->dev, dbg);
		return NULL;
	}

	snprintf(top_dir, 16, "%d", info->id);
	top_dentry = debugfs_create_dir(top_dir, scmi_top_dentry);
	trans = debugfs_create_dir("transport", top_dentry);

	dbg->is_atomic = info->desc->atomic_enabled &&
				is_transport_polling_capable(info->desc);

	debugfs_create_str("instance_name", 0400, top_dentry,
			   (char **)&dbg->name);

	debugfs_create_u32("atomic_threshold_us", 0400, top_dentry,
			   (u32 *)&info->desc->atomic_threshold);

	debugfs_create_str("type", 0400, trans, (char **)&dbg->type);

	debugfs_create_bool("is_atomic", 0400, trans, &dbg->is_atomic);

	debugfs_create_u32("max_rx_timeout_ms", 0400, trans,
			   (u32 *)&info->desc->max_rx_timeout_ms);

	debugfs_create_u32("max_msg_size", 0400, trans,
			   (u32 *)&info->desc->max_msg_size);

	debugfs_create_u32("tx_max_msg", 0400, trans,
			   (u32 *)&info->tx_minfo.max_msg);

	debugfs_create_u32("rx_max_msg", 0400, trans,
			   (u32 *)&info->rx_minfo.max_msg);

	if (IS_ENABLED(CONFIG_ARM_SCMI_DEBUG_COUNTERS))
		scmi_debugfs_counters_setup(dbg, trans);

Annotation

Implementation Notes