drivers/clk/zynqmp/clk-mux-zynqmp.c

Source file repositories/reference/linux-study-clean/drivers/clk/zynqmp/clk-mux-zynqmp.c

File Facts

System
Linux kernel
Corpus path
drivers/clk/zynqmp/clk-mux-zynqmp.c
Extension
.c
Size
4295 bytes
Lines
168
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 zynqmp_clk_mux {
	struct clk_hw hw;
	u8 flags;
	u32 clk_id;
};

#define to_zynqmp_clk_mux(_hw) container_of(_hw, struct zynqmp_clk_mux, hw)

/**
 * zynqmp_clk_mux_get_parent() - Get parent of clock
 * @hw:		handle between common and hardware-specific interfaces
 *
 * Return: Parent index on success or number of parents in case of error
 */
static u8 zynqmp_clk_mux_get_parent(struct clk_hw *hw)
{
	struct zynqmp_clk_mux *mux = to_zynqmp_clk_mux(hw);
	const char *clk_name = clk_hw_get_name(hw);
	u32 clk_id = mux->clk_id;
	u32 val;
	int ret;

	ret = zynqmp_pm_clock_getparent(clk_id, &val);

	if (ret) {
		pr_debug("%s() getparent failed for clock: %s, ret = %d\n",
			 __func__, clk_name, ret);
		/*
		 * clk_core_get_parent_by_index() takes num_parents as incorrect
		 * index which is exactly what I want to return here
		 */
		return clk_hw_get_num_parents(hw);
	}

	return val;
}

/**
 * zynqmp_clk_mux_set_parent() - Set parent of clock
 * @hw:		handle between common and hardware-specific interfaces
 * @index:	Parent index
 *
 * Return: 0 on success else error+reason
 */
static int zynqmp_clk_mux_set_parent(struct clk_hw *hw, u8 index)
{
	struct zynqmp_clk_mux *mux = to_zynqmp_clk_mux(hw);
	const char *clk_name = clk_hw_get_name(hw);
	u32 clk_id = mux->clk_id;
	int ret;

	ret = zynqmp_pm_clock_setparent(clk_id, index);

	if (ret)
		pr_debug("%s() set parent failed for clock: %s, ret = %d\n",
			 __func__, clk_name, ret);

	return ret;
}

static const struct clk_ops zynqmp_clk_mux_ops = {
	.get_parent = zynqmp_clk_mux_get_parent,
	.set_parent = zynqmp_clk_mux_set_parent,
	.determine_rate = __clk_mux_determine_rate_closest,
};

static const struct clk_ops zynqmp_clk_mux_ro_ops = {
	.get_parent = zynqmp_clk_mux_get_parent,
};

static inline unsigned long zynqmp_clk_map_mux_ccf_flags(
				       const u32 zynqmp_type_flag)
{
	unsigned long ccf_flag = 0;

	if (zynqmp_type_flag & ZYNQMP_CLK_MUX_INDEX_ONE)
		ccf_flag |= CLK_MUX_INDEX_ONE;
	if (zynqmp_type_flag & ZYNQMP_CLK_MUX_INDEX_BIT)
		ccf_flag |= CLK_MUX_INDEX_BIT;
	if (zynqmp_type_flag & ZYNQMP_CLK_MUX_HIWORD_MASK)
		ccf_flag |= CLK_MUX_HIWORD_MASK;
	if (zynqmp_type_flag & ZYNQMP_CLK_MUX_READ_ONLY)
		ccf_flag |= CLK_MUX_READ_ONLY;
	if (zynqmp_type_flag & ZYNQMP_CLK_MUX_ROUND_CLOSEST)
		ccf_flag |= CLK_MUX_ROUND_CLOSEST;
	if (zynqmp_type_flag & ZYNQMP_CLK_MUX_BIG_ENDIAN)
		ccf_flag |= CLK_MUX_BIG_ENDIAN;

	return ccf_flag;
}

Annotation

Implementation Notes