cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

time.c (2324B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 *  linux/arch/arm/common/time-acorn.c
      4 *
      5 *  Copyright (c) 1996-2000 Russell King.
      6 *
      7 *  Changelog:
      8 *   24-Sep-1996	RMK	Created
      9 *   10-Oct-1996	RMK	Brought up to date with arch-sa110eval
     10 *   04-Dec-1997	RMK	Updated for new arch/arm/time.c
     11 *   13=Jun-2004	DS	Moved to arch/arm/common b/c shared w/CLPS7500
     12 */
     13#include <linux/clocksource.h>
     14#include <linux/init.h>
     15#include <linux/interrupt.h>
     16#include <linux/irq.h>
     17#include <linux/io.h>
     18
     19#include <mach/hardware.h>
     20#include <asm/hardware/ioc.h>
     21
     22#include <asm/mach/time.h>
     23
     24#define RPC_CLOCK_FREQ 2000000
     25#define RPC_LATCH DIV_ROUND_CLOSEST(RPC_CLOCK_FREQ, HZ)
     26
     27static u32 ioc_time;
     28
     29static u64 ioc_timer_read(struct clocksource *cs)
     30{
     31	unsigned int count1, count2, status;
     32	unsigned long flags;
     33	u32 ticks;
     34
     35	local_irq_save(flags);
     36	ioc_writeb (0, IOC_T0LATCH);
     37	barrier ();
     38	count1 = ioc_readb(IOC_T0CNTL) | (ioc_readb(IOC_T0CNTH) << 8);
     39	barrier ();
     40	status = ioc_readb(IOC_IRQREQA);
     41	barrier ();
     42	ioc_writeb (0, IOC_T0LATCH);
     43	barrier ();
     44	count2 = ioc_readb(IOC_T0CNTL) | (ioc_readb(IOC_T0CNTH) << 8);
     45	ticks = ioc_time + RPC_LATCH - count2;
     46	local_irq_restore(flags);
     47
     48	if (count2 < count1) {
     49		/*
     50		 * The timer has not reloaded between reading count1 and
     51		 * count2, check whether an interrupt was actually pending.
     52		 */
     53		if (status & (1 << 5))
     54			ticks += RPC_LATCH;
     55	} else if (count2 > count1) {
     56		/*
     57		 * The timer has reloaded, so count2 indicates the new
     58		 * count since the wrap.  The interrupt would not have
     59		 * been processed, so add the missed ticks.
     60		 */
     61		ticks += RPC_LATCH;
     62	}
     63
     64	return ticks;
     65}
     66
     67static struct clocksource ioctime_clocksource = {
     68	.read = ioc_timer_read,
     69	.mask = CLOCKSOURCE_MASK(32),
     70	.rating = 100,
     71};
     72
     73void __init ioctime_init(void)
     74{
     75	ioc_writeb(RPC_LATCH & 255, IOC_T0LTCHL);
     76	ioc_writeb(RPC_LATCH >> 8, IOC_T0LTCHH);
     77	ioc_writeb(0, IOC_T0GO);
     78}
     79
     80static irqreturn_t
     81ioc_timer_interrupt(int irq, void *dev_id)
     82{
     83	ioc_time += RPC_LATCH;
     84	legacy_timer_tick(1);
     85	return IRQ_HANDLED;
     86}
     87
     88/*
     89 * Set up timer interrupt.
     90 */
     91void __init ioc_timer_init(void)
     92{
     93	WARN_ON(clocksource_register_hz(&ioctime_clocksource, RPC_CLOCK_FREQ));
     94	ioctime_init();
     95	if (request_irq(IRQ_TIMER0, ioc_timer_interrupt, 0, "timer", NULL))
     96		pr_err("Failed to request irq %d (timer)\n", IRQ_TIMER0);
     97}