drivers/clocksource/timer-keystone.c

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

File Facts

System
Linux kernel
Corpus path
drivers/clocksource/timer-keystone.c
Extension
.c
Size
5429 bytes
Lines
227
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-only
/*
 * Keystone broadcast clock-event
 *
 * Copyright 2013 Texas Instruments, Inc.
 *
 * Author: Ivan Khoronzhuk <ivan.khoronzhuk@ti.com>
 */

#include <linux/clk.h>
#include <linux/clockchips.h>
#include <linux/clocksource.h>
#include <linux/interrupt.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>

#define TIMER_NAME			"timer-keystone"

/* Timer register offsets */
#define TIM12				0x10
#define TIM34				0x14
#define PRD12				0x18
#define PRD34				0x1c
#define TCR				0x20
#define TGCR				0x24
#define INTCTLSTAT			0x44

/* Timer register bitfields */
#define TCR_ENAMODE_MASK		0xC0
#define TCR_ENAMODE_ONESHOT_MASK	0x40
#define TCR_ENAMODE_PERIODIC_MASK	0x80

#define TGCR_TIM_UNRESET_MASK		0x03
#define INTCTLSTAT_ENINT_MASK		0x01

/**
 * struct keystone_timer: holds timer's data
 * @base: timer memory base address
 * @hz_period: cycles per HZ period
 * @event_dev: event device based on timer
 */
static struct keystone_timer {
	void __iomem *base;
	unsigned long hz_period;
	struct clock_event_device event_dev;
} timer;

static inline u32 keystone_timer_readl(unsigned long rg)
{
	return readl_relaxed(timer.base + rg);
}

static inline void keystone_timer_writel(u32 val, unsigned long rg)
{
	writel_relaxed(val, timer.base + rg);
}

/**
 * keystone_timer_barrier: write memory barrier
 * use explicit barrier to avoid using readl/writel non relaxed function
 * variants, because in our case non relaxed variants hide the true places
 * where barrier is needed.
 */
static inline void keystone_timer_barrier(void)
{
	__iowmb();
}

/**
 * keystone_timer_config: configures timer to work in oneshot/periodic modes.
 * @ mask: mask of the mode to configure
 * @ period: cycles number to configure for
 */
static int keystone_timer_config(u64 period, int mask)
{
	u32 tcr;
	u32 off;

	tcr = keystone_timer_readl(TCR);
	off = tcr & ~(TCR_ENAMODE_MASK);

	/* set enable mode */
	tcr |= mask;

	/* disable timer */
	keystone_timer_writel(off, TCR);
	/* here we have to be sure the timer has been disabled */
	keystone_timer_barrier();

	/* reset counter to zero, set new period */

Annotation

Implementation Notes