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:
51
arch/metag/include/asm/clock.h
Arquivo normal
51
arch/metag/include/asm/clock.h
Arquivo normal
@@ -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
29
arch/metag/include/asm/delay.h
Arquivo normal
@@ -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 */
|
@@ -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
53
arch/metag/kernel/clock.c
Arquivo normal
@@ -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
15
arch/metag/kernel/time.c
Arquivo normal
@@ -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();
|
||||
}
|
Referência em uma nova issue
Block a user