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-txx9.c (6686B)


      1/*
      2 * This file is subject to the terms and conditions of the GNU General Public
      3 * License.  See the file "COPYING" in the main directory of this archive
      4 * for more details.
      5 *
      6 * Based on linux/arch/mips/kernel/cevt-r4k.c,
      7 *	    linux/arch/mips/jmr3927/rbhma3100/setup.c
      8 *
      9 * Copyright 2001 MontaVista Software Inc.
     10 * Copyright (C) 2000-2001 Toshiba Corporation
     11 * Copyright (C) 2007 MIPS Technologies, Inc.
     12 * Copyright (C) 2007 Ralf Baechle <ralf@linux-mips.org>
     13 */
     14#include <linux/init.h>
     15#include <linux/interrupt.h>
     16#include <linux/irq.h>
     17#include <linux/sched_clock.h>
     18#include <asm/time.h>
     19#include <asm/txx9tmr.h>
     20
     21#define TCR_BASE (TXx9_TMTCR_CCDE | TXx9_TMTCR_CRE | TXx9_TMTCR_TMODE_ITVL)
     22#define TIMER_CCD	0	/* 1/2 */
     23#define TIMER_CLK(imclk)	((imclk) / (2 << TIMER_CCD))
     24
     25struct txx9_clocksource {
     26	struct clocksource cs;
     27	struct txx9_tmr_reg __iomem *tmrptr;
     28};
     29
     30static u64 txx9_cs_read(struct clocksource *cs)
     31{
     32	struct txx9_clocksource *txx9_cs =
     33		container_of(cs, struct txx9_clocksource, cs);
     34	return __raw_readl(&txx9_cs->tmrptr->trr);
     35}
     36
     37/* Use 1 bit smaller width to use full bits in that width */
     38#define TXX9_CLOCKSOURCE_BITS (TXX9_TIMER_BITS - 1)
     39
     40static struct txx9_clocksource txx9_clocksource = {
     41	.cs = {
     42		.name		= "TXx9",
     43		.rating		= 200,
     44		.read		= txx9_cs_read,
     45		.mask		= CLOCKSOURCE_MASK(TXX9_CLOCKSOURCE_BITS),
     46		.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
     47	},
     48};
     49
     50static u64 notrace txx9_read_sched_clock(void)
     51{
     52	return __raw_readl(&txx9_clocksource.tmrptr->trr);
     53}
     54
     55void __init txx9_clocksource_init(unsigned long baseaddr,
     56				  unsigned int imbusclk)
     57{
     58	struct txx9_tmr_reg __iomem *tmrptr;
     59
     60	clocksource_register_hz(&txx9_clocksource.cs, TIMER_CLK(imbusclk));
     61
     62	tmrptr = ioremap(baseaddr, sizeof(struct txx9_tmr_reg));
     63	__raw_writel(TCR_BASE, &tmrptr->tcr);
     64	__raw_writel(0, &tmrptr->tisr);
     65	__raw_writel(TIMER_CCD, &tmrptr->ccdr);
     66	__raw_writel(TXx9_TMITMR_TZCE, &tmrptr->itmr);
     67	__raw_writel(1 << TXX9_CLOCKSOURCE_BITS, &tmrptr->cpra);
     68	__raw_writel(TCR_BASE | TXx9_TMTCR_TCE, &tmrptr->tcr);
     69	txx9_clocksource.tmrptr = tmrptr;
     70
     71	sched_clock_register(txx9_read_sched_clock, TXX9_CLOCKSOURCE_BITS,
     72			     TIMER_CLK(imbusclk));
     73}
     74
     75struct txx9_clock_event_device {
     76	struct clock_event_device cd;
     77	struct txx9_tmr_reg __iomem *tmrptr;
     78};
     79
     80static void txx9tmr_stop_and_clear(struct txx9_tmr_reg __iomem *tmrptr)
     81{
     82	/* stop and reset counter */
     83	__raw_writel(TCR_BASE, &tmrptr->tcr);
     84	/* clear pending interrupt */
     85	__raw_writel(0, &tmrptr->tisr);
     86}
     87
     88static int txx9tmr_set_state_periodic(struct clock_event_device *evt)
     89{
     90	struct txx9_clock_event_device *txx9_cd =
     91		container_of(evt, struct txx9_clock_event_device, cd);
     92	struct txx9_tmr_reg __iomem *tmrptr = txx9_cd->tmrptr;
     93
     94	txx9tmr_stop_and_clear(tmrptr);
     95
     96	__raw_writel(TXx9_TMITMR_TIIE | TXx9_TMITMR_TZCE, &tmrptr->itmr);
     97	/* start timer */
     98	__raw_writel(((u64)(NSEC_PER_SEC / HZ) * evt->mult) >> evt->shift,
     99		     &tmrptr->cpra);
    100	__raw_writel(TCR_BASE | TXx9_TMTCR_TCE, &tmrptr->tcr);
    101	return 0;
    102}
    103
    104static int txx9tmr_set_state_oneshot(struct clock_event_device *evt)
    105{
    106	struct txx9_clock_event_device *txx9_cd =
    107		container_of(evt, struct txx9_clock_event_device, cd);
    108	struct txx9_tmr_reg __iomem *tmrptr = txx9_cd->tmrptr;
    109
    110	txx9tmr_stop_and_clear(tmrptr);
    111	__raw_writel(TXx9_TMITMR_TIIE, &tmrptr->itmr);
    112	return 0;
    113}
    114
    115static int txx9tmr_set_state_shutdown(struct clock_event_device *evt)
    116{
    117	struct txx9_clock_event_device *txx9_cd =
    118		container_of(evt, struct txx9_clock_event_device, cd);
    119	struct txx9_tmr_reg __iomem *tmrptr = txx9_cd->tmrptr;
    120
    121	txx9tmr_stop_and_clear(tmrptr);
    122	__raw_writel(0, &tmrptr->itmr);
    123	return 0;
    124}
    125
    126static int txx9tmr_tick_resume(struct clock_event_device *evt)
    127{
    128	struct txx9_clock_event_device *txx9_cd =
    129		container_of(evt, struct txx9_clock_event_device, cd);
    130	struct txx9_tmr_reg __iomem *tmrptr = txx9_cd->tmrptr;
    131
    132	txx9tmr_stop_and_clear(tmrptr);
    133	__raw_writel(TIMER_CCD, &tmrptr->ccdr);
    134	__raw_writel(0, &tmrptr->itmr);
    135	return 0;
    136}
    137
    138static int txx9tmr_set_next_event(unsigned long delta,
    139				  struct clock_event_device *evt)
    140{
    141	struct txx9_clock_event_device *txx9_cd =
    142		container_of(evt, struct txx9_clock_event_device, cd);
    143	struct txx9_tmr_reg __iomem *tmrptr = txx9_cd->tmrptr;
    144
    145	txx9tmr_stop_and_clear(tmrptr);
    146	/* start timer */
    147	__raw_writel(delta, &tmrptr->cpra);
    148	__raw_writel(TCR_BASE | TXx9_TMTCR_TCE, &tmrptr->tcr);
    149	return 0;
    150}
    151
    152static struct txx9_clock_event_device txx9_clock_event_device = {
    153	.cd = {
    154		.name			= "TXx9",
    155		.features		= CLOCK_EVT_FEAT_PERIODIC |
    156					  CLOCK_EVT_FEAT_ONESHOT,
    157		.rating			= 200,
    158		.set_state_shutdown	= txx9tmr_set_state_shutdown,
    159		.set_state_periodic	= txx9tmr_set_state_periodic,
    160		.set_state_oneshot	= txx9tmr_set_state_oneshot,
    161		.tick_resume		= txx9tmr_tick_resume,
    162		.set_next_event		= txx9tmr_set_next_event,
    163	},
    164};
    165
    166static irqreturn_t txx9tmr_interrupt(int irq, void *dev_id)
    167{
    168	struct txx9_clock_event_device *txx9_cd = dev_id;
    169	struct clock_event_device *cd = &txx9_cd->cd;
    170	struct txx9_tmr_reg __iomem *tmrptr = txx9_cd->tmrptr;
    171
    172	__raw_writel(0, &tmrptr->tisr); /* ack interrupt */
    173	cd->event_handler(cd);
    174	return IRQ_HANDLED;
    175}
    176
    177void __init txx9_clockevent_init(unsigned long baseaddr, int irq,
    178				 unsigned int imbusclk)
    179{
    180	struct clock_event_device *cd = &txx9_clock_event_device.cd;
    181	struct txx9_tmr_reg __iomem *tmrptr;
    182
    183	tmrptr = ioremap(baseaddr, sizeof(struct txx9_tmr_reg));
    184	txx9tmr_stop_and_clear(tmrptr);
    185	__raw_writel(TIMER_CCD, &tmrptr->ccdr);
    186	__raw_writel(0, &tmrptr->itmr);
    187	txx9_clock_event_device.tmrptr = tmrptr;
    188
    189	clockevent_set_clock(cd, TIMER_CLK(imbusclk));
    190	cd->max_delta_ns =
    191		clockevent_delta2ns(0xffffffff >> (32 - TXX9_TIMER_BITS), cd);
    192	cd->max_delta_ticks = 0xffffffff >> (32 - TXX9_TIMER_BITS);
    193	cd->min_delta_ns = clockevent_delta2ns(0xf, cd);
    194	cd->min_delta_ticks = 0xf;
    195	cd->irq = irq;
    196	cd->cpumask = cpumask_of(0);
    197	clockevents_register_device(cd);
    198	if (request_irq(irq, txx9tmr_interrupt, IRQF_PERCPU | IRQF_TIMER,
    199			"txx9tmr", &txx9_clock_event_device))
    200		pr_err("Failed to request irq %d (txx9tmr)\n", irq);
    201	printk(KERN_INFO "TXx9: clockevent device at 0x%lx, irq %d\n",
    202	       baseaddr, irq);
    203}
    204
    205void __init txx9_tmr_init(unsigned long baseaddr)
    206{
    207	struct txx9_tmr_reg __iomem *tmrptr;
    208
    209	tmrptr = ioremap(baseaddr, sizeof(struct txx9_tmr_reg));
    210	/* Start once to make CounterResetEnable effective */
    211	__raw_writel(TXx9_TMTCR_CRE | TXx9_TMTCR_TCE, &tmrptr->tcr);
    212	/* Stop and reset the counter */
    213	__raw_writel(TXx9_TMTCR_CRE, &tmrptr->tcr);
    214	__raw_writel(0, &tmrptr->tisr);
    215	__raw_writel(0xffffffff, &tmrptr->cpra);
    216	__raw_writel(0, &tmrptr->itmr);
    217	__raw_writel(0, &tmrptr->ccdr);
    218	__raw_writel(0, &tmrptr->pgmr);
    219	iounmap(tmrptr);
    220}