drivers/clk/qcom/clk-branch.c

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

File Facts

System
Linux kernel
Corpus path
drivers/clk/qcom/clk-branch.c
Extension
.c
Size
4947 bytes
Lines
201
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

while (count-- > 0) {
			if (check_halt(br, enabling))
				return 0;
			udelay(1);
		}
		WARN(1, "%s status stuck at 'o%s'", name,
				enabling ? "ff" : "n");
		return -EBUSY;
	}
	return 0;
}

static int clk_branch_toggle(struct clk_hw *hw, bool en,
		bool (check_halt)(const struct clk_branch *, bool))
{
	struct clk_branch *br = to_clk_branch(hw);
	int ret;

	if (en) {
		ret = clk_enable_regmap(hw);
		if (ret)
			return ret;
	} else {
		clk_disable_regmap(hw);
	}

	return clk_branch_wait(br, en, check_halt);
}

static int clk_branch_enable(struct clk_hw *hw)
{
	return clk_branch_toggle(hw, true, clk_branch_check_halt);
}

static void clk_branch_disable(struct clk_hw *hw)
{
	clk_branch_toggle(hw, false, clk_branch_check_halt);
}

const struct clk_ops clk_branch_ops = {
	.enable = clk_branch_enable,
	.disable = clk_branch_disable,
	.is_enabled = clk_is_enabled_regmap,
};
EXPORT_SYMBOL_GPL(clk_branch_ops);

static int clk_branch2_enable(struct clk_hw *hw)
{
	return clk_branch_toggle(hw, true, clk_branch2_check_halt);
}

static void clk_branch2_disable(struct clk_hw *hw)
{
	clk_branch_toggle(hw, false, clk_branch2_check_halt);
}

static int clk_branch2_mem_enable(struct clk_hw *hw)
{
	struct clk_mem_branch *mem_br = to_clk_mem_branch(hw);
	struct clk_branch branch = mem_br->branch;
	u32 val;
	int ret;

	regmap_assign_bits(branch.clkr.regmap, mem_br->mem_enable_reg,
			   mem_br->mem_enable_mask, !mem_br->mem_enable_invert);

	ret = regmap_read_poll_timeout(branch.clkr.regmap, mem_br->mem_ack_reg,
				       val, val & mem_br->mem_enable_ack_mask, 0, 200);
	if (ret) {
		WARN(1, "%s mem enable failed\n", clk_hw_get_name(&branch.clkr.hw));
		return ret;
	}

	return clk_branch2_enable(hw);
}

static void clk_branch2_mem_disable(struct clk_hw *hw)
{
	struct clk_mem_branch *mem_br = to_clk_mem_branch(hw);

	regmap_assign_bits(mem_br->branch.clkr.regmap, mem_br->mem_enable_reg,
			   mem_br->mem_enable_mask, mem_br->mem_enable_invert);

	return clk_branch2_disable(hw);
}

const struct clk_ops clk_branch2_mem_ops = {
	.enable = clk_branch2_mem_enable,
	.disable = clk_branch2_mem_disable,
	.is_enabled = clk_is_enabled_regmap,

Annotation

Implementation Notes