drivers/clocksource/timer-rtl-otto.c

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

File Facts

System
Linux kernel
Corpus path
drivers/clocksource/timer-rtl-otto.c
Extension
.c
Size
8188 bytes
Lines
304
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 rttm_cs {
	struct timer_of		to;
	struct clocksource	cs;
};

/* Simple internal register functions */
static inline unsigned int rttm_get_counter(void __iomem *base)
{
	return ioread32(base + RTTM_CNT);
}

static inline void rttm_set_period(void __iomem *base, unsigned int period)
{
	iowrite32(period, base + RTTM_DATA);
}

static inline void rttm_disable_timer(void __iomem *base)
{
	iowrite32(0, base + RTTM_CTRL);
}

static inline void rttm_enable_timer(void __iomem *base, u32 mode, u32 divisor)
{
	iowrite32(RTTM_CTRL_ENABLE | mode | divisor, base + RTTM_CTRL);
}

static inline void rttm_ack_irq(void __iomem *base)
{
	iowrite32(ioread32(base + RTTM_INT) | RTTM_INT_PENDING, base + RTTM_INT);
}

static inline void rttm_enable_irq(void __iomem *base)
{
	iowrite32(RTTM_INT_ENABLE, base + RTTM_INT);
}

static inline void rttm_disable_irq(void __iomem *base)
{
	iowrite32(0, base + RTTM_INT);
}

/* Aggregated control functions for kernel clock framework */
#define RTTM_DEBUG(base)			\
	pr_debug("------------- %d %p\n",	\
		 smp_processor_id(), base)

static irqreturn_t rttm_timer_interrupt(int irq, void *dev_id)
{
	struct clock_event_device *clkevt = dev_id;
	struct timer_of *to = to_timer_of(clkevt);

	rttm_ack_irq(to->of_base.base);
	RTTM_DEBUG(to->of_base.base);
	clkevt->event_handler(clkevt);

	return IRQ_HANDLED;
}

static void rttm_bounce_timer(void __iomem *base, u32 mode)
{
	/*
	 * When a running timer has less than ~5us left, a stop/start sequence
	 * might fail. While the details are unknown the most evident effect is
	 * that the subsequent interrupt will not be fired.
	 *
	 * As a workaround issue an intermediate restart with a very slow
	 * frequency of ~3kHz keeping the target counter (>=8). So the follow
	 * up restart will always be issued outside the critical window.
	 */

	rttm_disable_timer(base);
	rttm_enable_timer(base, mode, RTTM_MAX_DIVISOR);
}

static void rttm_stop_timer(void __iomem *base)
{
	rttm_disable_timer(base);
	rttm_ack_irq(base);
}

static void rttm_start_timer(struct timer_of *to, u32 mode)
{
	rttm_enable_timer(to->of_base.base, mode, to->of_clk.rate / RTTM_TICKS_PER_SEC);
}

static int rttm_next_event(unsigned long delta, struct clock_event_device *clkevt)
{
	struct timer_of *to = to_timer_of(clkevt);

	RTTM_DEBUG(to->of_base.base);

Annotation

Implementation Notes