arch/mips/sni/time.c

Source file repositories/reference/linux-study-clean/arch/mips/sni/time.c

File Facts

System
Linux kernel
Corpus path
arch/mips/sni/time.c
Extension
.c
Size
4459 bytes
Lines
168
Domain
Architecture Layer
Bucket
arch/mips
Inferred role
Architecture Layer: implementation source
Status
source implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

// SPDX-License-Identifier: GPL-2.0
#include <linux/types.h>
#include <linux/i8253.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/smp.h>
#include <linux/time.h>
#include <linux/clockchips.h>

#include <asm/sni.h>
#include <asm/time.h>

#define SNI_CLOCK_TICK_RATE	3686400
#define SNI_COUNTER2_DIV	64
#define SNI_COUNTER0_DIV	((SNI_CLOCK_TICK_RATE / SNI_COUNTER2_DIV) / HZ)

static int a20r_set_periodic(struct clock_event_device *evt)
{
	*(volatile u8 *)(A20R_PT_CLOCK_BASE + 12) = 0x34;
	wmb();
	*(volatile u8 *)(A20R_PT_CLOCK_BASE + 0) = SNI_COUNTER0_DIV & 0xff;
	wmb();
	*(volatile u8 *)(A20R_PT_CLOCK_BASE + 0) = SNI_COUNTER0_DIV >> 8;
	wmb();

	*(volatile u8 *)(A20R_PT_CLOCK_BASE + 12) = 0xb4;
	wmb();
	*(volatile u8 *)(A20R_PT_CLOCK_BASE + 8) = SNI_COUNTER2_DIV & 0xff;
	wmb();
	*(volatile u8 *)(A20R_PT_CLOCK_BASE + 8) = SNI_COUNTER2_DIV >> 8;
	wmb();
	return 0;
}

static struct clock_event_device a20r_clockevent_device = {
	.name			= "a20r-timer",
	.features		= CLOCK_EVT_FEAT_PERIODIC,

	/* .mult, .shift, .max_delta_ns and .min_delta_ns left uninitialized */

	.rating			= 300,
	.irq			= SNI_A20R_IRQ_TIMER,
	.set_state_periodic	= a20r_set_periodic,
};

static irqreturn_t a20r_interrupt(int irq, void *dev_id)
{
	struct clock_event_device *cd = dev_id;

	*(volatile u8 *)A20R_PT_TIM0_ACK = 0;
	wmb();

	cd->event_handler(cd);

	return IRQ_HANDLED;
}

/*
 * a20r platform uses 2 counters to divide the input frequency.
 * Counter 2 output is connected to Counter 0 & 1 input.
 */
static void __init sni_a20r_timer_setup(void)
{
	struct clock_event_device *cd = &a20r_clockevent_device;
	unsigned int cpu = smp_processor_id();

	cd->cpumask		= cpumask_of(cpu);
	clockevents_register_device(cd);
	if (request_irq(SNI_A20R_IRQ_TIMER, a20r_interrupt,
			IRQF_PERCPU | IRQF_TIMER, "a20r-timer", cd))
		pr_err("Failed to register a20r-timer interrupt\n");
}

#define SNI_8254_TICK_RATE	  1193182UL

#define SNI_8254_TCSAMP_COUNTER	  ((SNI_8254_TICK_RATE / HZ) + 255)

static __init unsigned long dosample(void)
{
	u32 ct0, ct1;
	volatile u8 msb;

	/* Start the counter. */
	outb_p(0x34, 0x43);
	outb_p(SNI_8254_TCSAMP_COUNTER & 0xff, 0x40);
	outb(SNI_8254_TCSAMP_COUNTER >> 8, 0x40);

	/* Get initial counter invariant */
	ct0 = read_c0_count();

Annotation

Implementation Notes