drivers/clk/qcom/clk-rcg.c

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

File Facts

System
Linux kernel
Corpus path
drivers/clk/qcom/clk-rcg.c
Extension
.c
Size
21660 bytes
Lines
914
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 frac_entry {
	int num;
	int den;
};

static const struct frac_entry pixel_table[] = {
	{ 1, 1 },
	{ 1, 2 },
	{ 1, 3 },
	{ 3, 16 },
	{ }
};

static int clk_rcg_pixel_determine_rate(struct clk_hw *hw,
		struct clk_rate_request *req)
{
	int delta = 100000;
	const struct frac_entry *frac = pixel_table;
	unsigned long request, src_rate;

	for (; frac->num; frac++) {
		request = (req->rate * frac->den) / frac->num;

		src_rate = clk_hw_round_rate(req->best_parent_hw, request);

		if ((src_rate < (request - delta)) ||
			(src_rate > (request + delta)))
			continue;

		req->best_parent_rate = src_rate;
		req->rate = (src_rate * frac->num) / frac->den;
		return 0;
	}

	return -EINVAL;
}

static int clk_rcg_pixel_set_rate(struct clk_hw *hw, unsigned long rate,
				unsigned long parent_rate)
{
	struct clk_rcg *rcg = to_clk_rcg(hw);
	int delta = 100000;
	const struct frac_entry *frac = pixel_table;
	unsigned long request;
	struct freq_tbl f = { 0 };
	u32 ns, src;
	int i, ret, num_parents = clk_hw_get_num_parents(hw);

	ret = regmap_read(rcg->clkr.regmap, rcg->ns_reg, &ns);
	if (ret)
		return ret;

	src = ns_to_src(&rcg->s, ns);

	for (i = 0; i < num_parents; i++) {
		if (src == rcg->s.parent_map[i].cfg) {
			f.src = rcg->s.parent_map[i].src;
			break;
		}
	}

	/* bypass the pre divider */
	f.pre_div = 1;

	/* let us find appropriate m/n values for this */
	for (; frac->num; frac++) {
		request = (rate * frac->den) / frac->num;

		if ((parent_rate < (request - delta)) ||
			(parent_rate > (request + delta)))
			continue;

		f.m = frac->num;
		f.n = frac->den;

		return __clk_rcg_set_rate(rcg, &f);
	}

	return -EINVAL;
}

static int clk_rcg_pixel_set_rate_and_parent(struct clk_hw *hw,
		unsigned long rate, unsigned long parent_rate, u8 index)
{
	return clk_rcg_pixel_set_rate(hw, rate, parent_rate);
}

static int clk_rcg_esc_determine_rate(struct clk_hw *hw,
		struct clk_rate_request *req)
{

Annotation

Implementation Notes