drivers/clocksource/timer-nxp-pit.c

Source file repositories/reference/linux-study-clean/drivers/clocksource/timer-nxp-pit.c

File Facts

System
Linux kernel
Corpus path
drivers/clocksource/timer-nxp-pit.c
Extension
.c
Size
9280 bytes
Lines
384
Domain
Driver Families
Bucket
drivers/clocksource
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 pit_timer {
	void __iomem *clksrc_base;
	void __iomem *clkevt_base;
	struct clock_event_device ced;
	struct clocksource cs;
	int rate;
};

struct pit_timer_data {
	int max_pit_instances;
};

static DEFINE_PER_CPU(struct pit_timer *, pit_timers);

/*
 * Global structure for multiple PITs initialization
 */
static int pit_instances;
static int max_pit_instances = 1;

static void __iomem *sched_clock_base;

static inline struct pit_timer *ced_to_pit(struct clock_event_device *ced)
{
	return container_of(ced, struct pit_timer, ced);
}

static inline struct pit_timer *cs_to_pit(struct clocksource *cs)
{
	return container_of(cs, struct pit_timer, cs);
}

static inline void pit_module_enable(void __iomem *base)
{
	writel(0, PITMCR(base));
}

static inline void pit_module_disable(void __iomem *base)
{
	writel(PITMCR_MDIS, PITMCR(base));
}

static inline void pit_timer_enable(void __iomem *base, bool tie)
{
	u32 val = PITTCTRL_TEN | (tie ? PITTCTRL_TIE : 0);

	writel(val, PITTCTRL(base));
}

static inline void pit_timer_disable(void __iomem *base)
{
	writel(0, PITTCTRL(base));
}

static inline void pit_timer_set_counter(void __iomem *base, unsigned int cnt)
{
	writel(cnt, PITLDVAL(base));
}

static inline void pit_timer_irqack(struct pit_timer *pit)
{
	writel(PITTFLG_TIF, PITTFLG(pit->clkevt_base));
}

static u64 notrace pit_read_sched_clock(void)
{
	return ~readl(sched_clock_base);
}

static u64 pit_timer_clocksource_read(struct clocksource *cs)
{
	struct pit_timer *pit = cs_to_pit(cs);

	return (u64)~readl(PITCVAL(pit->clksrc_base));
}

static int pit_clocksource_init(struct pit_timer *pit, const char *name,
				void __iomem *base, unsigned long rate)
{
	/*
	 * The channels 0 and 1 can be chained to build a 64-bit
	 * timer. Let's use the channel 2 as a clocksource and leave
	 * the channels 0 and 1 unused for anyone else who needs them
	 */
	pit->clksrc_base = base + PIT_CH(2);
	pit->cs.name = name;
	pit->cs.rating = 300;
	pit->cs.read = pit_timer_clocksource_read;
	pit->cs.mask = CLOCKSOURCE_MASK(32);
	pit->cs.flags = CLOCK_SOURCE_IS_CONTINUOUS;

Annotation

Implementation Notes