metag: Time keeping

Add time keeping code for metag. Meta hardware threads have 2 timers.
The background timer (TXTIMER) is used as a free-running time base, and
the interrupt timer (TXTIMERI) is used for the timer interrupt. Both
counters traditionally count at approximately 1MHz.

Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: John Stultz <johnstul@us.ibm.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Esse commit está contido em:
James Hogan
2012-10-09 10:54:39 +01:00
commit a2c5d4ed92
10 arquivos alterados com 378 adições e 0 exclusões

51
arch/metag/include/asm/clock.h Arquivo normal
Ver arquivo

@@ -0,0 +1,51 @@
/*
* arch/metag/include/asm/clock.h
*
* Copyright (C) 2012 Imagination Technologies Ltd.
*
* 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 _METAG_CLOCK_H_
#define _METAG_CLOCK_H_
#include <asm/mach/arch.h>
/**
* struct meta_clock_desc - Meta Core clock callbacks.
* @get_core_freq: Get the frequency of the Meta core. If this is NULL, the
* core frequency will be determined like this:
* Meta 1: based on loops_per_jiffy.
* Meta 2: (EXPAND_TIMER_DIV + 1) MHz.
*/
struct meta_clock_desc {
unsigned long (*get_core_freq)(void);
};
extern struct meta_clock_desc _meta_clock;
/*
* Set up the default clock, ensuring all callbacks are valid - only accessible
* during boot.
*/
void setup_meta_clocks(struct meta_clock_desc *desc);
/**
* get_coreclock() - Get the frequency of the Meta core clock.
*
* Returns: The Meta core clock frequency in Hz.
*/
static inline unsigned long get_coreclock(void)
{
/*
* Use the current clock callback. If set correctly this will provide
* the most accurate frequency as it can be calculated directly from the
* PLL configuration. otherwise a default callback will have been set
* instead.
*/
return _meta_clock.get_core_freq();
}
#endif /* _METAG_CLOCK_H_ */

29
arch/metag/include/asm/delay.h Arquivo normal
Ver arquivo

@@ -0,0 +1,29 @@
#ifndef _METAG_DELAY_H
#define _METAG_DELAY_H
/*
* Copyright (C) 1993 Linus Torvalds
*
* Delay routines calling functions in arch/metag/lib/delay.c
*/
/* Undefined functions to get compile-time errors */
extern void __bad_udelay(void);
extern void __bad_ndelay(void);
extern void __udelay(unsigned long usecs);
extern void __ndelay(unsigned long nsecs);
extern void __const_udelay(unsigned long xloops);
extern void __delay(unsigned long loops);
/* 0x10c7 is 2**32 / 1000000 (rounded up) */
#define udelay(n) (__builtin_constant_p(n) ? \
((n) > 20000 ? __bad_udelay() : __const_udelay((n) * 0x10c7ul)) : \
__udelay(n))
/* 0x5 is 2**32 / 1000000000 (rounded up) */
#define ndelay(n) (__builtin_constant_p(n) ? \
((n) > 20000 ? __bad_ndelay() : __const_udelay((n) * 5ul)) : \
__ndelay(n))
#endif /* _METAG_DELAY_H */

Ver arquivo

@@ -16,10 +16,13 @@
#include <linux/stddef.h>
#include <asm/clock.h>
/**
* struct machine_desc - Describes a board controlled by a Meta.
* @name: Board/SoC name.
* @dt_compat: Array of device tree 'compatible' strings.
* @clocks: Clock callbacks.
*
* @nr_irqs: Maximum number of IRQs.
* If 0, defaults to NR_IRQS in asm-generic/irq.h.
@@ -37,6 +40,7 @@
struct machine_desc {
const char *name;
const char **dt_compat;
struct meta_clock_desc *clocks;
unsigned int nr_irqs;

53
arch/metag/kernel/clock.c Arquivo normal
Ver arquivo

@@ -0,0 +1,53 @@
/*
* arch/metag/kernel/clock.c
*
* Copyright (C) 2012 Imagination Technologies Ltd.
*
* 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.
*/
#include <linux/delay.h>
#include <linux/io.h>
#include <asm/param.h>
#include <asm/clock.h>
struct meta_clock_desc _meta_clock;
/* Default machine get_core_freq callback. */
static unsigned long get_core_freq_default(void)
{
#ifdef CONFIG_METAG_META21
/*
* Meta 2 cores divide down the core clock for the Meta timers, so we
* can estimate the core clock from the divider.
*/
return (metag_in32(EXPAND_TIMER_DIV) + 1) * 1000000;
#else
/*
* On Meta 1 we don't know the core clock, but assuming the Meta timer
* is correct it can be estimated based on loops_per_jiffy.
*/
return (loops_per_jiffy * HZ * 5) >> 1;
#endif
}
/**
* setup_meta_clocks() - Set up the Meta clock.
* @desc: Clock descriptor usually provided by machine description
*
* Ensures all callbacks are valid.
*/
void __init setup_meta_clocks(struct meta_clock_desc *desc)
{
/* copy callbacks */
if (desc)
_meta_clock = *desc;
/* set fallback functions */
if (!_meta_clock.get_core_freq)
_meta_clock.get_core_freq = get_core_freq_default;
}

15
arch/metag/kernel/time.c Arquivo normal
Ver arquivo

@@ -0,0 +1,15 @@
/*
* Copyright (C) 2005-2013 Imagination Technologies Ltd.
*
* This file contains the Meta-specific time handling details.
*
*/
#include <linux/init.h>
#include <clocksource/metag_generic.h>
void __init time_init(void)
{
metag_generic_timer_init();
}