drivers/clk/keystone/gate.c

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

File Facts

System
Linux kernel
Corpus path
drivers/clk/keystone/gate.c
Extension
.c
Size
6782 bytes
Lines
270
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_psc_data {
	void __iomem *control_base;
	void __iomem *domain_base;
	u32 domain_id;
};

/**
 * struct clk_psc - PSC clock structure
 * @hw: clk_hw for the psc
 * @psc_data: PSC driver specific data
 * @lock: Spinlock used by the driver
 */
struct clk_psc {
	struct clk_hw hw;
	struct clk_psc_data *psc_data;
	spinlock_t *lock;
};

static DEFINE_SPINLOCK(psc_lock);

#define to_clk_psc(_hw) container_of(_hw, struct clk_psc, hw)

static void psc_config(void __iomem *control_base, void __iomem *domain_base,
						u32 next_state, u32 domain_id)
{
	u32 ptcmd, pdstat, pdctl, mdstat, mdctl, ptstat;
	u32 count = STATE_TRANS_MAX_COUNT;

	mdctl = readl(control_base + MDCTL);
	mdctl &= ~MDSTAT_STATE_MASK;
	mdctl |= next_state;
	/* For disable, we always put the module in local reset */
	if (next_state == PSC_STATE_DISABLE)
		mdctl &= ~MDCTL_LRESET;
	writel(mdctl, control_base + MDCTL);

	pdstat = readl(domain_base + PDSTAT);
	if (!(pdstat & PDSTAT_STATE_MASK)) {
		pdctl = readl(domain_base + PDCTL);
		pdctl |= PDCTL_NEXT;
		writel(pdctl, domain_base + PDCTL);
	}

	ptcmd = 1 << domain_id;
	writel(ptcmd, domain_transition_base + PTCMD);
	do {
		ptstat = readl(domain_transition_base + PTSTAT);
	} while (((ptstat >> domain_id) & 1) && count--);

	count = STATE_TRANS_MAX_COUNT;
	do {
		mdstat = readl(control_base + MDSTAT);
	} while (!((mdstat & MDSTAT_STATE_MASK) == next_state) && count--);
}

static int keystone_clk_is_enabled(struct clk_hw *hw)
{
	struct clk_psc *psc = to_clk_psc(hw);
	struct clk_psc_data *data = psc->psc_data;
	u32 mdstat = readl(data->control_base + MDSTAT);

	return (mdstat & MDSTAT_MCKOUT) ? 1 : 0;
}

static int keystone_clk_enable(struct clk_hw *hw)
{
	struct clk_psc *psc = to_clk_psc(hw);
	struct clk_psc_data *data = psc->psc_data;
	unsigned long flags = 0;

	if (psc->lock)
		spin_lock_irqsave(psc->lock, flags);

	psc_config(data->control_base, data->domain_base,
				PSC_STATE_ENABLE, data->domain_id);

	if (psc->lock)
		spin_unlock_irqrestore(psc->lock, flags);

	return 0;
}

static void keystone_clk_disable(struct clk_hw *hw)
{
	struct clk_psc *psc = to_clk_psc(hw);
	struct clk_psc_data *data = psc->psc_data;
	unsigned long flags = 0;

	if (psc->lock)
		spin_lock_irqsave(psc->lock, flags);

Annotation

Implementation Notes