drivers/clk/x86/clk-pmc-atom.c

Source file repositories/reference/linux-study-clean/drivers/clk/x86/clk-pmc-atom.c

File Facts

System
Linux kernel
Corpus path
drivers/clk/x86/clk-pmc-atom.c
Extension
.c
Size
8666 bytes
Lines
379
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 clk_plt_fixed {
	struct clk_hw *clk;
	struct clk_lookup *lookup;
};

struct clk_plt {
	struct clk_hw hw;
	void __iomem *reg;
	struct clk_lookup *lookup;
	/* protect access to PMC registers */
	spinlock_t lock;
};

#define to_clk_plt(_hw) container_of(_hw, struct clk_plt, hw)

struct clk_plt_data {
	struct clk_plt_fixed **parents;
	u8 nparents;
	struct clk_plt *clks[PMC_CLK_NUM];
	struct clk_lookup *mclk_lookup;
	struct clk_lookup *ether_clk_lookup;
};

/* Return an index in parent table */
static inline int plt_reg_to_parent(int reg)
{
	switch (reg & PMC_MASK_CLK_FREQ) {
	default:
	case PMC_CLK_FREQ_XTAL:
		return 0;
	case PMC_CLK_FREQ_PLL:
		return 1;
	}
}

/* Return clk index of parent */
static inline int plt_parent_to_reg(int index)
{
	switch (index) {
	default:
	case 0:
		return PMC_CLK_FREQ_XTAL;
	case 1:
		return PMC_CLK_FREQ_PLL;
	}
}

/* Abstract status in simpler enabled/disabled value */
static inline int plt_reg_to_enabled(int reg)
{
	switch (reg & PMC_MASK_CLK_CTL) {
	case PMC_CLK_CTL_GATED_ON_D3:
	case PMC_CLK_CTL_FORCE_ON:
		return 1;	/* enabled */
	case PMC_CLK_CTL_FORCE_OFF:
	case PMC_CLK_CTL_RESERVED:
	default:
		return 0;	/* disabled */
	}
}

static void plt_clk_reg_update(struct clk_plt *clk, u32 mask, u32 val)
{
	u32 tmp;
	unsigned long flags;

	spin_lock_irqsave(&clk->lock, flags);

	tmp = readl(clk->reg);
	tmp = (tmp & ~mask) | (val & mask);
	writel(tmp, clk->reg);

	spin_unlock_irqrestore(&clk->lock, flags);
}

static int plt_clk_set_parent(struct clk_hw *hw, u8 index)
{
	struct clk_plt *clk = to_clk_plt(hw);

	plt_clk_reg_update(clk, PMC_MASK_CLK_FREQ, plt_parent_to_reg(index));

	return 0;
}

static u8 plt_clk_get_parent(struct clk_hw *hw)
{
	struct clk_plt *clk = to_clk_plt(hw);
	u32 value;

	value = readl(clk->reg);

Annotation

Implementation Notes