drivers/clk/ti/clkctrl.c

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

File Facts

System
Linux kernel
Corpus path
drivers/clk/ti/clkctrl.c
Extension
.c
Size
17533 bytes
Lines
751
Domain
Driver Families
Bucket
drivers/clk
Inferred role
Driver Families: exported/initcall integration point
Status
integration 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 omap_clkctrl_provider {
	void __iomem *base;
	struct list_head clocks;
	char *clkdm_name;
};

struct omap_clkctrl_clk {
	struct clk_hw *clk;
	u16 reg_offset;
	int bit_offset;
	struct list_head node;
};

union omap4_timeout {
	u32 cycles;
	ktime_t start;
};

static const struct omap_clkctrl_data default_clkctrl_data[] __initconst = {
	{ 0 },
};

static u32 _omap4_idlest(u32 val)
{
	val &= OMAP4_IDLEST_MASK;
	val >>= OMAP4_IDLEST_SHIFT;

	return val;
}

static bool _omap4_is_idle(u32 val)
{
	val = _omap4_idlest(val);

	return val == CLKCTRL_IDLEST_DISABLED;
}

static bool _omap4_is_ready(u32 val)
{
	val = _omap4_idlest(val);

	return val == CLKCTRL_IDLEST_FUNCTIONAL ||
	       val == CLKCTRL_IDLEST_INTERFACE_IDLE;
}

static bool _omap4_is_timeout(union omap4_timeout *time, u32 timeout)
{
	/*
	 * There are two special cases where ktime_to_ns() can't be
	 * used to track the timeouts. First one is during early boot
	 * when the timers haven't been initialized yet. The second
	 * one is during suspend-resume cycle while timekeeping is
	 * being suspended / resumed. Clocksource for the system
	 * can be from a timer that requires pm_runtime access, which
	 * will eventually bring us here with timekeeping_suspended,
	 * during both suspend entry and resume paths. This happens
	 * at least on am43xx platform. Account for flakeyness
	 * with udelay() by multiplying the timeout value by 2.
	 */
	if (unlikely(_early_timeout || timekeeping_suspended)) {
		if (time->cycles++ < timeout) {
			udelay(1 * 2);
			return false;
		}
	} else {
		if (!ktime_to_ns(time->start)) {
			time->start = ktime_get();
			return false;
		}

		if (ktime_us_delta(ktime_get(), time->start) < timeout) {
			cpu_relax();
			return false;
		}
	}

	return true;
}

static int __init _omap4_disable_early_timeout(void)
{
	_early_timeout = false;

	return 0;
}
arch_initcall(_omap4_disable_early_timeout);

static int _omap4_clkctrl_clk_enable(struct clk_hw *hw)
{
	struct clk_hw_omap *clk = to_clk_hw_omap(hw);

Annotation

Implementation Notes