drivers/clk/bcm/clk-iproc-armpll.c

Source file repositories/reference/linux-study-clean/drivers/clk/bcm/clk-iproc-armpll.c

File Facts

System
Linux kernel
Corpus path
drivers/clk/bcm/clk-iproc-armpll.c
Extension
.c
Size
7252 bytes
Lines
274
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 iproc_arm_pll {
	struct clk_hw hw;
	void __iomem *base;
	unsigned long rate;
};

#define to_iproc_arm_pll(hw) container_of(hw, struct iproc_arm_pll, hw)

static unsigned int __get_fid(struct iproc_arm_pll *pll)
{
	u32 val;
	unsigned int policy, fid, active_fid;

	val = readl(pll->base + IPROC_CLK_ARM_DIV_OFFSET);
	if (val & (1 << IPROC_CLK_ARM_DIV_PLL_SELECT_OVERRIDE_SHIFT))
		policy = val & IPROC_CLK_ARM_DIV_ARM_PLL_SELECT_MASK;
	else
		policy = 0;

	/* something is seriously wrong */
	BUG_ON(policy > IPROC_CLK_MAX_FREQ_POLICY);

	val = readl(pll->base + IPROC_CLK_POLICY_FREQ_OFFSET);
	fid = (val >> (IPROC_CLK_POLICY_FREQ_POLICY_FREQ_SHIFT * policy)) &
		IPROC_CLK_POLICY_FREQ_POLICY_FREQ_MASK;

	val = readl(pll->base + IPROC_CLK_POLICY_DBG_OFFSET);
	active_fid = IPROC_CLK_POLICY_DBG_ACT_FREQ_MASK &
		(val >> IPROC_CLK_POLICY_DBG_ACT_FREQ_SHIFT);
	if (fid != active_fid) {
		pr_debug("%s: fid override %u->%u\n", __func__,	fid,
				active_fid);
		fid = active_fid;
	}

	pr_debug("%s: active fid: %u\n", __func__, fid);

	return fid;
}

/*
 * Determine the mdiv (post divider) based on the frequency ID being used.
 * There are 4 sources that can be used to derive the output clock rate:
 *    - 25 MHz Crystal
 *    - System clock
 *    - PLL channel 0 (slow clock)
 *    - PLL channel 1 (fast clock)
 */
static int __get_mdiv(struct iproc_arm_pll *pll)
{
	unsigned int fid;
	int mdiv;
	u32 val;

	fid = __get_fid(pll);

	switch (fid) {
	case ARM_PLL_FID_CRYSTAL_CLK:
	case ARM_PLL_FID_SYS_CLK:
		mdiv = 1;
		break;

	case ARM_PLL_FID_CH0_SLOW_CLK:
		val = readl(pll->base + IPROC_CLK_PLLARMC_OFFSET);
		mdiv = val & IPROC_CLK_PLLARMC_MDIV_MASK;
		if (mdiv == 0)
			mdiv = 256;
		break;

	case ARM_PLL_FID_CH1_FAST_CLK:
		val = readl(pll->base +	IPROC_CLK_PLLARMCTL5_OFFSET);
		mdiv = val & IPROC_CLK_PLLARMCTL5_H_MDIV_MASK;
		if (mdiv == 0)
			mdiv = 256;
		break;

	default:
		mdiv = -EFAULT;
	}

	return mdiv;
}

static unsigned int __get_ndiv(struct iproc_arm_pll *pll)
{
	u32 val;
	unsigned int ndiv_int, ndiv_frac, ndiv;

	val = readl(pll->base + IPROC_CLK_PLLARM_OFFSET_OFFSET);
	if (val & (1 << IPROC_CLK_PLLARM_SW_CTL_SHIFT)) {

Annotation

Implementation Notes