drivers/clk/sunxi-ng/ccu_mux.c

Source file repositories/reference/linux-study-clean/drivers/clk/sunxi-ng/ccu_mux.c

File Facts

System
Linux kernel
Corpus path
drivers/clk/sunxi-ng/ccu_mux.c
Extension
.c
Size
8202 bytes
Lines
325
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 (parent_index == cm->var_predivs[i].index) {
				u8 div;

				div = reg >> cm->var_predivs[i].shift;
				div &= (1 << cm->var_predivs[i].width) - 1;
				prediv = div + 1;
			}
	}

	return prediv;
}

unsigned long ccu_mux_helper_apply_prediv(struct ccu_common *common,
					  struct ccu_mux_internal *cm,
					  int parent_index,
					  unsigned long parent_rate)
{
	return parent_rate / ccu_mux_get_prediv(common, cm, parent_index);
}
EXPORT_SYMBOL_NS_GPL(ccu_mux_helper_apply_prediv, "SUNXI_CCU");

static unsigned long ccu_mux_helper_unapply_prediv(struct ccu_common *common,
					    struct ccu_mux_internal *cm,
					    int parent_index,
					    unsigned long parent_rate)
{
	return parent_rate * ccu_mux_get_prediv(common, cm, parent_index);
}

int ccu_mux_helper_determine_rate(struct ccu_common *common,
				  struct ccu_mux_internal *cm,
				  struct clk_rate_request *req,
				  int (*round)(struct ccu_mux_internal *,
					       struct clk_rate_request *,
					       void *),
				  void *data)
{
	unsigned long best_parent_rate = 0, best_rate = 0;
	struct clk_hw *best_parent, *hw = &common->hw;
	unsigned int i;
	int ret;

	if (clk_hw_get_flags(hw) & CLK_SET_RATE_NO_REPARENT) {
		struct clk_rate_request adj_req = *req;

		best_parent = clk_hw_get_parent(hw);
		best_parent_rate = clk_hw_get_rate(best_parent);

		adj_req.best_parent_hw = best_parent;
		adj_req.best_parent_rate = ccu_mux_helper_apply_prediv(common, cm, -1,
								       best_parent_rate);

		ret = round(cm, &adj_req, data);
		if (ret)
			return ret;

		best_rate = adj_req.rate;

		/*
		 * best_parent_rate might have been modified by our clock.
		 * Unapply the pre-divider if there's one, and give
		 * the actual frequency the parent needs to run at.
		 */
		best_parent_rate = ccu_mux_helper_unapply_prediv(common, cm, -1,
								 adj_req.best_parent_rate);

		goto out;
	}

	for (i = 0; i < clk_hw_get_num_parents(hw); i++) {
		struct clk_rate_request tmp_req = *req;
		unsigned long parent_rate;
		struct clk_hw *parent;

		parent = clk_hw_get_parent_by_index(hw, i);
		if (!parent)
			continue;

		parent_rate = ccu_mux_helper_apply_prediv(common, cm, i,
							  clk_hw_get_rate(parent));

		tmp_req.best_parent_hw = parent;
		tmp_req.best_parent_rate = parent_rate;

		ret = round(cm, &tmp_req, data);
		if (ret)
			continue;

		/*
		 * parent_rate might have been modified by our clock.

Annotation

Implementation Notes