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 (8569B)


      1/*
      2 * Copyright (C) 2013-2014 Altera Corporation
      3 * Copyright (C) 2010 Tobias Klauser <tklauser@distanz.ch>
      4 * Copyright (C) 2004 Microtronix Datacom Ltd.
      5 *
      6 * This file is subject to the terms and conditions of the GNU General Public
      7 * License. See the file "COPYING" in the main directory of this archive
      8 * for more details.
      9 */
     10
     11#include <linux/export.h>
     12#include <linux/interrupt.h>
     13#include <linux/clockchips.h>
     14#include <linux/clocksource.h>
     15#include <linux/delay.h>
     16#include <linux/of.h>
     17#include <linux/of_address.h>
     18#include <linux/of_irq.h>
     19#include <linux/io.h>
     20#include <linux/slab.h>
     21
     22#define ALTR_TIMER_COMPATIBLE		"altr,timer-1.0"
     23
     24#define ALTERA_TIMER_STATUS_REG	0
     25#define ALTERA_TIMER_CONTROL_REG	4
     26#define ALTERA_TIMER_PERIODL_REG	8
     27#define ALTERA_TIMER_PERIODH_REG	12
     28#define ALTERA_TIMER_SNAPL_REG		16
     29#define ALTERA_TIMER_SNAPH_REG		20
     30
     31#define ALTERA_TIMER_CONTROL_ITO_MSK	(0x1)
     32#define ALTERA_TIMER_CONTROL_CONT_MSK	(0x2)
     33#define ALTERA_TIMER_CONTROL_START_MSK	(0x4)
     34#define ALTERA_TIMER_CONTROL_STOP_MSK	(0x8)
     35
     36struct nios2_timer {
     37	void __iomem *base;
     38	unsigned long freq;
     39};
     40
     41struct nios2_clockevent_dev {
     42	struct nios2_timer timer;
     43	struct clock_event_device ced;
     44};
     45
     46struct nios2_clocksource {
     47	struct nios2_timer timer;
     48	struct clocksource cs;
     49};
     50
     51static inline struct nios2_clockevent_dev *
     52	to_nios2_clkevent(struct clock_event_device *evt)
     53{
     54	return container_of(evt, struct nios2_clockevent_dev, ced);
     55}
     56
     57static inline struct nios2_clocksource *
     58	to_nios2_clksource(struct clocksource *cs)
     59{
     60	return container_of(cs, struct nios2_clocksource, cs);
     61}
     62
     63static u16 timer_readw(struct nios2_timer *timer, u32 offs)
     64{
     65	return readw(timer->base + offs);
     66}
     67
     68static void timer_writew(struct nios2_timer *timer, u16 val, u32 offs)
     69{
     70	writew(val, timer->base + offs);
     71}
     72
     73static inline unsigned long read_timersnapshot(struct nios2_timer *timer)
     74{
     75	unsigned long count;
     76
     77	timer_writew(timer, 0, ALTERA_TIMER_SNAPL_REG);
     78	count = timer_readw(timer, ALTERA_TIMER_SNAPH_REG) << 16 |
     79		timer_readw(timer, ALTERA_TIMER_SNAPL_REG);
     80
     81	return count;
     82}
     83
     84static u64 nios2_timer_read(struct clocksource *cs)
     85{
     86	struct nios2_clocksource *nios2_cs = to_nios2_clksource(cs);
     87	unsigned long flags;
     88	u32 count;
     89
     90	local_irq_save(flags);
     91	count = read_timersnapshot(&nios2_cs->timer);
     92	local_irq_restore(flags);
     93
     94	/* Counter is counting down */
     95	return ~count;
     96}
     97
     98static struct nios2_clocksource nios2_cs = {
     99	.cs = {
    100		.name	= "nios2-clksrc",
    101		.rating	= 250,
    102		.read	= nios2_timer_read,
    103		.mask	= CLOCKSOURCE_MASK(32),
    104		.flags	= CLOCK_SOURCE_IS_CONTINUOUS,
    105	},
    106};
    107
    108cycles_t get_cycles(void)
    109{
    110	/* Only read timer if it has been initialized */
    111	if (nios2_cs.timer.base)
    112		return nios2_timer_read(&nios2_cs.cs);
    113	return 0;
    114}
    115EXPORT_SYMBOL(get_cycles);
    116
    117static void nios2_timer_start(struct nios2_timer *timer)
    118{
    119	u16 ctrl;
    120
    121	ctrl = timer_readw(timer, ALTERA_TIMER_CONTROL_REG);
    122	ctrl |= ALTERA_TIMER_CONTROL_START_MSK;
    123	timer_writew(timer, ctrl, ALTERA_TIMER_CONTROL_REG);
    124}
    125
    126static void nios2_timer_stop(struct nios2_timer *timer)
    127{
    128	u16 ctrl;
    129
    130	ctrl = timer_readw(timer, ALTERA_TIMER_CONTROL_REG);
    131	ctrl |= ALTERA_TIMER_CONTROL_STOP_MSK;
    132	timer_writew(timer, ctrl, ALTERA_TIMER_CONTROL_REG);
    133}
    134
    135static void nios2_timer_config(struct nios2_timer *timer, unsigned long period,
    136			       bool periodic)
    137{
    138	u16 ctrl;
    139
    140	/* The timer's actual period is one cycle greater than the value
    141	 * stored in the period register. */
    142	 period--;
    143
    144	ctrl = timer_readw(timer, ALTERA_TIMER_CONTROL_REG);
    145	/* stop counter */
    146	timer_writew(timer, ctrl | ALTERA_TIMER_CONTROL_STOP_MSK,
    147		ALTERA_TIMER_CONTROL_REG);
    148
    149	/* write new count */
    150	timer_writew(timer, period, ALTERA_TIMER_PERIODL_REG);
    151	timer_writew(timer, period >> 16, ALTERA_TIMER_PERIODH_REG);
    152
    153	ctrl |= ALTERA_TIMER_CONTROL_START_MSK | ALTERA_TIMER_CONTROL_ITO_MSK;
    154	if (periodic)
    155		ctrl |= ALTERA_TIMER_CONTROL_CONT_MSK;
    156	else
    157		ctrl &= ~ALTERA_TIMER_CONTROL_CONT_MSK;
    158	timer_writew(timer, ctrl, ALTERA_TIMER_CONTROL_REG);
    159}
    160
    161static int nios2_timer_set_next_event(unsigned long delta,
    162	struct clock_event_device *evt)
    163{
    164	struct nios2_clockevent_dev *nios2_ced = to_nios2_clkevent(evt);
    165
    166	nios2_timer_config(&nios2_ced->timer, delta, false);
    167
    168	return 0;
    169}
    170
    171static int nios2_timer_shutdown(struct clock_event_device *evt)
    172{
    173	struct nios2_clockevent_dev *nios2_ced = to_nios2_clkevent(evt);
    174	struct nios2_timer *timer = &nios2_ced->timer;
    175
    176	nios2_timer_stop(timer);
    177	return 0;
    178}
    179
    180static int nios2_timer_set_periodic(struct clock_event_device *evt)
    181{
    182	unsigned long period;
    183	struct nios2_clockevent_dev *nios2_ced = to_nios2_clkevent(evt);
    184	struct nios2_timer *timer = &nios2_ced->timer;
    185
    186	period = DIV_ROUND_UP(timer->freq, HZ);
    187	nios2_timer_config(timer, period, true);
    188	return 0;
    189}
    190
    191static int nios2_timer_resume(struct clock_event_device *evt)
    192{
    193	struct nios2_clockevent_dev *nios2_ced = to_nios2_clkevent(evt);
    194	struct nios2_timer *timer = &nios2_ced->timer;
    195
    196	nios2_timer_start(timer);
    197	return 0;
    198}
    199
    200irqreturn_t timer_interrupt(int irq, void *dev_id)
    201{
    202	struct clock_event_device *evt = (struct clock_event_device *) dev_id;
    203	struct nios2_clockevent_dev *nios2_ced = to_nios2_clkevent(evt);
    204
    205	/* Clear the interrupt condition */
    206	timer_writew(&nios2_ced->timer, 0, ALTERA_TIMER_STATUS_REG);
    207	evt->event_handler(evt);
    208
    209	return IRQ_HANDLED;
    210}
    211
    212static int __init nios2_timer_get_base_and_freq(struct device_node *np,
    213				void __iomem **base, u32 *freq)
    214{
    215	*base = of_iomap(np, 0);
    216	if (!*base) {
    217		pr_crit("Unable to map reg for %pOFn\n", np);
    218		return -ENXIO;
    219	}
    220
    221	if (of_property_read_u32(np, "clock-frequency", freq)) {
    222		pr_crit("Unable to get %pOFn clock frequency\n", np);
    223		return -EINVAL;
    224	}
    225
    226	return 0;
    227}
    228
    229static struct nios2_clockevent_dev nios2_ce = {
    230	.ced = {
    231		.name = "nios2-clkevent",
    232		.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
    233		.rating = 250,
    234		.shift = 32,
    235		.set_next_event = nios2_timer_set_next_event,
    236		.set_state_shutdown = nios2_timer_shutdown,
    237		.set_state_periodic = nios2_timer_set_periodic,
    238		.set_state_oneshot = nios2_timer_shutdown,
    239		.tick_resume = nios2_timer_resume,
    240	},
    241};
    242
    243static __init int nios2_clockevent_init(struct device_node *timer)
    244{
    245	void __iomem *iobase;
    246	u32 freq;
    247	int irq, ret;
    248
    249	ret = nios2_timer_get_base_and_freq(timer, &iobase, &freq);
    250	if (ret)
    251		return ret;
    252
    253	irq = irq_of_parse_and_map(timer, 0);
    254	if (!irq) {
    255		pr_crit("Unable to parse timer irq\n");
    256		return -EINVAL;
    257	}
    258
    259	nios2_ce.timer.base = iobase;
    260	nios2_ce.timer.freq = freq;
    261
    262	nios2_ce.ced.cpumask = cpumask_of(0);
    263	nios2_ce.ced.irq = irq;
    264
    265	nios2_timer_stop(&nios2_ce.timer);
    266	/* clear pending interrupt */
    267	timer_writew(&nios2_ce.timer, 0, ALTERA_TIMER_STATUS_REG);
    268
    269	ret = request_irq(irq, timer_interrupt, IRQF_TIMER, timer->name,
    270			  &nios2_ce.ced);
    271	if (ret) {
    272		pr_crit("Unable to setup timer irq\n");
    273		return ret;
    274	}
    275
    276	clockevents_config_and_register(&nios2_ce.ced, freq, 1, ULONG_MAX);
    277
    278	return 0;
    279}
    280
    281static __init int nios2_clocksource_init(struct device_node *timer)
    282{
    283	unsigned int ctrl;
    284	void __iomem *iobase;
    285	u32 freq;
    286	int ret;
    287
    288	ret = nios2_timer_get_base_and_freq(timer, &iobase, &freq);
    289	if (ret)
    290		return ret;
    291
    292	nios2_cs.timer.base = iobase;
    293	nios2_cs.timer.freq = freq;
    294
    295	ret = clocksource_register_hz(&nios2_cs.cs, freq);
    296	if (ret)
    297		return ret;
    298
    299	timer_writew(&nios2_cs.timer, USHRT_MAX, ALTERA_TIMER_PERIODL_REG);
    300	timer_writew(&nios2_cs.timer, USHRT_MAX, ALTERA_TIMER_PERIODH_REG);
    301
    302	/* interrupt disable + continuous + start */
    303	ctrl = ALTERA_TIMER_CONTROL_CONT_MSK | ALTERA_TIMER_CONTROL_START_MSK;
    304	timer_writew(&nios2_cs.timer, ctrl, ALTERA_TIMER_CONTROL_REG);
    305
    306	/* Calibrate the delay loop directly */
    307	lpj_fine = freq / HZ;
    308
    309	return 0;
    310}
    311
    312/*
    313 * The first timer instance will use as a clockevent. If there are two or
    314 * more instances, the second one gets used as clocksource and all
    315 * others are unused.
    316*/
    317static int __init nios2_time_init(struct device_node *timer)
    318{
    319	static int num_called;
    320	int ret;
    321
    322	switch (num_called) {
    323	case 0:
    324		ret = nios2_clockevent_init(timer);
    325		break;
    326	case 1:
    327		ret = nios2_clocksource_init(timer);
    328		break;
    329	default:
    330		ret = 0;
    331		break;
    332	}
    333
    334	num_called++;
    335
    336	return ret;
    337}
    338
    339void read_persistent_clock64(struct timespec64 *ts)
    340{
    341	ts->tv_sec = mktime64(2007, 1, 1, 0, 0, 0);
    342	ts->tv_nsec = 0;
    343}
    344
    345void __init time_init(void)
    346{
    347	struct device_node *np;
    348	int count = 0;
    349
    350	for_each_compatible_node(np, NULL,  ALTR_TIMER_COMPATIBLE)
    351		count++;
    352
    353	if (count < 2)
    354		panic("%d timer is found, it needs 2 timers in system\n", count);
    355
    356	timer_probe();
    357}
    358
    359TIMER_OF_DECLARE(nios2_timer, ALTR_TIMER_COMPATIBLE, nios2_time_init);