Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d8005e6b authored by Vineet Gupta's avatar Vineet Gupta
Browse files

ARC: Timers/counters/delay management



ARC700 includes 2 in-core 32bit timers TIMER0 and TIMER1.
Both have exactly same capabilies.

* programmable to count from TIMER<n>_CNT to TIMER<n>_LIMIT
* for count 0 and LIMIT ~1, provides a free-running counter by
    auto-wrapping when limit is reached.
* optionally interrupt when LIMIT is reached (oneshot event semantics)
* rearming the interrupt provides periodic semantics
* run at CPU clk

ARC Linux uses TIMER0 for clockevent (periodic/oneshot) and TIMER1 for
clocksource (free-running clock).

Newer cores provide RTSC insn which gives a 64bit cpu clk snapshot hence
is more apt for clocksource when available.

SMP poses a bit of challenge for global timekeeping clocksource /
sched_clock() backend:
 -TIMER1 based local clocks are out-of-sync hence can't be used
  (thus we default to jiffies based cs as well as sched_clock() one/both
  of which platform can override with it's specific hardware assist)
 -RTSC is only allowed in SMP if it's cross-core-sync (Kconfig glue
  ensures that) and thus usable for both requirements.

Signed-off-by: default avatarVineet Gupta <vgupta@synopsys.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
parent bf90e1ea
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -47,6 +47,17 @@
#define AUX_ITRIGGER		0x40d
#define AUX_IPULSE		0x415

/* Timer related Aux registers */
#define ARC_REG_TIMER0_LIMIT	0x23	/* timer 0 limit */
#define ARC_REG_TIMER0_CTRL	0x22	/* timer 0 control */
#define ARC_REG_TIMER0_CNT	0x21	/* timer 0 count */
#define ARC_REG_TIMER1_LIMIT	0x102	/* timer 1 limit */
#define ARC_REG_TIMER1_CTRL	0x101	/* timer 1 control */
#define ARC_REG_TIMER1_CNT	0x100	/* timer 1 count */

#define TIMER_CTRL_IE		(1 << 0) /* Interupt when Count reachs limit */
#define TIMER_CTRL_NH		(1 << 1) /* Count only when CPU NOT halted */

/*
 * Floating Pt Registers
 * Status regs are read-only (build-time) so need not be saved/restored
+20 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2012 Synopsys, Inc. (www.synopsys.com)
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#ifndef _ASM_ARC_CLK_H
#define _ASM_ARC_CLK_H

/* Although we can't really hide core_freq, the accessor is still better way */
extern unsigned long core_freq;

static inline unsigned long arc_get_core_freq(void)
{
	return core_freq;
}

#endif
+68 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 * Delay routines using pre computed loops_per_jiffy value.
 *
 * vineetg: Feb 2012
 *  -Rewrote in "C" to avoid dealing with availability of H/w MPY
 *  -Also reduced the num of MPY operations from 3 to 2
 *
 * Amit Bhor: Codito Technologies 2004
 */

#ifndef __ASM_ARC_UDELAY_H
#define __ASM_ARC_UDELAY_H

#include <asm/param.h>		/* HZ */

static inline void __delay(unsigned long loops)
{
	__asm__ __volatile__(
	"1:	sub.f %0, %0, 1	\n"
	"	jpnz 1b		\n"
	: "+r"(loops)
	:
	: "cc");
}

extern void __bad_udelay(void);

/*
 * Normal Math for computing loops in "N" usecs
 *  -we have precomputed @loops_per_jiffy
 *  -1 sec has HZ jiffies
 * loops per "N" usecs = ((loops_per_jiffy * HZ / 1000000) * N)
 *
 * Approximate Division by multiplication:
 *  -Mathematically if we multiply and divide a number by same value the
 *   result remains unchanged:  In this case, we use 2^32
 *  -> (loops_per_N_usec * 2^32 ) / 2^32
 *  -> (((loops_per_jiffy * HZ / 1000000) * N) * 2^32) / 2^32
 *  -> (loops_per_jiffy * HZ * N * 4295) / 2^32
 *
 *  -Divide by 2^32 is very simply right shift by 32
 *  -We simply need to ensure that the multiply per above eqn happens in
 *   64-bit precision (if CPU doesn't support it - gcc can emaulate it)
 */

static inline void __udelay(unsigned long usecs)
{
	unsigned long loops;

	/* (long long) cast ensures 64 bit MPY - real or emulated
	 * HZ * 4295 is pre-evaluated by gcc - hence only 2 mpy ops
	 */
	loops = ((long long)(usecs * 4295 * HZ) *
		 (long long)(loops_per_jiffy)) >> 32;

	__delay(loops);
}

#define udelay(n) (__builtin_constant_p(n) ? ((n) > 20000 ? __bad_udelay() \
				: __udelay(n)) : __udelay(n))

#endif /* __ASM_ARC_UDELAY_H */
+2 −0
Original line number Diff line number Diff line
@@ -19,4 +19,6 @@ extern void __init arc_init_IRQ(void);
extern void __init plat_init_IRQ(void);
extern int __init get_hw_config_num_irq(void);

void __cpuinit arc_local_timer_setup(unsigned int cpu);

#endif
+18 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#ifndef _ASM_ARC_TIMEX_H
#define _ASM_ARC_TIMEX_H

#define CLOCK_TICK_RATE	80000000 /* slated to be removed */

#include <asm-generic/timex.h>

/* XXX: get_cycles() to be implemented with RTSC insn */

#endif /* _ASM_ARC_TIMEX_H */
Loading