[ARM] smp: allow re-use of realview localtimer TWD support
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
This commit is contained in:
committed by
Russell King
parent
a8cbcd92bd
commit
f32f4ce257
@@ -885,6 +885,12 @@ config HAVE_ARM_SCU
|
|||||||
help
|
help
|
||||||
This option enables support for the ARM system coherency unit
|
This option enables support for the ARM system coherency unit
|
||||||
|
|
||||||
|
config HAVE_ARM_TWD
|
||||||
|
bool
|
||||||
|
depends on SMP
|
||||||
|
help
|
||||||
|
This options enables support for the ARM timer and watchdog unit
|
||||||
|
|
||||||
choice
|
choice
|
||||||
prompt "Memory split"
|
prompt "Memory split"
|
||||||
default VMSPLIT_3G
|
default VMSPLIT_3G
|
||||||
@@ -925,6 +931,7 @@ config LOCAL_TIMERS
|
|||||||
bool "Use local timer interrupts"
|
bool "Use local timer interrupts"
|
||||||
depends on SMP && (REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP || REALVIEW_EB_A9MP)
|
depends on SMP && (REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP || REALVIEW_EB_A9MP)
|
||||||
default y
|
default y
|
||||||
|
select HAVE_ARM_TWD if ARCH_REALVIEW
|
||||||
help
|
help
|
||||||
Enable support for local timers on SMP platforms, rather then the
|
Enable support for local timers on SMP platforms, rather then the
|
||||||
legacy IPI broadcast method. Local timers allows the system
|
legacy IPI broadcast method. Local timers allows the system
|
||||||
|
@@ -1,21 +0,0 @@
|
|||||||
#ifndef __ASM_HARDWARE_TWD_H
|
|
||||||
#define __ASM_HARDWARE_TWD_H
|
|
||||||
|
|
||||||
#define TWD_TIMER_LOAD 0x00
|
|
||||||
#define TWD_TIMER_COUNTER 0x04
|
|
||||||
#define TWD_TIMER_CONTROL 0x08
|
|
||||||
#define TWD_TIMER_INTSTAT 0x0C
|
|
||||||
|
|
||||||
#define TWD_WDOG_LOAD 0x20
|
|
||||||
#define TWD_WDOG_COUNTER 0x24
|
|
||||||
#define TWD_WDOG_CONTROL 0x28
|
|
||||||
#define TWD_WDOG_INTSTAT 0x2C
|
|
||||||
#define TWD_WDOG_RESETSTAT 0x30
|
|
||||||
#define TWD_WDOG_DISABLE 0x34
|
|
||||||
|
|
||||||
#define TWD_TIMER_CONTROL_ENABLE (1 << 0)
|
|
||||||
#define TWD_TIMER_CONTROL_ONESHOT (0 << 1)
|
|
||||||
#define TWD_TIMER_CONTROL_PERIODIC (1 << 1)
|
|
||||||
#define TWD_TIMER_CONTROL_IT_ENABLE (1 << 2)
|
|
||||||
|
|
||||||
#endif
|
|
@@ -24,6 +24,16 @@ asmlinkage void do_local_timer(struct pt_regs *);
|
|||||||
|
|
||||||
|
|
||||||
#ifdef CONFIG_LOCAL_TIMERS
|
#ifdef CONFIG_LOCAL_TIMERS
|
||||||
|
|
||||||
|
#ifdef CONFIG_HAVE_ARM_TWD
|
||||||
|
|
||||||
|
#include "smp_twd.h"
|
||||||
|
|
||||||
|
#define local_timer_ack() twd_timer_ack()
|
||||||
|
#define local_timer_stop() twd_timer_stop()
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Platform provides this to acknowledge a local timer IRQ.
|
* Platform provides this to acknowledge a local timer IRQ.
|
||||||
* Returns true if the local timer IRQ is to be processed.
|
* Returns true if the local timer IRQ is to be processed.
|
||||||
@@ -35,6 +45,8 @@ int local_timer_ack(void);
|
|||||||
*/
|
*/
|
||||||
void local_timer_stop(void);
|
void local_timer_stop(void);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Setup a local timer interrupt for a CPU.
|
* Setup a local timer interrupt for a CPU.
|
||||||
*/
|
*/
|
||||||
|
12
arch/arm/include/asm/smp_twd.h
Normal file
12
arch/arm/include/asm/smp_twd.h
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
#ifndef __ASMARM_SMP_TWD_H
|
||||||
|
#define __ASMARM_SMP_TWD_H
|
||||||
|
|
||||||
|
struct clock_event_device;
|
||||||
|
|
||||||
|
extern void __iomem *twd_base;
|
||||||
|
|
||||||
|
void twd_timer_stop(void);
|
||||||
|
int twd_timer_ack(void);
|
||||||
|
void twd_timer_setup(struct clock_event_device *);
|
||||||
|
|
||||||
|
#endif
|
@@ -23,6 +23,7 @@ obj-$(CONFIG_ISA_DMA) += dma-isa.o
|
|||||||
obj-$(CONFIG_PCI) += bios32.o isa.o
|
obj-$(CONFIG_PCI) += bios32.o isa.o
|
||||||
obj-$(CONFIG_SMP) += smp.o
|
obj-$(CONFIG_SMP) += smp.o
|
||||||
obj-$(CONFIG_HAVE_ARM_SCU) += smp_scu.o
|
obj-$(CONFIG_HAVE_ARM_SCU) += smp_scu.o
|
||||||
|
obj-$(CONFIG_HAVE_ARM_TWD) += smp_twd.o
|
||||||
obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o
|
obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o
|
||||||
obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o
|
obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o
|
||||||
obj-$(CONFIG_KPROBES) += kprobes.o kprobes-decode.o
|
obj-$(CONFIG_KPROBES) += kprobes.o kprobes-decode.o
|
||||||
|
173
arch/arm/kernel/smp_twd.c
Normal file
173
arch/arm/kernel/smp_twd.c
Normal file
@@ -0,0 +1,173 @@
|
|||||||
|
/*
|
||||||
|
* linux/arch/arm/kernel/smp_twd.c
|
||||||
|
*
|
||||||
|
* Copyright (C) 2002 ARM Ltd.
|
||||||
|
* All Rights Reserved
|
||||||
|
*
|
||||||
|
* 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/init.h>
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
|
#include <linux/device.h>
|
||||||
|
#include <linux/smp.h>
|
||||||
|
#include <linux/jiffies.h>
|
||||||
|
#include <linux/clockchips.h>
|
||||||
|
#include <linux/irq.h>
|
||||||
|
#include <linux/io.h>
|
||||||
|
|
||||||
|
#include <asm/smp_twd.h>
|
||||||
|
#include <asm/hardware/gic.h>
|
||||||
|
|
||||||
|
#define TWD_TIMER_LOAD 0x00
|
||||||
|
#define TWD_TIMER_COUNTER 0x04
|
||||||
|
#define TWD_TIMER_CONTROL 0x08
|
||||||
|
#define TWD_TIMER_INTSTAT 0x0C
|
||||||
|
|
||||||
|
#define TWD_WDOG_LOAD 0x20
|
||||||
|
#define TWD_WDOG_COUNTER 0x24
|
||||||
|
#define TWD_WDOG_CONTROL 0x28
|
||||||
|
#define TWD_WDOG_INTSTAT 0x2C
|
||||||
|
#define TWD_WDOG_RESETSTAT 0x30
|
||||||
|
#define TWD_WDOG_DISABLE 0x34
|
||||||
|
|
||||||
|
#define TWD_TIMER_CONTROL_ENABLE (1 << 0)
|
||||||
|
#define TWD_TIMER_CONTROL_ONESHOT (0 << 1)
|
||||||
|
#define TWD_TIMER_CONTROL_PERIODIC (1 << 1)
|
||||||
|
#define TWD_TIMER_CONTROL_IT_ENABLE (1 << 2)
|
||||||
|
|
||||||
|
/* set up by the platform code */
|
||||||
|
void __iomem *twd_base;
|
||||||
|
|
||||||
|
static unsigned long twd_timer_rate;
|
||||||
|
|
||||||
|
static void twd_set_mode(enum clock_event_mode mode,
|
||||||
|
struct clock_event_device *clk)
|
||||||
|
{
|
||||||
|
unsigned long ctrl;
|
||||||
|
|
||||||
|
switch(mode) {
|
||||||
|
case CLOCK_EVT_MODE_PERIODIC:
|
||||||
|
/* timer load already set up */
|
||||||
|
ctrl = TWD_TIMER_CONTROL_ENABLE | TWD_TIMER_CONTROL_IT_ENABLE
|
||||||
|
| TWD_TIMER_CONTROL_PERIODIC;
|
||||||
|
break;
|
||||||
|
case CLOCK_EVT_MODE_ONESHOT:
|
||||||
|
/* period set, and timer enabled in 'next_event' hook */
|
||||||
|
ctrl = TWD_TIMER_CONTROL_IT_ENABLE | TWD_TIMER_CONTROL_ONESHOT;
|
||||||
|
break;
|
||||||
|
case CLOCK_EVT_MODE_UNUSED:
|
||||||
|
case CLOCK_EVT_MODE_SHUTDOWN:
|
||||||
|
default:
|
||||||
|
ctrl = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
__raw_writel(ctrl, twd_base + TWD_TIMER_CONTROL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int twd_set_next_event(unsigned long evt,
|
||||||
|
struct clock_event_device *unused)
|
||||||
|
{
|
||||||
|
unsigned long ctrl = __raw_readl(twd_base + TWD_TIMER_CONTROL);
|
||||||
|
|
||||||
|
__raw_writel(evt, twd_base + TWD_TIMER_COUNTER);
|
||||||
|
__raw_writel(ctrl | TWD_TIMER_CONTROL_ENABLE, twd_base + TWD_TIMER_CONTROL);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* local_timer_ack: checks for a local timer interrupt.
|
||||||
|
*
|
||||||
|
* If a local timer interrupt has occurred, acknowledge and return 1.
|
||||||
|
* Otherwise, return 0.
|
||||||
|
*/
|
||||||
|
int twd_timer_ack(void)
|
||||||
|
{
|
||||||
|
if (__raw_readl(twd_base + TWD_TIMER_INTSTAT)) {
|
||||||
|
__raw_writel(1, twd_base + TWD_TIMER_INTSTAT);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __cpuinit twd_calibrate_rate(void)
|
||||||
|
{
|
||||||
|
unsigned long load, count;
|
||||||
|
u64 waitjiffies;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If this is the first time round, we need to work out how fast
|
||||||
|
* the timer ticks
|
||||||
|
*/
|
||||||
|
if (twd_timer_rate == 0) {
|
||||||
|
printk("Calibrating local timer... ");
|
||||||
|
|
||||||
|
/* Wait for a tick to start */
|
||||||
|
waitjiffies = get_jiffies_64() + 1;
|
||||||
|
|
||||||
|
while (get_jiffies_64() < waitjiffies)
|
||||||
|
udelay(10);
|
||||||
|
|
||||||
|
/* OK, now the tick has started, let's get the timer going */
|
||||||
|
waitjiffies += 5;
|
||||||
|
|
||||||
|
/* enable, no interrupt or reload */
|
||||||
|
__raw_writel(0x1, twd_base + TWD_TIMER_CONTROL);
|
||||||
|
|
||||||
|
/* maximum value */
|
||||||
|
__raw_writel(0xFFFFFFFFU, twd_base + TWD_TIMER_COUNTER);
|
||||||
|
|
||||||
|
while (get_jiffies_64() < waitjiffies)
|
||||||
|
udelay(10);
|
||||||
|
|
||||||
|
count = __raw_readl(twd_base + TWD_TIMER_COUNTER);
|
||||||
|
|
||||||
|
twd_timer_rate = (0xFFFFFFFFU - count) * (HZ / 5);
|
||||||
|
|
||||||
|
printk("%lu.%02luMHz.\n", twd_timer_rate / 1000000,
|
||||||
|
(twd_timer_rate / 100000) % 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
load = twd_timer_rate / HZ;
|
||||||
|
|
||||||
|
__raw_writel(load, twd_base + TWD_TIMER_LOAD);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Setup the local clock events for a CPU.
|
||||||
|
*/
|
||||||
|
void __cpuinit twd_timer_setup(struct clock_event_device *clk)
|
||||||
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
twd_calibrate_rate();
|
||||||
|
|
||||||
|
clk->name = "local_timer";
|
||||||
|
clk->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
|
||||||
|
clk->rating = 350;
|
||||||
|
clk->set_mode = twd_set_mode;
|
||||||
|
clk->set_next_event = twd_set_next_event;
|
||||||
|
clk->shift = 20;
|
||||||
|
clk->mult = div_sc(twd_timer_rate, NSEC_PER_SEC, clk->shift);
|
||||||
|
clk->max_delta_ns = clockevent_delta2ns(0xffffffff, clk);
|
||||||
|
clk->min_delta_ns = clockevent_delta2ns(0xf, clk);
|
||||||
|
|
||||||
|
/* Make sure our local interrupt controller has this enabled */
|
||||||
|
local_irq_save(flags);
|
||||||
|
get_irq_chip(clk->irq)->unmask(clk->irq);
|
||||||
|
local_irq_restore(flags);
|
||||||
|
|
||||||
|
clockevents_register_device(clk);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* take a local timer down
|
||||||
|
*/
|
||||||
|
void __cpuexit twd_timer_stop(void)
|
||||||
|
{
|
||||||
|
__raw_writel(0, twd_base + TWD_TIMER_CONTROL);
|
||||||
|
}
|
@@ -7,5 +7,6 @@ obj-$(CONFIG_MACH_REALVIEW_EB) += realview_eb.o
|
|||||||
obj-$(CONFIG_MACH_REALVIEW_PB11MP) += realview_pb11mp.o
|
obj-$(CONFIG_MACH_REALVIEW_PB11MP) += realview_pb11mp.o
|
||||||
obj-$(CONFIG_MACH_REALVIEW_PB1176) += realview_pb1176.o
|
obj-$(CONFIG_MACH_REALVIEW_PB1176) += realview_pb1176.o
|
||||||
obj-$(CONFIG_MACH_REALVIEW_PBA8) += realview_pba8.o
|
obj-$(CONFIG_MACH_REALVIEW_PBA8) += realview_pba8.o
|
||||||
obj-$(CONFIG_SMP) += platsmp.o headsmp.o localtimer.o
|
obj-$(CONFIG_SMP) += platsmp.o headsmp.o
|
||||||
obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
|
obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
|
||||||
|
obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o
|
||||||
|
@@ -51,9 +51,6 @@ extern struct mmc_platform_data realview_mmc0_plat_data;
|
|||||||
extern struct mmc_platform_data realview_mmc1_plat_data;
|
extern struct mmc_platform_data realview_mmc1_plat_data;
|
||||||
extern struct clcd_board clcd_plat_data;
|
extern struct clcd_board clcd_plat_data;
|
||||||
extern void __iomem *gic_cpu_base_addr;
|
extern void __iomem *gic_cpu_base_addr;
|
||||||
#ifdef CONFIG_LOCAL_TIMERS
|
|
||||||
extern void __iomem *twd_base;
|
|
||||||
#endif
|
|
||||||
extern void __iomem *timer0_va_base;
|
extern void __iomem *timer0_va_base;
|
||||||
extern void __iomem *timer1_va_base;
|
extern void __iomem *timer1_va_base;
|
||||||
extern void __iomem *timer2_va_base;
|
extern void __iomem *timer2_va_base;
|
||||||
|
@@ -9,154 +9,18 @@
|
|||||||
* published by the Free Software Foundation.
|
* published by the Free Software Foundation.
|
||||||
*/
|
*/
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/kernel.h>
|
|
||||||
#include <linux/delay.h>
|
|
||||||
#include <linux/smp.h>
|
#include <linux/smp.h>
|
||||||
#include <linux/jiffies.h>
|
|
||||||
#include <linux/clockchips.h>
|
#include <linux/clockchips.h>
|
||||||
#include <linux/irq.h>
|
|
||||||
#include <linux/io.h>
|
|
||||||
|
|
||||||
#include <asm/hardware/arm_twd.h>
|
|
||||||
#include <asm/hardware/gic.h>
|
|
||||||
#include <mach/hardware.h>
|
|
||||||
#include <asm/irq.h>
|
#include <asm/irq.h>
|
||||||
|
#include <asm/smp_twd.h>
|
||||||
#ifdef CONFIG_LOCAL_TIMERS
|
#include <asm/localtimer.h>
|
||||||
|
|
||||||
/* set up by the platform code */
|
|
||||||
void __iomem *twd_base;
|
|
||||||
|
|
||||||
static unsigned long mpcore_timer_rate;
|
|
||||||
|
|
||||||
static void local_timer_set_mode(enum clock_event_mode mode,
|
|
||||||
struct clock_event_device *evt)
|
|
||||||
{
|
|
||||||
unsigned long ctrl;
|
|
||||||
|
|
||||||
switch(mode) {
|
|
||||||
case CLOCK_EVT_MODE_PERIODIC:
|
|
||||||
/* timer load already set up */
|
|
||||||
ctrl = TWD_TIMER_CONTROL_ENABLE | TWD_TIMER_CONTROL_IT_ENABLE
|
|
||||||
| TWD_TIMER_CONTROL_PERIODIC;
|
|
||||||
break;
|
|
||||||
case CLOCK_EVT_MODE_ONESHOT:
|
|
||||||
/* period set, and timer enabled in 'next_event' hook */
|
|
||||||
ctrl = TWD_TIMER_CONTROL_IT_ENABLE | TWD_TIMER_CONTROL_ONESHOT;
|
|
||||||
break;
|
|
||||||
case CLOCK_EVT_MODE_UNUSED:
|
|
||||||
case CLOCK_EVT_MODE_SHUTDOWN:
|
|
||||||
default:
|
|
||||||
ctrl = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
__raw_writel(ctrl, twd_base + TWD_TIMER_CONTROL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int local_timer_set_next_event(unsigned long evt,
|
|
||||||
struct clock_event_device *unused)
|
|
||||||
{
|
|
||||||
unsigned long ctrl = __raw_readl(twd_base + TWD_TIMER_CONTROL);
|
|
||||||
|
|
||||||
__raw_writel(evt, twd_base + TWD_TIMER_COUNTER);
|
|
||||||
__raw_writel(ctrl | TWD_TIMER_CONTROL_ENABLE, twd_base + TWD_TIMER_CONTROL);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* local_timer_ack: checks for a local timer interrupt.
|
|
||||||
*
|
|
||||||
* If a local timer interrupt has occurred, acknowledge and return 1.
|
|
||||||
* Otherwise, return 0.
|
|
||||||
*/
|
|
||||||
int local_timer_ack(void)
|
|
||||||
{
|
|
||||||
if (__raw_readl(twd_base + TWD_TIMER_INTSTAT)) {
|
|
||||||
__raw_writel(1, twd_base + TWD_TIMER_INTSTAT);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void __cpuinit twd_calibrate_rate(void)
|
|
||||||
{
|
|
||||||
unsigned long load, count;
|
|
||||||
u64 waitjiffies;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If this is the first time round, we need to work out how fast
|
|
||||||
* the timer ticks
|
|
||||||
*/
|
|
||||||
if (mpcore_timer_rate == 0) {
|
|
||||||
printk("Calibrating local timer... ");
|
|
||||||
|
|
||||||
/* Wait for a tick to start */
|
|
||||||
waitjiffies = get_jiffies_64() + 1;
|
|
||||||
|
|
||||||
while (get_jiffies_64() < waitjiffies)
|
|
||||||
udelay(10);
|
|
||||||
|
|
||||||
/* OK, now the tick has started, let's get the timer going */
|
|
||||||
waitjiffies += 5;
|
|
||||||
|
|
||||||
/* enable, no interrupt or reload */
|
|
||||||
__raw_writel(0x1, twd_base + TWD_TIMER_CONTROL);
|
|
||||||
|
|
||||||
/* maximum value */
|
|
||||||
__raw_writel(0xFFFFFFFFU, twd_base + TWD_TIMER_COUNTER);
|
|
||||||
|
|
||||||
while (get_jiffies_64() < waitjiffies)
|
|
||||||
udelay(10);
|
|
||||||
|
|
||||||
count = __raw_readl(twd_base + TWD_TIMER_COUNTER);
|
|
||||||
|
|
||||||
mpcore_timer_rate = (0xFFFFFFFFU - count) * (HZ / 5);
|
|
||||||
|
|
||||||
printk("%lu.%02luMHz.\n", mpcore_timer_rate / 1000000,
|
|
||||||
(mpcore_timer_rate / 100000) % 100);
|
|
||||||
}
|
|
||||||
|
|
||||||
load = mpcore_timer_rate / HZ;
|
|
||||||
|
|
||||||
__raw_writel(load, twd_base + TWD_TIMER_LOAD);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Setup the local clock events for a CPU.
|
* Setup the local clock events for a CPU.
|
||||||
*/
|
*/
|
||||||
void __cpuinit local_timer_setup(struct clock_event_device *evt)
|
void __cpuinit local_timer_setup(struct clock_event_device *evt)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
evt->irq = IRQ_LOCALTIMER;
|
||||||
|
twd_timer_setup(evt);
|
||||||
twd_calibrate_rate();
|
|
||||||
|
|
||||||
evt->name = "local_timer";
|
|
||||||
evt->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
|
|
||||||
evt->rating = 350;
|
|
||||||
evt->set_mode = local_timer_set_mode;
|
|
||||||
evt->set_next_event = local_timer_set_next_event;
|
|
||||||
evt->irq = IRQ_LOCALTIMER;
|
|
||||||
evt->shift = 20;
|
|
||||||
evt->mult = div_sc(mpcore_timer_rate, NSEC_PER_SEC, evt->shift);
|
|
||||||
evt->max_delta_ns = clockevent_delta2ns(0xffffffff, evt);
|
|
||||||
evt->min_delta_ns = clockevent_delta2ns(0xf, evt);
|
|
||||||
|
|
||||||
/* Make sure our local interrupt controller has this enabled */
|
|
||||||
local_irq_save(flags);
|
|
||||||
get_irq_chip(IRQ_LOCALTIMER)->unmask(IRQ_LOCALTIMER);
|
|
||||||
local_irq_restore(flags);
|
|
||||||
|
|
||||||
clockevents_register_device(evt);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* take a local timer down
|
|
||||||
*/
|
|
||||||
void __cpuexit local_timer_stop(void)
|
|
||||||
{
|
|
||||||
__raw_writel(0, twd_base + TWD_TIMER_CONTROL);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* CONFIG_LOCAL_TIMERS */
|
|
||||||
|
@@ -32,6 +32,7 @@
|
|||||||
#include <asm/hardware/gic.h>
|
#include <asm/hardware/gic.h>
|
||||||
#include <asm/hardware/icst307.h>
|
#include <asm/hardware/icst307.h>
|
||||||
#include <asm/hardware/cache-l2x0.h>
|
#include <asm/hardware/cache-l2x0.h>
|
||||||
|
#include <asm/localtimer.h>
|
||||||
|
|
||||||
#include <asm/mach/arch.h>
|
#include <asm/mach/arch.h>
|
||||||
#include <asm/mach/map.h>
|
#include <asm/mach/map.h>
|
||||||
|
@@ -32,6 +32,7 @@
|
|||||||
#include <asm/hardware/gic.h>
|
#include <asm/hardware/gic.h>
|
||||||
#include <asm/hardware/icst307.h>
|
#include <asm/hardware/icst307.h>
|
||||||
#include <asm/hardware/cache-l2x0.h>
|
#include <asm/hardware/cache-l2x0.h>
|
||||||
|
#include <asm/localtimer.h>
|
||||||
|
|
||||||
#include <asm/mach/arch.h>
|
#include <asm/mach/arch.h>
|
||||||
#include <asm/mach/flash.h>
|
#include <asm/mach/flash.h>
|
||||||
|
Reference in New Issue
Block a user