drivers/clocksource/timer-fttmr010.c

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

File Facts

System
Linux kernel
Corpus path
drivers/clocksource/timer-fttmr010.c
Extension
.c
Size
12333 bytes
Lines
460
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 fttmr010 {
	void __iomem *base;
	unsigned int tick_rate;
	bool is_aspeed;
	u32 t1_enable_val;
	struct clock_event_device clkevt;
	int (*timer_shutdown)(struct clock_event_device *evt);
#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 fttmr010 *local_fttmr;

static inline struct fttmr010 *to_fttmr010(struct clock_event_device *evt)
{
	return container_of(evt, struct fttmr010, clkevt);
}

static unsigned long fttmr010_read_current_timer_up(void)
{
	return readl(local_fttmr->base + TIMER2_COUNT);
}

static unsigned long fttmr010_read_current_timer_down(void)
{
	return ~readl(local_fttmr->base + TIMER2_COUNT);
}

static u64 notrace fttmr010_read_sched_clock_up(void)
{
	return fttmr010_read_current_timer_up();
}

static u64 notrace fttmr010_read_sched_clock_down(void)
{
	return fttmr010_read_current_timer_down();
}

static int fttmr010_timer_set_next_event(unsigned long cycles,
				       struct clock_event_device *evt)
{
	struct fttmr010 *fttmr010 = to_fttmr010(evt);
	u32 cr;

	/* Stop */
	fttmr010->timer_shutdown(evt);

	if (fttmr010->is_aspeed) {
		/*
		 * ASPEED Timer Controller will load TIMER1_LOAD register
		 * into TIMER1_COUNT register when the timer is re-enabled.
		 */
		writel(cycles, fttmr010->base + TIMER1_LOAD);
	} else {
		/* Setup the match register forward in time */
		cr = readl(fttmr010->base + TIMER1_COUNT);
		writel(cr + cycles, fttmr010->base + TIMER1_MATCH1);
	}

	/* Start */
	cr = readl(fttmr010->base + TIMER_CR);
	cr |= fttmr010->t1_enable_val;
	writel(cr, fttmr010->base + TIMER_CR);

	return 0;
}

static int ast2600_timer_shutdown(struct clock_event_device *evt)
{
	struct fttmr010 *fttmr010 = to_fttmr010(evt);

	/* Stop */
	writel(fttmr010->t1_enable_val, fttmr010->base + AST2600_TIMER_CR_CLR);

	return 0;
}

static int fttmr010_timer_shutdown(struct clock_event_device *evt)
{
	struct fttmr010 *fttmr010 = to_fttmr010(evt);
	u32 cr;

	/* Stop */
	cr = readl(fttmr010->base + TIMER_CR);
	cr &= ~fttmr010->t1_enable_val;

Annotation

Implementation Notes