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

mxs_timer.c (7498B)


      1// SPDX-License-Identifier: GPL-2.0+
      2//
      3//  Copyright (C) 2000-2001 Deep Blue Solutions
      4//  Copyright (C) 2002 Shane Nay (shane@minirl.com)
      5//  Copyright (C) 2006-2007 Pavel Pisa (ppisa@pikron.com)
      6//  Copyright (C) 2008 Juergen Beisert (kernel@pengutronix.de)
      7//  Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
      8
      9#include <linux/err.h>
     10#include <linux/interrupt.h>
     11#include <linux/irq.h>
     12#include <linux/clockchips.h>
     13#include <linux/clk.h>
     14#include <linux/of.h>
     15#include <linux/of_address.h>
     16#include <linux/of_irq.h>
     17#include <linux/stmp_device.h>
     18#include <linux/sched_clock.h>
     19
     20/*
     21 * There are 2 versions of the timrot on Freescale MXS-based SoCs.
     22 * The v1 on MX23 only gets 16 bits counter, while v2 on MX28
     23 * extends the counter to 32 bits.
     24 *
     25 * The implementation uses two timers, one for clock_event and
     26 * another for clocksource. MX28 uses timrot 0 and 1, while MX23
     27 * uses 0 and 2.
     28 */
     29
     30#define MX23_TIMROT_VERSION_OFFSET	0x0a0
     31#define MX28_TIMROT_VERSION_OFFSET	0x120
     32#define BP_TIMROT_MAJOR_VERSION		24
     33#define BV_TIMROT_VERSION_1		0x01
     34#define BV_TIMROT_VERSION_2		0x02
     35#define timrot_is_v1()	(timrot_major_version == BV_TIMROT_VERSION_1)
     36
     37/*
     38 * There are 4 registers for each timrotv2 instance, and 2 registers
     39 * for each timrotv1. So address step 0x40 in macros below strides
     40 * one instance of timrotv2 while two instances of timrotv1.
     41 *
     42 * As the result, HW_TIMROT_XXXn(1) defines the address of timrot1
     43 * on MX28 while timrot2 on MX23.
     44 */
     45/* common between v1 and v2 */
     46#define HW_TIMROT_ROTCTRL		0x00
     47#define HW_TIMROT_TIMCTRLn(n)		(0x20 + (n) * 0x40)
     48/* v1 only */
     49#define HW_TIMROT_TIMCOUNTn(n)		(0x30 + (n) * 0x40)
     50/* v2 only */
     51#define HW_TIMROT_RUNNING_COUNTn(n)	(0x30 + (n) * 0x40)
     52#define HW_TIMROT_FIXED_COUNTn(n)	(0x40 + (n) * 0x40)
     53
     54#define BM_TIMROT_TIMCTRLn_RELOAD	(1 << 6)
     55#define BM_TIMROT_TIMCTRLn_UPDATE	(1 << 7)
     56#define BM_TIMROT_TIMCTRLn_IRQ_EN	(1 << 14)
     57#define BM_TIMROT_TIMCTRLn_IRQ		(1 << 15)
     58#define BP_TIMROT_TIMCTRLn_SELECT	0
     59#define BV_TIMROTv1_TIMCTRLn_SELECT__32KHZ_XTAL		0x8
     60#define BV_TIMROTv2_TIMCTRLn_SELECT__32KHZ_XTAL		0xb
     61#define BV_TIMROTv2_TIMCTRLn_SELECT__TICK_ALWAYS	0xf
     62
     63static struct clock_event_device mxs_clockevent_device;
     64
     65static void __iomem *mxs_timrot_base;
     66static u32 timrot_major_version;
     67
     68static inline void timrot_irq_disable(void)
     69{
     70	__raw_writel(BM_TIMROT_TIMCTRLn_IRQ_EN, mxs_timrot_base +
     71		     HW_TIMROT_TIMCTRLn(0) + STMP_OFFSET_REG_CLR);
     72}
     73
     74static inline void timrot_irq_enable(void)
     75{
     76	__raw_writel(BM_TIMROT_TIMCTRLn_IRQ_EN, mxs_timrot_base +
     77		     HW_TIMROT_TIMCTRLn(0) + STMP_OFFSET_REG_SET);
     78}
     79
     80static void timrot_irq_acknowledge(void)
     81{
     82	__raw_writel(BM_TIMROT_TIMCTRLn_IRQ, mxs_timrot_base +
     83		     HW_TIMROT_TIMCTRLn(0) + STMP_OFFSET_REG_CLR);
     84}
     85
     86static u64 timrotv1_get_cycles(struct clocksource *cs)
     87{
     88	return ~((__raw_readl(mxs_timrot_base + HW_TIMROT_TIMCOUNTn(1))
     89			& 0xffff0000) >> 16);
     90}
     91
     92static int timrotv1_set_next_event(unsigned long evt,
     93					struct clock_event_device *dev)
     94{
     95	/* timrot decrements the count */
     96	__raw_writel(evt, mxs_timrot_base + HW_TIMROT_TIMCOUNTn(0));
     97
     98	return 0;
     99}
    100
    101static int timrotv2_set_next_event(unsigned long evt,
    102					struct clock_event_device *dev)
    103{
    104	/* timrot decrements the count */
    105	__raw_writel(evt, mxs_timrot_base + HW_TIMROT_FIXED_COUNTn(0));
    106
    107	return 0;
    108}
    109
    110static irqreturn_t mxs_timer_interrupt(int irq, void *dev_id)
    111{
    112	struct clock_event_device *evt = dev_id;
    113
    114	timrot_irq_acknowledge();
    115	evt->event_handler(evt);
    116
    117	return IRQ_HANDLED;
    118}
    119
    120static void mxs_irq_clear(char *state)
    121{
    122	/* Disable interrupt in timer module */
    123	timrot_irq_disable();
    124
    125	/* Set event time into the furthest future */
    126	if (timrot_is_v1())
    127		__raw_writel(0xffff, mxs_timrot_base + HW_TIMROT_TIMCOUNTn(1));
    128	else
    129		__raw_writel(0xffffffff,
    130			     mxs_timrot_base + HW_TIMROT_FIXED_COUNTn(1));
    131
    132	/* Clear pending interrupt */
    133	timrot_irq_acknowledge();
    134	pr_debug("%s: changing mode to %s\n", __func__, state);
    135}
    136
    137static int mxs_shutdown(struct clock_event_device *evt)
    138{
    139	mxs_irq_clear("shutdown");
    140
    141	return 0;
    142}
    143
    144static int mxs_set_oneshot(struct clock_event_device *evt)
    145{
    146	if (clockevent_state_oneshot(evt))
    147		mxs_irq_clear("oneshot");
    148	timrot_irq_enable();
    149	return 0;
    150}
    151
    152static struct clock_event_device mxs_clockevent_device = {
    153	.name			= "mxs_timrot",
    154	.features		= CLOCK_EVT_FEAT_ONESHOT,
    155	.set_state_shutdown	= mxs_shutdown,
    156	.set_state_oneshot	= mxs_set_oneshot,
    157	.tick_resume		= mxs_shutdown,
    158	.set_next_event		= timrotv2_set_next_event,
    159	.rating			= 200,
    160};
    161
    162static int __init mxs_clockevent_init(struct clk *timer_clk)
    163{
    164	if (timrot_is_v1())
    165		mxs_clockevent_device.set_next_event = timrotv1_set_next_event;
    166	mxs_clockevent_device.cpumask = cpumask_of(0);
    167	clockevents_config_and_register(&mxs_clockevent_device,
    168					clk_get_rate(timer_clk),
    169					timrot_is_v1() ? 0xf : 0x2,
    170					timrot_is_v1() ? 0xfffe : 0xfffffffe);
    171
    172	return 0;
    173}
    174
    175static struct clocksource clocksource_mxs = {
    176	.name		= "mxs_timer",
    177	.rating		= 200,
    178	.read		= timrotv1_get_cycles,
    179	.mask		= CLOCKSOURCE_MASK(16),
    180	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
    181};
    182
    183static u64 notrace mxs_read_sched_clock_v2(void)
    184{
    185	return ~readl_relaxed(mxs_timrot_base + HW_TIMROT_RUNNING_COUNTn(1));
    186}
    187
    188static int __init mxs_clocksource_init(struct clk *timer_clk)
    189{
    190	unsigned int c = clk_get_rate(timer_clk);
    191
    192	if (timrot_is_v1())
    193		clocksource_register_hz(&clocksource_mxs, c);
    194	else {
    195		clocksource_mmio_init(mxs_timrot_base + HW_TIMROT_RUNNING_COUNTn(1),
    196			"mxs_timer", c, 200, 32, clocksource_mmio_readl_down);
    197		sched_clock_register(mxs_read_sched_clock_v2, 32, c);
    198	}
    199
    200	return 0;
    201}
    202
    203static int __init mxs_timer_init(struct device_node *np)
    204{
    205	struct clk *timer_clk;
    206	int irq, ret;
    207
    208	mxs_timrot_base = of_iomap(np, 0);
    209	WARN_ON(!mxs_timrot_base);
    210
    211	timer_clk = of_clk_get(np, 0);
    212	if (IS_ERR(timer_clk)) {
    213		pr_err("%s: failed to get clk\n", __func__);
    214		return PTR_ERR(timer_clk);
    215	}
    216
    217	ret = clk_prepare_enable(timer_clk);
    218	if (ret)
    219		return ret;
    220
    221	/*
    222	 * Initialize timers to a known state
    223	 */
    224	stmp_reset_block(mxs_timrot_base + HW_TIMROT_ROTCTRL);
    225
    226	/* get timrot version */
    227	timrot_major_version = __raw_readl(mxs_timrot_base +
    228			(of_device_is_compatible(np, "fsl,imx23-timrot") ?
    229						MX23_TIMROT_VERSION_OFFSET :
    230						MX28_TIMROT_VERSION_OFFSET));
    231	timrot_major_version >>= BP_TIMROT_MAJOR_VERSION;
    232
    233	/* one for clock_event */
    234	__raw_writel((timrot_is_v1() ?
    235			BV_TIMROTv1_TIMCTRLn_SELECT__32KHZ_XTAL :
    236			BV_TIMROTv2_TIMCTRLn_SELECT__TICK_ALWAYS) |
    237			BM_TIMROT_TIMCTRLn_UPDATE |
    238			BM_TIMROT_TIMCTRLn_IRQ_EN,
    239			mxs_timrot_base + HW_TIMROT_TIMCTRLn(0));
    240
    241	/* another for clocksource */
    242	__raw_writel((timrot_is_v1() ?
    243			BV_TIMROTv1_TIMCTRLn_SELECT__32KHZ_XTAL :
    244			BV_TIMROTv2_TIMCTRLn_SELECT__TICK_ALWAYS) |
    245			BM_TIMROT_TIMCTRLn_RELOAD,
    246			mxs_timrot_base + HW_TIMROT_TIMCTRLn(1));
    247
    248	/* set clocksource timer fixed count to the maximum */
    249	if (timrot_is_v1())
    250		__raw_writel(0xffff,
    251			mxs_timrot_base + HW_TIMROT_TIMCOUNTn(1));
    252	else
    253		__raw_writel(0xffffffff,
    254			mxs_timrot_base + HW_TIMROT_FIXED_COUNTn(1));
    255
    256	/* init and register the timer to the framework */
    257	ret = mxs_clocksource_init(timer_clk);
    258	if (ret)
    259		return ret;
    260
    261	ret = mxs_clockevent_init(timer_clk);
    262	if (ret)
    263		return ret;
    264
    265	/* Make irqs happen */
    266	irq = irq_of_parse_and_map(np, 0);
    267	if (irq <= 0)
    268		return -EINVAL;
    269
    270	return request_irq(irq, mxs_timer_interrupt, IRQF_TIMER | IRQF_IRQPOLL,
    271			   "MXS Timer Tick", &mxs_clockevent_device);
    272}
    273TIMER_OF_DECLARE(mxs, "fsl,timrot", mxs_timer_init);