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-rt3352.c (3846B)


      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 * Copyright (C) 2013 by John Crispin <john@phrozen.org>
      7 */
      8
      9#include <linux/clockchips.h>
     10#include <linux/clocksource.h>
     11#include <linux/interrupt.h>
     12#include <linux/reset.h>
     13#include <linux/init.h>
     14#include <linux/time.h>
     15#include <linux/of.h>
     16#include <linux/of_irq.h>
     17#include <linux/of_address.h>
     18
     19#include <asm/mach-ralink/ralink_regs.h>
     20
     21#define SYSTICK_FREQ		(50 * 1000)
     22
     23#define SYSTICK_CONFIG		0x00
     24#define SYSTICK_COMPARE		0x04
     25#define SYSTICK_COUNT		0x08
     26
     27/* route systick irq to mips irq 7 instead of the r4k-timer */
     28#define CFG_EXT_STK_EN		0x2
     29/* enable the counter */
     30#define CFG_CNT_EN		0x1
     31
     32struct systick_device {
     33	void __iomem *membase;
     34	struct clock_event_device dev;
     35	int irq_requested;
     36	int freq_scale;
     37};
     38
     39static int systick_set_oneshot(struct clock_event_device *evt);
     40static int systick_shutdown(struct clock_event_device *evt);
     41
     42static int systick_next_event(unsigned long delta,
     43				struct clock_event_device *evt)
     44{
     45	struct systick_device *sdev;
     46	u32 count;
     47
     48	sdev = container_of(evt, struct systick_device, dev);
     49	count = ioread32(sdev->membase + SYSTICK_COUNT);
     50	count = (count + delta) % SYSTICK_FREQ;
     51	iowrite32(count, sdev->membase + SYSTICK_COMPARE);
     52
     53	return 0;
     54}
     55
     56static void systick_event_handler(struct clock_event_device *dev)
     57{
     58	/* noting to do here */
     59}
     60
     61static irqreturn_t systick_interrupt(int irq, void *dev_id)
     62{
     63	struct clock_event_device *dev = (struct clock_event_device *) dev_id;
     64
     65	dev->event_handler(dev);
     66
     67	return IRQ_HANDLED;
     68}
     69
     70static struct systick_device systick = {
     71	.dev = {
     72		/*
     73		 * cevt-r4k uses 300, make sure systick
     74		 * gets used if available
     75		 */
     76		.rating			= 310,
     77		.features		= CLOCK_EVT_FEAT_ONESHOT,
     78		.set_next_event		= systick_next_event,
     79		.set_state_shutdown	= systick_shutdown,
     80		.set_state_oneshot	= systick_set_oneshot,
     81		.event_handler		= systick_event_handler,
     82	},
     83};
     84
     85static int systick_shutdown(struct clock_event_device *evt)
     86{
     87	struct systick_device *sdev;
     88
     89	sdev = container_of(evt, struct systick_device, dev);
     90
     91	if (sdev->irq_requested)
     92		free_irq(systick.dev.irq, &systick.dev);
     93	sdev->irq_requested = 0;
     94	iowrite32(0, systick.membase + SYSTICK_CONFIG);
     95
     96	return 0;
     97}
     98
     99static int systick_set_oneshot(struct clock_event_device *evt)
    100{
    101	const char *name = systick.dev.name;
    102	struct systick_device *sdev;
    103	int irq = systick.dev.irq;
    104
    105	sdev = container_of(evt, struct systick_device, dev);
    106
    107	if (!sdev->irq_requested) {
    108		if (request_irq(irq, systick_interrupt,
    109				IRQF_PERCPU | IRQF_TIMER, name, &systick.dev))
    110			pr_err("Failed to request irq %d (%s)\n", irq, name);
    111	}
    112	sdev->irq_requested = 1;
    113	iowrite32(CFG_EXT_STK_EN | CFG_CNT_EN,
    114		  systick.membase + SYSTICK_CONFIG);
    115
    116	return 0;
    117}
    118
    119static int __init ralink_systick_init(struct device_node *np)
    120{
    121	int ret;
    122
    123	systick.membase = of_iomap(np, 0);
    124	if (!systick.membase)
    125		return -ENXIO;
    126
    127	systick.dev.name = np->name;
    128	clockevents_calc_mult_shift(&systick.dev, SYSTICK_FREQ, 60);
    129	systick.dev.max_delta_ns = clockevent_delta2ns(0x7fff, &systick.dev);
    130	systick.dev.max_delta_ticks = 0x7fff;
    131	systick.dev.min_delta_ns = clockevent_delta2ns(0x3, &systick.dev);
    132	systick.dev.min_delta_ticks = 0x3;
    133	systick.dev.irq = irq_of_parse_and_map(np, 0);
    134	if (!systick.dev.irq) {
    135		pr_err("%pOFn: request_irq failed", np);
    136		return -EINVAL;
    137	}
    138
    139	ret = clocksource_mmio_init(systick.membase + SYSTICK_COUNT, np->name,
    140				    SYSTICK_FREQ, 301, 16,
    141				    clocksource_mmio_readl_up);
    142	if (ret)
    143		return ret;
    144
    145	clockevents_register_device(&systick.dev);
    146
    147	pr_info("%pOFn: running - mult: %d, shift: %d\n",
    148			np, systick.dev.mult, systick.dev.shift);
    149
    150	return 0;
    151}
    152
    153TIMER_OF_DECLARE(systick, "ralink,cevt-systick", ralink_systick_init);