drivers/clocksource/timer-sp804.c

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

File Facts

System
Linux kernel
Corpus path
drivers/clocksource/timer-sp804.c
Extension
.c
Size
9616 bytes
Lines
419
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

static inline void sp804_register_delay_timer(struct sp804_clkevt *clk, int freq) {}
#endif

static int __init sp804_clocksource_and_sched_clock_init(void __iomem *base,
							 const char *name,
							 struct clk *clk,
							 int use_sched_clock)
{
	long rate;
	struct sp804_clkevt *clkevt;

	rate = sp804_get_clock_rate(clk, name);
	if (rate < 0)
		return -EINVAL;

	clkevt = sp804_clkevt_get(base);

	writel(0, clkevt->ctrl);
	writel(0xffffffff, clkevt->load);
	writel(0xffffffff, clkevt->value);
	if (clkevt->width == 64) {
		writel(0xffffffff, clkevt->load_h);
		writel(0xffffffff, clkevt->value_h);
	}
	writel(TIMER_CTRL_32BIT | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC,
		clkevt->ctrl);

	clocksource_mmio_init(clkevt->value, name,
		rate, 200, 32, clocksource_mmio_readl_down);

	sp804_register_delay_timer(clkevt, rate);

	if (use_sched_clock) {
		sched_clkevt = clkevt;
		sched_clock_register(sp804_read, 32, rate);
	}

	return 0;
}


static struct sp804_clkevt *common_clkevt;

/*
 * IRQ handler for the timer
 */
static irqreturn_t sp804_timer_interrupt(int irq, void *dev_id)
{
	struct clock_event_device *evt = dev_id;

	/* clear the interrupt */
	writel(1, common_clkevt->intclr);

	evt->event_handler(evt);

	return IRQ_HANDLED;
}

static inline void evt_timer_shutdown(struct clock_event_device *evt)
{
	writel(0, common_clkevt->ctrl);
}

static int sp804_shutdown(struct clock_event_device *evt)
{
	evt_timer_shutdown(evt);
	return 0;
}

static int sp804_set_periodic(struct clock_event_device *evt)
{
	unsigned long ctrl = TIMER_CTRL_32BIT | TIMER_CTRL_IE |
			     TIMER_CTRL_PERIODIC | TIMER_CTRL_ENABLE;

	evt_timer_shutdown(evt);
	writel(common_clkevt->reload, common_clkevt->load);
	writel(ctrl, common_clkevt->ctrl);
	return 0;
}

static int sp804_set_next_event(unsigned long next,
	struct clock_event_device *evt)
{
	unsigned long ctrl = TIMER_CTRL_32BIT | TIMER_CTRL_IE |
			     TIMER_CTRL_ONESHOT | TIMER_CTRL_ENABLE;

	writel(next, common_clkevt->load);
	writel(ctrl, common_clkevt->ctrl);

	return 0;

Annotation

Implementation Notes