drivers/clk/clk-devres.c

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

File Facts

System
Linux kernel
Corpus path
drivers/clk/clk-devres.c
Extension
.c
Size
7651 bytes
Lines
345
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 devm_clk_state {
	struct clk *clk;
	void (*exit)(struct clk *clk);
};

static void devm_clk_release(struct device *dev, void *res)
{
	struct devm_clk_state *state = res;

	if (state->exit)
		state->exit(state->clk);

	clk_put(state->clk);
}

static struct clk *__devm_clk_get(struct device *dev, const char *id,
				  struct clk *(*get)(struct device *dev, const char *id),
				  int (*init)(struct clk *clk),
				  void (*exit)(struct clk *clk))
{
	struct devm_clk_state *state;
	struct clk *clk;
	int ret;

	state = devres_alloc(devm_clk_release, sizeof(*state), GFP_KERNEL);
	if (!state)
		return ERR_PTR(-ENOMEM);

	clk = get(dev, id);
	if (IS_ERR(clk)) {
		ret = PTR_ERR(clk);
		goto err_clk_get;
	}

	if (init) {
		ret = init(clk);
		if (ret)
			goto err_clk_init;
	}

	state->clk = clk;
	state->exit = exit;

	devres_add(dev, state);

	return clk;

err_clk_init:

	clk_put(clk);
err_clk_get:

	devres_free(state);
	return ERR_PTR(ret);
}

struct clk *devm_clk_get(struct device *dev, const char *id)
{
	return __devm_clk_get(dev, id, clk_get, NULL, NULL);
}
EXPORT_SYMBOL(devm_clk_get);

struct clk *devm_clk_get_prepared(struct device *dev, const char *id)
{
	return __devm_clk_get(dev, id, clk_get, clk_prepare, clk_unprepare);
}
EXPORT_SYMBOL_GPL(devm_clk_get_prepared);

struct clk *devm_clk_get_enabled(struct device *dev, const char *id)
{
	return __devm_clk_get(dev, id, clk_get,
			      clk_prepare_enable, clk_disable_unprepare);
}
EXPORT_SYMBOL_GPL(devm_clk_get_enabled);

struct clk *devm_clk_get_optional(struct device *dev, const char *id)
{
	return __devm_clk_get(dev, id, clk_get_optional, NULL, NULL);
}
EXPORT_SYMBOL(devm_clk_get_optional);

struct clk *devm_clk_get_optional_prepared(struct device *dev, const char *id)
{
	return __devm_clk_get(dev, id, clk_get_optional,
			      clk_prepare, clk_unprepare);
}
EXPORT_SYMBOL_GPL(devm_clk_get_optional_prepared);

struct clk *devm_clk_get_optional_enabled(struct device *dev, const char *id)
{

Annotation

Implementation Notes