drivers/clocksource/renesas-ostm.c

Source file repositories/reference/linux-study-clean/drivers/clocksource/renesas-ostm.c

File Facts

System
Linux kernel
Corpus path
drivers/clocksource/renesas-ostm.c
Extension
.c
Size
5711 bytes
Lines
248
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

// SPDX-License-Identifier: GPL-2.0
/*
 * Renesas Timer Support - OSTM
 *
 * Copyright (C) 2017 Renesas Electronics America, Inc.
 * Copyright (C) 2017 Chris Brandt
 */

#include <linux/clk.h>
#include <linux/clockchips.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/reset.h>
#include <linux/sched_clock.h>
#include <linux/slab.h>

#include "timer-of.h"

/*
 * The OSTM contains independent channels.
 * The first OSTM channel probed will be set up as a free running
 * clocksource. Additionally we will use this clocksource for the system
 * schedule timer sched_clock().
 *
 * The second (or more) channel probed will be set up as an interrupt
 * driven clock event.
 */

static void __iomem *system_clock;	/* For sched_clock() */

/* OSTM REGISTERS */
#define	OSTM_CMP		0x000	/* RW,32 */
#define	OSTM_CNT		0x004	/* R,32 */
#define	OSTM_TE			0x010	/* R,8 */
#define	OSTM_TS			0x014	/* W,8 */
#define	OSTM_TT			0x018	/* W,8 */
#define	OSTM_CTL		0x020	/* RW,8 */

#define	TE			0x01
#define	TS			0x01
#define	TT			0x01
#define	CTL_PERIODIC		0x00
#define	CTL_ONESHOT		0x02
#define	CTL_FREERUN		0x02

static void ostm_timer_stop(struct timer_of *to)
{
	if (readb(timer_of_base(to) + OSTM_TE) & TE) {
		writeb(TT, timer_of_base(to) + OSTM_TT);

		/*
		 * Read back the register simply to confirm the write operation
		 * has completed since I/O writes can sometimes get queued by
		 * the bus architecture.
		 */
		while (readb(timer_of_base(to) + OSTM_TE) & TE)
			;
	}
}

static int __init ostm_init_clksrc(struct timer_of *to)
{
	ostm_timer_stop(to);

	writel(0, timer_of_base(to) + OSTM_CMP);
	writeb(CTL_FREERUN, timer_of_base(to) + OSTM_CTL);
	writeb(TS, timer_of_base(to) + OSTM_TS);

	return clocksource_mmio_init(timer_of_base(to) + OSTM_CNT,
				     to->np->full_name, timer_of_rate(to), 300,
				     32, clocksource_mmio_readl_up);
}

static u64 notrace ostm_read_sched_clock(void)
{
	return readl(system_clock);
}

static void __init ostm_init_sched_clock(struct timer_of *to)
{
	system_clock = timer_of_base(to) + OSTM_CNT;
	sched_clock_register(ostm_read_sched_clock, 32, timer_of_rate(to));
}

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

	ostm_timer_stop(to);

Annotation

Implementation Notes