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

cevt-gt641xx.c (3528B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 *  GT641xx clockevent routines.
      4 *
      5 *  Copyright (C) 2007	Yoichi Yuasa <yuasa@linux-mips.org>
      6 */
      7#include <linux/clockchips.h>
      8#include <linux/init.h>
      9#include <linux/interrupt.h>
     10#include <linux/spinlock.h>
     11#include <linux/irq.h>
     12
     13#include <asm/gt64120.h>
     14#include <asm/time.h>
     15
     16static DEFINE_RAW_SPINLOCK(gt641xx_timer_lock);
     17static unsigned int gt641xx_base_clock;
     18
     19void gt641xx_set_base_clock(unsigned int clock)
     20{
     21	gt641xx_base_clock = clock;
     22}
     23
     24int gt641xx_timer0_state(void)
     25{
     26	if (GT_READ(GT_TC0_OFS))
     27		return 0;
     28
     29	GT_WRITE(GT_TC0_OFS, gt641xx_base_clock / HZ);
     30	GT_WRITE(GT_TC_CONTROL_OFS, GT_TC_CONTROL_ENTC0_MSK);
     31
     32	return 1;
     33}
     34
     35static int gt641xx_timer0_set_next_event(unsigned long delta,
     36					 struct clock_event_device *evt)
     37{
     38	u32 ctrl;
     39
     40	raw_spin_lock(&gt641xx_timer_lock);
     41
     42	ctrl = GT_READ(GT_TC_CONTROL_OFS);
     43	ctrl &= ~(GT_TC_CONTROL_ENTC0_MSK | GT_TC_CONTROL_SELTC0_MSK);
     44	ctrl |= GT_TC_CONTROL_ENTC0_MSK;
     45
     46	GT_WRITE(GT_TC0_OFS, delta);
     47	GT_WRITE(GT_TC_CONTROL_OFS, ctrl);
     48
     49	raw_spin_unlock(&gt641xx_timer_lock);
     50
     51	return 0;
     52}
     53
     54static int gt641xx_timer0_shutdown(struct clock_event_device *evt)
     55{
     56	u32 ctrl;
     57
     58	raw_spin_lock(&gt641xx_timer_lock);
     59
     60	ctrl = GT_READ(GT_TC_CONTROL_OFS);
     61	ctrl &= ~(GT_TC_CONTROL_ENTC0_MSK | GT_TC_CONTROL_SELTC0_MSK);
     62	GT_WRITE(GT_TC_CONTROL_OFS, ctrl);
     63
     64	raw_spin_unlock(&gt641xx_timer_lock);
     65	return 0;
     66}
     67
     68static int gt641xx_timer0_set_oneshot(struct clock_event_device *evt)
     69{
     70	u32 ctrl;
     71
     72	raw_spin_lock(&gt641xx_timer_lock);
     73
     74	ctrl = GT_READ(GT_TC_CONTROL_OFS);
     75	ctrl &= ~GT_TC_CONTROL_SELTC0_MSK;
     76	ctrl |= GT_TC_CONTROL_ENTC0_MSK;
     77	GT_WRITE(GT_TC_CONTROL_OFS, ctrl);
     78
     79	raw_spin_unlock(&gt641xx_timer_lock);
     80	return 0;
     81}
     82
     83static int gt641xx_timer0_set_periodic(struct clock_event_device *evt)
     84{
     85	u32 ctrl;
     86
     87	raw_spin_lock(&gt641xx_timer_lock);
     88
     89	ctrl = GT_READ(GT_TC_CONTROL_OFS);
     90	ctrl |= GT_TC_CONTROL_ENTC0_MSK | GT_TC_CONTROL_SELTC0_MSK;
     91	GT_WRITE(GT_TC_CONTROL_OFS, ctrl);
     92
     93	raw_spin_unlock(&gt641xx_timer_lock);
     94	return 0;
     95}
     96
     97static void gt641xx_timer0_event_handler(struct clock_event_device *dev)
     98{
     99}
    100
    101static struct clock_event_device gt641xx_timer0_clockevent = {
    102	.name			= "gt641xx-timer0",
    103	.features		= CLOCK_EVT_FEAT_PERIODIC |
    104				  CLOCK_EVT_FEAT_ONESHOT,
    105	.irq			= GT641XX_TIMER0_IRQ,
    106	.set_next_event		= gt641xx_timer0_set_next_event,
    107	.set_state_shutdown	= gt641xx_timer0_shutdown,
    108	.set_state_periodic	= gt641xx_timer0_set_periodic,
    109	.set_state_oneshot	= gt641xx_timer0_set_oneshot,
    110	.tick_resume		= gt641xx_timer0_shutdown,
    111	.event_handler		= gt641xx_timer0_event_handler,
    112};
    113
    114static irqreturn_t gt641xx_timer0_interrupt(int irq, void *dev_id)
    115{
    116	struct clock_event_device *cd = &gt641xx_timer0_clockevent;
    117
    118	cd->event_handler(cd);
    119
    120	return IRQ_HANDLED;
    121}
    122
    123static int __init gt641xx_timer0_clockevent_init(void)
    124{
    125	struct clock_event_device *cd;
    126
    127	if (!gt641xx_base_clock)
    128		return 0;
    129
    130	GT_WRITE(GT_TC0_OFS, gt641xx_base_clock / HZ);
    131
    132	cd = &gt641xx_timer0_clockevent;
    133	cd->rating = 200 + gt641xx_base_clock / 10000000;
    134	clockevent_set_clock(cd, gt641xx_base_clock);
    135	cd->max_delta_ns = clockevent_delta2ns(0x7fffffff, cd);
    136	cd->max_delta_ticks = 0x7fffffff;
    137	cd->min_delta_ns = clockevent_delta2ns(0x300, cd);
    138	cd->min_delta_ticks = 0x300;
    139	cd->cpumask = cpumask_of(0);
    140
    141	clockevents_register_device(&gt641xx_timer0_clockevent);
    142
    143	return request_irq(GT641XX_TIMER0_IRQ, gt641xx_timer0_interrupt,
    144			   IRQF_PERCPU | IRQF_TIMER, "gt641xx_timer0", NULL);
    145}
    146arch_initcall(gt641xx_timer0_clockevent_init);