drivers/clk/clkdev.c

Source file repositories/reference/linux-study-clean/drivers/clk/clkdev.c

File Facts

System
Linux kernel
Corpus path
drivers/clk/clkdev.c
Extension
.c
Size
9954 bytes
Lines
419
Domain
Driver Families
Bucket
drivers/clk
Inferred role
Driver Families: exported/initcall integration point
Status
integration 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 clk_lookup_alloc {
	struct clk_lookup cl;
	char	dev_id[MAX_DEV_ID];
	char	con_id[MAX_CON_ID];
};

static __printf(3, 0) struct clk_lookup * __ref
vclkdev_alloc(struct clk_hw *hw, const char *con_id, const char *dev_fmt,
	va_list ap)
{
	struct clk_lookup_alloc *cla;
	struct va_format vaf;
	const char *failure;
	va_list ap_copy;
	size_t max_size;
	ssize_t res;

	cla = kzalloc_obj(*cla);
	if (!cla)
		return NULL;

	va_copy(ap_copy, ap);

	cla->cl.clk_hw = hw;
	if (con_id) {
		res = strscpy(cla->con_id, con_id, sizeof(cla->con_id));
		if (res < 0) {
			max_size = sizeof(cla->con_id);
			failure = "connection";
			goto fail;
		}
		cla->cl.con_id = cla->con_id;
	}

	if (dev_fmt) {
		res = vsnprintf(cla->dev_id, sizeof(cla->dev_id), dev_fmt, ap);
		if (res >= sizeof(cla->dev_id)) {
			max_size = sizeof(cla->dev_id);
			failure = "device";
			goto fail;
		}
		cla->cl.dev_id = cla->dev_id;
	}

	va_end(ap_copy);

	return &cla->cl;

fail:
	if (dev_fmt)
		vaf.fmt = dev_fmt;
	else
		vaf.fmt = "null-device";
	vaf.va = &ap_copy;
	pr_err("%pV:%s: %s ID is greater than %zu\n",
	       &vaf, con_id, failure, max_size);
	va_end(ap_copy);

	/*
	 * Don't fail in this case, but as the entry won't ever match just
	 * fill it with something that also won't match.
	 */
	strscpy(cla->con_id, "bad", sizeof(cla->con_id));
	strscpy(cla->dev_id, "bad", sizeof(cla->dev_id));

	return &cla->cl;
}

static __printf(3, 0) struct clk_lookup *
vclkdev_create(struct clk_hw *hw, const char *con_id, const char *dev_fmt,
	va_list ap)
{
	struct clk_lookup *cl;

	cl = vclkdev_alloc(hw, con_id, dev_fmt, ap);
	if (cl)
		__clkdev_add(cl);

	return cl;
}

/**
 * clkdev_create - allocate and add a clkdev lookup structure
 * @clk: struct clk to associate with all clk_lookups
 * @con_id: connection ID string on device
 * @dev_fmt: format string describing device name
 *
 * Returns a clk_lookup structure, which can be later unregistered and
 * freed.
 */

Annotation

Implementation Notes