drivers/clk/keystone/syscon-clk.c

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

File Facts

System
Linux kernel
Corpus path
drivers/clk/keystone/syscon-clk.c
Extension
.c
Size
6260 bytes
Lines
246
Domain
Driver Families
Bucket
drivers/clk
Inferred role
Driver Families: implementation source
Status
source 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 ti_syscon_gate_clk_priv {
	struct clk_hw hw;
	struct regmap *regmap;
	u32 reg;
	u32 idx;
};

struct ti_syscon_gate_clk_data {
	char *name;
	u32 offset;
	u32 bit_idx;
};

static struct
ti_syscon_gate_clk_priv *to_ti_syscon_gate_clk_priv(struct clk_hw *hw)
{
	return container_of(hw, struct ti_syscon_gate_clk_priv, hw);
}

static int ti_syscon_gate_clk_enable(struct clk_hw *hw)
{
	struct ti_syscon_gate_clk_priv *priv = to_ti_syscon_gate_clk_priv(hw);

	return regmap_write_bits(priv->regmap, priv->reg, priv->idx,
				 priv->idx);
}

static void ti_syscon_gate_clk_disable(struct clk_hw *hw)
{
	struct ti_syscon_gate_clk_priv *priv = to_ti_syscon_gate_clk_priv(hw);

	regmap_write_bits(priv->regmap, priv->reg, priv->idx, 0);
}

static int ti_syscon_gate_clk_is_enabled(struct clk_hw *hw)
{
	unsigned int val;
	struct ti_syscon_gate_clk_priv *priv = to_ti_syscon_gate_clk_priv(hw);

	regmap_read(priv->regmap, priv->reg, &val);

	return !!(val & priv->idx);
}

static const struct clk_ops ti_syscon_gate_clk_ops = {
	.enable		= ti_syscon_gate_clk_enable,
	.disable	= ti_syscon_gate_clk_disable,
	.is_enabled	= ti_syscon_gate_clk_is_enabled,
};

static struct clk_hw
*ti_syscon_gate_clk_register(struct device *dev, struct regmap *regmap,
			     const char *parent_name,
			     const struct ti_syscon_gate_clk_data *data)
{
	struct ti_syscon_gate_clk_priv *priv;
	struct clk_init_data init;
	char *name = NULL;
	int ret;

	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
	if (!priv)
		return ERR_PTR(-ENOMEM);

	init.ops = &ti_syscon_gate_clk_ops;
	if (parent_name) {
		name = kasprintf(GFP_KERNEL, "%s:%s", data->name, parent_name);
		init.name = name;
		init.parent_names = &parent_name;
		init.num_parents = 1;
		init.flags = CLK_SET_RATE_PARENT;
	} else {
		init.name = data->name;
		init.parent_names = NULL;
		init.num_parents = 0;
		init.flags = 0;
	}

	priv->regmap = regmap;
	priv->reg = data->offset;
	priv->idx = BIT(data->bit_idx);
	priv->hw.init = &init;

	ret = devm_clk_hw_register(dev, &priv->hw);

	if (name)
		kfree(init.name);

	if (ret)
		return ERR_PTR(ret);

Annotation

Implementation Notes