drivers/clk/clk-eyeq.c

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

File Facts

System
Linux kernel
Corpus path
drivers/clk/clk-eyeq.c
Extension
.c
Size
26758 bytes
Lines
898
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 eqc_pll {
	unsigned int	index;
	const char	*name;
	unsigned int	reg64;
};

/*
 * Divider clock. Divider is 2*(v+1), with v the register value.
 * Min divider is 2, max is 2*(2^width).
 */
struct eqc_div {
	unsigned int	index;
	const char	*name;
	unsigned int	parent;
	unsigned int	reg;
	u8		shift;
	u8		width;
};

struct eqc_fixed_factor {
	unsigned int	index;
	const char	*name;
	unsigned int	mult;
	unsigned int	div;
	unsigned int	parent;
};

struct eqc_match_data {
	unsigned int		pll_count;
	const struct eqc_pll	*plls;

	unsigned int		div_count;
	const struct eqc_div	*divs;

	unsigned int			fixed_factor_count;
	const struct eqc_fixed_factor	*fixed_factors;

	const char		*reset_auxdev_name;
	const char		*pinctrl_auxdev_name;
	const char		*eth_phy_auxdev_name;

	unsigned int		early_clk_count;
};

struct eqc_early_match_data {
	unsigned int		early_pll_count;
	const struct eqc_pll	*early_plls;

	unsigned int			early_fixed_factor_count;
	const struct eqc_fixed_factor	*early_fixed_factors;

	/*
	 * We want our of_xlate callback to EPROBE_DEFER instead of dev_err()
	 * and EINVAL. For that, we must know the total clock count.
	 */
	unsigned int		late_clk_count;
};

/*
 * Both factors (mult and div) must fit in 32 bits. When an operation overflows,
 * this function throws away low bits so that factors still fit in 32 bits.
 *
 * Precision loss depends on amplitude of mult and div. Worst theoretical
 * loss is: (UINT_MAX+1) / UINT_MAX - 1 = 2.3e-10.
 * This is 1Hz every 4.3GHz.
 */
static void eqc_pll_downshift_factors(unsigned long *mult, unsigned long *div)
{
	unsigned long biggest;
	unsigned int shift;

	/* This function can be removed if mult/div switch to unsigned long. */
	static_assert(sizeof_field(struct clk_fixed_factor, mult) == sizeof(unsigned int));
	static_assert(sizeof_field(struct clk_fixed_factor, div) == sizeof(unsigned int));

	/* No overflow, nothing to be done. */
	if (*mult <= UINT_MAX && *div <= UINT_MAX)
		return;

	/*
	 * Compute the shift required to bring the biggest factor into unsigned
	 * int range. That is, shift its highest set bit to the unsigned int
	 * most significant bit.
	 */
	biggest = max(*mult, *div);
	shift = __fls(biggest) - (BITS_PER_BYTE * sizeof(unsigned int)) + 1;

	*mult >>= shift;
	*div >>= shift;
}

Annotation

Implementation Notes