drivers/clocksource/timer-ixp4xx.c

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

File Facts

System
Linux kernel
Corpus path
drivers/clocksource/timer-ixp4xx.c
Extension
.c
Size
7701 bytes
Lines
294
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 ixp4xx_timer {
	void __iomem *base;
	u32 latch;
	struct clock_event_device clkevt;
#ifdef CONFIG_ARM
	struct delay_timer delay_timer;
#endif
};

/*
 * A local singleton used by sched_clock and delay timer reads, which are
 * fast and stateless
 */
static struct ixp4xx_timer *local_ixp4xx_timer;

static inline struct ixp4xx_timer *
to_ixp4xx_timer(struct clock_event_device *evt)
{
	return container_of(evt, struct ixp4xx_timer, clkevt);
}

static unsigned long ixp4xx_read_timer(void)
{
	return __raw_readl(local_ixp4xx_timer->base + IXP4XX_OSTS_OFFSET);
}

static u64 notrace ixp4xx_read_sched_clock(void)
{
	return ixp4xx_read_timer();
}

static u64 ixp4xx_clocksource_read(struct clocksource *c)
{
	return ixp4xx_read_timer();
}

static irqreturn_t ixp4xx_timer_interrupt(int irq, void *dev_id)
{
	struct ixp4xx_timer *tmr = dev_id;
	struct clock_event_device *evt = &tmr->clkevt;

	/* Clear Pending Interrupt */
	__raw_writel(IXP4XX_OSST_TIMER_1_PEND,
		     tmr->base + IXP4XX_OSST_OFFSET);

	evt->event_handler(evt);

	return IRQ_HANDLED;
}

static int ixp4xx_set_next_event(unsigned long cycles,
				 struct clock_event_device *evt)
{
	struct ixp4xx_timer *tmr = to_ixp4xx_timer(evt);
	u32 val;

	val = __raw_readl(tmr->base + IXP4XX_OSRT1_OFFSET);
	/* Keep enable/oneshot bits */
	val &= IXP4XX_OST_RELOAD_MASK;
	__raw_writel((cycles & ~IXP4XX_OST_RELOAD_MASK) | val,
		     tmr->base + IXP4XX_OSRT1_OFFSET);

	return 0;
}

static int ixp4xx_shutdown(struct clock_event_device *evt)
{
	struct ixp4xx_timer *tmr = to_ixp4xx_timer(evt);
	u32 val;

	val = __raw_readl(tmr->base + IXP4XX_OSRT1_OFFSET);
	val &= ~IXP4XX_OST_ENABLE;
	__raw_writel(val, tmr->base + IXP4XX_OSRT1_OFFSET);

	return 0;
}

static int ixp4xx_set_oneshot(struct clock_event_device *evt)
{
	struct ixp4xx_timer *tmr = to_ixp4xx_timer(evt);

	__raw_writel(IXP4XX_OST_ENABLE | IXP4XX_OST_ONE_SHOT,
		     tmr->base + IXP4XX_OSRT1_OFFSET);

	return 0;
}

static int ixp4xx_set_periodic(struct clock_event_device *evt)
{
	struct ixp4xx_timer *tmr = to_ixp4xx_timer(evt);

Annotation

Implementation Notes