drivers/clocksource/timer-pxa.c

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

File Facts

System
Linux kernel
Corpus path
drivers/clocksource/timer-pxa.c
Extension
.c
Size
5995 bytes
Lines
228
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
/*
 * arch/arm/mach-pxa/time.c
 *
 * PXA clocksource, clockevents, and OST interrupt handlers.
 * Copyright (c) 2007 by Bill Gatliff <bgat@billgatliff.com>.
 *
 * Derived from Nicolas Pitre's PXA timer handler Copyright (c) 2001
 * by MontaVista Software, Inc.  (Nico, your code rocks!)
 */

#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/clk.h>
#include <linux/clockchips.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/sched/clock.h>
#include <linux/sched_clock.h>

#include <clocksource/pxa.h>

#include <asm/div64.h>

#define OSMR0		0x00	/* OS Timer 0 Match Register */
#define OSMR1		0x04	/* OS Timer 1 Match Register */
#define OSMR2		0x08	/* OS Timer 2 Match Register */
#define OSMR3		0x0C	/* OS Timer 3 Match Register */

#define OSCR		0x10	/* OS Timer Counter Register */
#define OSSR		0x14	/* OS Timer Status Register */
#define OWER		0x18	/* OS Timer Watchdog Enable Register */
#define OIER		0x1C	/* OS Timer Interrupt Enable Register */

#define OSSR_M3		(1 << 3)	/* Match status channel 3 */
#define OSSR_M2		(1 << 2)	/* Match status channel 2 */
#define OSSR_M1		(1 << 1)	/* Match status channel 1 */
#define OSSR_M0		(1 << 0)	/* Match status channel 0 */

#define OIER_E0		(1 << 0)	/* Interrupt enable channel 0 */

/*
 * This is PXA's sched_clock implementation. This has a resolution
 * of at least 308 ns and a maximum value of 208 days.
 *
 * The return value is guaranteed to be monotonic in that range as
 * long as there is always less than 582 seconds between successive
 * calls to sched_clock() which should always be the case in practice.
 */

#define timer_readl(reg) readl_relaxed(timer_base + (reg))
#define timer_writel(val, reg) writel_relaxed((val), timer_base + (reg))

static void __iomem *timer_base;

static u64 notrace pxa_read_sched_clock(void)
{
	return timer_readl(OSCR);
}


#define MIN_OSCR_DELTA 16

static irqreturn_t
pxa_ost0_interrupt(int irq, void *dev_id)
{
	struct clock_event_device *c = dev_id;

	/* Disarm the compare/match, signal the event. */
	timer_writel(timer_readl(OIER) & ~OIER_E0, OIER);
	timer_writel(OSSR_M0, OSSR);
	c->event_handler(c);

	return IRQ_HANDLED;
}

static int
pxa_osmr0_set_next_event(unsigned long delta, struct clock_event_device *dev)
{
	unsigned long next, oscr;

	timer_writel(timer_readl(OIER) | OIER_E0, OIER);
	next = timer_readl(OSCR) + delta;
	timer_writel(next, OSMR0);
	oscr = timer_readl(OSCR);

	return (signed)(next - oscr) <= MIN_OSCR_DELTA ? -ETIME : 0;
}

Annotation

Implementation Notes