drivers/clk/mediatek/clk-pll.c

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

File Facts

System
Linux kernel
Corpus path
drivers/clk/mediatek/clk-pll.c
Extension
.c
Size
11627 bytes
Lines
504
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

if (!IS_ERR_OR_NULL(clk_data->hws[pll->id])) {
			pr_warn("%pOF: Trying to register duplicate clock ID: %d\n",
				dev->of_node, pll->id);
			continue;
		}

		hw = mtk_clk_register_pll(dev, pll, base);

		if (IS_ERR(hw)) {
			pr_err("Failed to register clk %s: %pe\n", pll->name,
			       hw);
			goto err;
		}

		clk_data->hws[pll->id] = hw;
	}

	return 0;

err:
	while (--i >= 0) {
		const struct mtk_pll_data *pll = &plls[i];

		mtk_clk_unregister_pll(clk_data->hws[pll->id]);
		clk_data->hws[pll->id] = ERR_PTR(-ENOENT);
	}

	iounmap(base);

	return PTR_ERR(hw);
}
EXPORT_SYMBOL_GPL(mtk_clk_register_plls);

__iomem void *mtk_clk_pll_get_base(struct clk_hw *hw,
				   const struct mtk_pll_data *data)
{
	struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);

	return pll->base_addr - data->reg;
}

void mtk_clk_unregister_plls(const struct mtk_pll_data *plls, int num_plls,
			     struct clk_hw_onecell_data *clk_data)
{
	__iomem void *base = NULL;
	int i;

	if (!clk_data)
		return;

	for (i = num_plls; i > 0; i--) {
		const struct mtk_pll_data *pll = &plls[i - 1];

		if (IS_ERR_OR_NULL(clk_data->hws[pll->id]))
			continue;

		/*
		 * This is quite ugly but unfortunately the clks don't have
		 * any device tied to them, so there's no place to store the
		 * pointer to the I/O region base address. We have to fetch
		 * it from one of the registered clks.
		 */
		base = mtk_clk_pll_get_base(clk_data->hws[pll->id], pll);

		mtk_clk_unregister_pll(clk_data->hws[pll->id]);
		clk_data->hws[pll->id] = ERR_PTR(-ENOENT);
	}

	iounmap(base);
}
EXPORT_SYMBOL_GPL(mtk_clk_unregister_plls);

MODULE_LICENSE("GPL");

Annotation

Implementation Notes