forked from Minki/linux
Merge branch 'local_timers-for-arm-soc' of git://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms into next/timer
* 'local_timers-for-arm-soc' of git://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms: ARM: local timers: make the runtime registration interface mandatory ARM: local timers: convert MSM to runtime registration interface ARM: local timers: convert exynos to runtime registration interface ARM: smp_twd: remove old local timer interface ARM: imx6q: convert to twd_local_timer_register() interface ARM: highbank: convert to twd_local_timer_register() interface ARM: ux500: convert to twd_local_timer_register() interface ARM: shmobile: convert to twd_local_timer_register() interface ARM: tegra: convert to twd_local_timer_register() interface ARM: plat-versatile: convert to twd_local_timer_register() interface ARM: OMAP4: convert to twd_local_timer_register() interface ARM: smp_twd: add device tree support ARM: smp_twd: add runtime registration support ARM: local timers: introduce a new registration interface ARM: smp_twd: make local_timer_stop a symbol instead of a #define
This commit is contained in:
commit
648ab3df21
48
Documentation/devicetree/bindings/arm/twd.txt
Normal file
48
Documentation/devicetree/bindings/arm/twd.txt
Normal file
@ -0,0 +1,48 @@
|
||||
* ARM Timer Watchdog
|
||||
|
||||
ARM 11MP, Cortex-A5 and Cortex-A9 are often associated with a per-core
|
||||
Timer-Watchdog (aka TWD), which provides both a per-cpu local timer
|
||||
and watchdog.
|
||||
|
||||
The TWD is usually attached to a GIC to deliver its two per-processor
|
||||
interrupts.
|
||||
|
||||
** Timer node required properties:
|
||||
|
||||
- compatible : Should be one of:
|
||||
"arm,cortex-a9-twd-timer"
|
||||
"arm,cortex-a5-twd-timer"
|
||||
"arm,arm11mp-twd-timer"
|
||||
|
||||
- interrupts : One interrupt to each core
|
||||
|
||||
- reg : Specify the base address and the size of the TWD timer
|
||||
register window.
|
||||
|
||||
Example:
|
||||
|
||||
twd-timer@2c000600 {
|
||||
compatible = "arm,arm11mp-twd-timer"";
|
||||
reg = <0x2c000600 0x20>;
|
||||
interrupts = <1 13 0xf01>;
|
||||
};
|
||||
|
||||
** Watchdog node properties:
|
||||
|
||||
- compatible : Should be one of:
|
||||
"arm,cortex-a9-twd-wdt"
|
||||
"arm,cortex-a5-twd-wdt"
|
||||
"arm,arm11mp-twd-wdt"
|
||||
|
||||
- interrupts : One interrupt to each core
|
||||
|
||||
- reg : Specify the base address and the size of the TWD watchdog
|
||||
register window.
|
||||
|
||||
Example:
|
||||
|
||||
twd-watchdog@2c000620 {
|
||||
compatible = "arm,arm11mp-twd-wdt";
|
||||
reg = <0x2c000620 0x20>;
|
||||
interrupts = <1 14 0xf01>;
|
||||
};
|
@ -72,15 +72,15 @@
|
||||
ranges;
|
||||
|
||||
timer@fff10600 {
|
||||
compatible = "arm,smp-twd";
|
||||
compatible = "arm,cortex-a9-twd-timer";
|
||||
reg = <0xfff10600 0x20>;
|
||||
interrupts = <1 13 0xf04>;
|
||||
interrupts = <1 13 0xf01>;
|
||||
};
|
||||
|
||||
watchdog@fff10620 {
|
||||
compatible = "arm,cortex-a9-wdt";
|
||||
compatible = "arm,cortex-a9-twd-wdt";
|
||||
reg = <0xfff10620 0x20>;
|
||||
interrupts = <1 14 0xf04>;
|
||||
interrupts = <1 14 0xf01>;
|
||||
};
|
||||
|
||||
intc: interrupt-controller@fff11000 {
|
||||
|
@ -88,9 +88,9 @@
|
||||
ranges;
|
||||
|
||||
timer@00a00600 {
|
||||
compatible = "arm,smp-twd";
|
||||
reg = <0x00a00600 0x100>;
|
||||
interrupts = <1 13 0xf4>;
|
||||
compatible = "arm,cortex-a9-twd-timer";
|
||||
reg = <0x00a00600 0x20>;
|
||||
interrupts = <1 13 0xf01>;
|
||||
};
|
||||
|
||||
L2: l2-cache@00a02000 {
|
||||
|
@ -11,47 +11,24 @@
|
||||
#define __ASM_ARM_LOCALTIMER_H
|
||||
|
||||
#include <linux/errno.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
struct clock_event_device;
|
||||
|
||||
/*
|
||||
* Setup a per-cpu timer, whether it be a local timer or dummy broadcast
|
||||
*/
|
||||
void percpu_timer_setup(void);
|
||||
struct local_timer_ops {
|
||||
int (*setup)(struct clock_event_device *);
|
||||
void (*stop)(struct clock_event_device *);
|
||||
};
|
||||
|
||||
#ifdef CONFIG_LOCAL_TIMERS
|
||||
|
||||
#ifdef CONFIG_HAVE_ARM_TWD
|
||||
|
||||
#include "smp_twd.h"
|
||||
|
||||
#define local_timer_stop(c) twd_timer_stop((c))
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
* Stop the local timer
|
||||
* Register a local timer driver
|
||||
*/
|
||||
void local_timer_stop(struct clock_event_device *);
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Setup a local timer interrupt for a CPU.
|
||||
*/
|
||||
int local_timer_setup(struct clock_event_device *);
|
||||
|
||||
int local_timer_register(struct local_timer_ops *);
|
||||
#else
|
||||
|
||||
static inline int local_timer_setup(struct clock_event_device *evt)
|
||||
static inline int local_timer_register(struct local_timer_ops *ops)
|
||||
{
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
static inline void local_timer_stop(struct clock_event_device *evt)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -18,11 +18,28 @@
|
||||
#define TWD_TIMER_CONTROL_PERIODIC (1 << 1)
|
||||
#define TWD_TIMER_CONTROL_IT_ENABLE (1 << 2)
|
||||
|
||||
struct clock_event_device;
|
||||
#include <linux/ioport.h>
|
||||
|
||||
extern void __iomem *twd_base;
|
||||
struct twd_local_timer {
|
||||
struct resource res[2];
|
||||
};
|
||||
|
||||
void twd_timer_setup(struct clock_event_device *);
|
||||
void twd_timer_stop(struct clock_event_device *);
|
||||
#define DEFINE_TWD_LOCAL_TIMER(name,base,irq) \
|
||||
struct twd_local_timer name __initdata = { \
|
||||
.res = { \
|
||||
DEFINE_RES_MEM(base, 0x10), \
|
||||
DEFINE_RES_IRQ(irq), \
|
||||
}, \
|
||||
};
|
||||
|
||||
int twd_local_timer_register(struct twd_local_timer *);
|
||||
|
||||
#ifdef CONFIG_HAVE_ARM_TWD
|
||||
void twd_local_timer_of_register(void);
|
||||
#else
|
||||
static inline void twd_local_timer_of_register(void)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -246,6 +246,8 @@ static void __cpuinit smp_store_cpu_info(unsigned int cpuid)
|
||||
store_cpu_topology(cpuid);
|
||||
}
|
||||
|
||||
static void percpu_timer_setup(void);
|
||||
|
||||
/*
|
||||
* This is the secondary CPU boot entry. We're using this CPUs
|
||||
* idle thread stack, but a set of temporary page tables.
|
||||
@ -459,7 +461,20 @@ static void __cpuinit broadcast_timer_setup(struct clock_event_device *evt)
|
||||
clockevents_register_device(evt);
|
||||
}
|
||||
|
||||
void __cpuinit percpu_timer_setup(void)
|
||||
static struct local_timer_ops *lt_ops;
|
||||
|
||||
#ifdef CONFIG_LOCAL_TIMERS
|
||||
int local_timer_register(struct local_timer_ops *ops)
|
||||
{
|
||||
if (lt_ops)
|
||||
return -EBUSY;
|
||||
|
||||
lt_ops = ops;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void __cpuinit percpu_timer_setup(void)
|
||||
{
|
||||
unsigned int cpu = smp_processor_id();
|
||||
struct clock_event_device *evt = &per_cpu(percpu_clockevent, cpu);
|
||||
@ -467,7 +482,7 @@ void __cpuinit percpu_timer_setup(void)
|
||||
evt->cpumask = cpumask_of(cpu);
|
||||
evt->broadcast = smp_timer_broadcast;
|
||||
|
||||
if (local_timer_setup(evt))
|
||||
if (!lt_ops || lt_ops->setup(evt))
|
||||
broadcast_timer_setup(evt);
|
||||
}
|
||||
|
||||
@ -482,7 +497,8 @@ static void percpu_timer_stop(void)
|
||||
unsigned int cpu = smp_processor_id();
|
||||
struct clock_event_device *evt = &per_cpu(percpu_clockevent, cpu);
|
||||
|
||||
local_timer_stop(evt);
|
||||
if (lt_ops)
|
||||
lt_ops->stop(evt);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -18,20 +18,23 @@
|
||||
#include <linux/smp.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/clockchips.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/of_address.h>
|
||||
|
||||
#include <asm/smp_twd.h>
|
||||
#include <asm/localtimer.h>
|
||||
#include <asm/hardware/gic.h>
|
||||
|
||||
/* set up by the platform code */
|
||||
void __iomem *twd_base;
|
||||
static void __iomem *twd_base;
|
||||
|
||||
static struct clk *twd_clk;
|
||||
static unsigned long twd_timer_rate;
|
||||
|
||||
static struct clock_event_device __percpu **twd_evt;
|
||||
static int twd_ppi;
|
||||
|
||||
static void twd_set_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *clk)
|
||||
@ -77,7 +80,7 @@ static int twd_set_next_event(unsigned long evt,
|
||||
* If a local timer interrupt has occurred, acknowledge and return 1.
|
||||
* Otherwise, return 0.
|
||||
*/
|
||||
int twd_timer_ack(void)
|
||||
static int twd_timer_ack(void)
|
||||
{
|
||||
if (__raw_readl(twd_base + TWD_TIMER_INTSTAT)) {
|
||||
__raw_writel(1, twd_base + TWD_TIMER_INTSTAT);
|
||||
@ -87,7 +90,7 @@ int twd_timer_ack(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void twd_timer_stop(struct clock_event_device *clk)
|
||||
static void twd_timer_stop(struct clock_event_device *clk)
|
||||
{
|
||||
twd_set_mode(CLOCK_EVT_MODE_UNUSED, clk);
|
||||
disable_percpu_irq(clk->irq);
|
||||
@ -222,28 +225,10 @@ static struct clk *twd_get_clock(void)
|
||||
/*
|
||||
* Setup the local clock events for a CPU.
|
||||
*/
|
||||
void __cpuinit twd_timer_setup(struct clock_event_device *clk)
|
||||
static int __cpuinit twd_timer_setup(struct clock_event_device *clk)
|
||||
{
|
||||
struct clock_event_device **this_cpu_clk;
|
||||
|
||||
if (!twd_evt) {
|
||||
int err;
|
||||
|
||||
twd_evt = alloc_percpu(struct clock_event_device *);
|
||||
if (!twd_evt) {
|
||||
pr_err("twd: can't allocate memory\n");
|
||||
return;
|
||||
}
|
||||
|
||||
err = request_percpu_irq(clk->irq, twd_handler,
|
||||
"twd", twd_evt);
|
||||
if (err) {
|
||||
pr_err("twd: can't register interrupt %d (%d)\n",
|
||||
clk->irq, err);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!twd_clk)
|
||||
twd_clk = twd_get_clock();
|
||||
|
||||
@ -260,6 +245,7 @@ void __cpuinit twd_timer_setup(struct clock_event_device *clk)
|
||||
clk->rating = 350;
|
||||
clk->set_mode = twd_set_mode;
|
||||
clk->set_next_event = twd_set_next_event;
|
||||
clk->irq = twd_ppi;
|
||||
|
||||
this_cpu_clk = __this_cpu_ptr(twd_evt);
|
||||
*this_cpu_clk = clk;
|
||||
@ -267,4 +253,95 @@ void __cpuinit twd_timer_setup(struct clock_event_device *clk)
|
||||
clockevents_config_and_register(clk, twd_timer_rate,
|
||||
0xf, 0xffffffff);
|
||||
enable_percpu_irq(clk->irq, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct local_timer_ops twd_lt_ops __cpuinitdata = {
|
||||
.setup = twd_timer_setup,
|
||||
.stop = twd_timer_stop,
|
||||
};
|
||||
|
||||
static int __init twd_local_timer_common_register(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
twd_evt = alloc_percpu(struct clock_event_device *);
|
||||
if (!twd_evt) {
|
||||
err = -ENOMEM;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
err = request_percpu_irq(twd_ppi, twd_handler, "twd", twd_evt);
|
||||
if (err) {
|
||||
pr_err("twd: can't register interrupt %d (%d)\n", twd_ppi, err);
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
err = local_timer_register(&twd_lt_ops);
|
||||
if (err)
|
||||
goto out_irq;
|
||||
|
||||
return 0;
|
||||
|
||||
out_irq:
|
||||
free_percpu_irq(twd_ppi, twd_evt);
|
||||
out_free:
|
||||
iounmap(twd_base);
|
||||
twd_base = NULL;
|
||||
free_percpu(twd_evt);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int __init twd_local_timer_register(struct twd_local_timer *tlt)
|
||||
{
|
||||
if (twd_base || twd_evt)
|
||||
return -EBUSY;
|
||||
|
||||
twd_ppi = tlt->res[1].start;
|
||||
|
||||
twd_base = ioremap(tlt->res[0].start, resource_size(&tlt->res[0]));
|
||||
if (!twd_base)
|
||||
return -ENOMEM;
|
||||
|
||||
return twd_local_timer_common_register();
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
const static struct of_device_id twd_of_match[] __initconst = {
|
||||
{ .compatible = "arm,cortex-a9-twd-timer", },
|
||||
{ .compatible = "arm,cortex-a5-twd-timer", },
|
||||
{ .compatible = "arm,arm11mp-twd-timer", },
|
||||
{ },
|
||||
};
|
||||
|
||||
void __init twd_local_timer_of_register(void)
|
||||
{
|
||||
struct device_node *np;
|
||||
int err;
|
||||
|
||||
np = of_find_matching_node(NULL, twd_of_match);
|
||||
if (!np) {
|
||||
err = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
|
||||
twd_ppi = irq_of_parse_and_map(np, 0);
|
||||
if (!twd_ppi) {
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
twd_base = of_iomap(np, 0);
|
||||
if (!twd_base) {
|
||||
err = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = twd_local_timer_common_register();
|
||||
|
||||
out:
|
||||
WARN(err, "twd_local_timer_of_register failed (%d)\n", err);
|
||||
}
|
||||
#endif
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include <linux/percpu.h>
|
||||
|
||||
#include <asm/hardware/gic.h>
|
||||
#include <asm/localtimer.h>
|
||||
|
||||
#include <plat/cpu.h>
|
||||
|
||||
@ -375,7 +376,7 @@ static struct irqaction mct_tick1_event_irq = {
|
||||
.handler = exynos4_mct_tick_isr,
|
||||
};
|
||||
|
||||
static void exynos4_mct_tick_init(struct clock_event_device *evt)
|
||||
static int __cpuinit exynos4_local_timer_setup(struct clock_event_device *evt)
|
||||
{
|
||||
struct mct_clock_event_device *mevt;
|
||||
unsigned int cpu = smp_processor_id();
|
||||
@ -417,17 +418,11 @@ static void exynos4_mct_tick_init(struct clock_event_device *evt)
|
||||
} else {
|
||||
enable_percpu_irq(IRQ_MCT_LOCALTIMER, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Setup the local clock events for a CPU */
|
||||
int __cpuinit local_timer_setup(struct clock_event_device *evt)
|
||||
{
|
||||
exynos4_mct_tick_init(evt);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void local_timer_stop(struct clock_event_device *evt)
|
||||
static void exynos4_local_timer_stop(struct clock_event_device *evt)
|
||||
{
|
||||
unsigned int cpu = smp_processor_id();
|
||||
evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt);
|
||||
@ -439,6 +434,11 @@ void local_timer_stop(struct clock_event_device *evt)
|
||||
else
|
||||
disable_percpu_irq(IRQ_MCT_LOCALTIMER);
|
||||
}
|
||||
|
||||
static struct local_timer_ops exynos4_mct_tick_ops __cpuinitdata = {
|
||||
.setup = exynos4_local_timer_setup,
|
||||
.stop = exynos4_local_timer_stop,
|
||||
};
|
||||
#endif /* CONFIG_LOCAL_TIMERS */
|
||||
|
||||
static void __init exynos4_timer_resources(void)
|
||||
@ -458,6 +458,8 @@ static void __init exynos4_timer_resources(void)
|
||||
WARN(err, "MCT: can't request IRQ %d (%d)\n",
|
||||
IRQ_MCT_LOCALTIMER, err);
|
||||
}
|
||||
|
||||
local_timer_register(&exynos4_mct_tick_ops);
|
||||
#endif /* CONFIG_LOCAL_TIMERS */
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
obj-y := clock.o highbank.o system.o
|
||||
obj-$(CONFIG_DEBUG_HIGHBANK_UART) += lluart.o
|
||||
obj-$(CONFIG_SMP) += platsmp.o
|
||||
obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o
|
||||
obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
|
||||
obj-$(CONFIG_PM_SLEEP) += pm.o
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/smp_plat.h>
|
||||
#include <asm/smp_scu.h>
|
||||
#include <asm/smp_twd.h>
|
||||
#include <asm/hardware/arm_timer.h>
|
||||
#include <asm/hardware/timer-sp.h>
|
||||
#include <asm/hardware/gic.h>
|
||||
@ -111,6 +112,8 @@ static void __init highbank_timer_init(void)
|
||||
|
||||
sp804_clocksource_init(timer_base + 0x20, "timer1");
|
||||
sp804_clockevents_init(timer_base, irq, "timer0");
|
||||
|
||||
twd_local_timer_of_register();
|
||||
}
|
||||
|
||||
static struct sys_timer highbank_timer = {
|
||||
|
@ -1,40 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2011 Calxeda, Inc.
|
||||
* Based on localtimer.c, Copyright (C) 2002 ARM Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <linux/init.h>
|
||||
#include <linux/clockchips.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_irq.h>
|
||||
|
||||
#include <asm/smp_twd.h>
|
||||
|
||||
/*
|
||||
* Setup the local clock events for a CPU.
|
||||
*/
|
||||
int __cpuinit local_timer_setup(struct clock_event_device *evt)
|
||||
{
|
||||
struct device_node *np;
|
||||
|
||||
np = of_find_compatible_node(NULL, NULL, "arm,smp-twd");
|
||||
if (!twd_base) {
|
||||
twd_base = of_iomap(np, 0);
|
||||
WARN_ON(!twd_base);
|
||||
}
|
||||
evt->irq = irq_of_parse_and_map(np, 0);
|
||||
twd_timer_setup(evt);
|
||||
return 0;
|
||||
}
|
@ -71,7 +71,6 @@ obj-$(CONFIG_CPU_V7) += head-v7.o
|
||||
AFLAGS_head-v7.o :=-Wa,-march=armv7-a
|
||||
obj-$(CONFIG_SMP) += platsmp.o
|
||||
obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
|
||||
obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o
|
||||
obj-$(CONFIG_SOC_IMX6Q) += clock-imx6q.o mach-imx6q.o
|
||||
|
||||
ifeq ($(CONFIG_PM),y)
|
||||
|
@ -1,35 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011 Freescale Semiconductor, Inc.
|
||||
* Copyright 2011 Linaro Ltd.
|
||||
*
|
||||
* The code contained herein is licensed under the GNU General Public
|
||||
* License. You may obtain a copy of the GNU General Public License
|
||||
* Version 2 or later at the following locations:
|
||||
*
|
||||
* http://www.opensource.org/licenses/gpl-license.html
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/clockchips.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <asm/smp_twd.h>
|
||||
|
||||
/*
|
||||
* Setup the local clock events for a CPU.
|
||||
*/
|
||||
int __cpuinit local_timer_setup(struct clock_event_device *evt)
|
||||
{
|
||||
struct device_node *np;
|
||||
|
||||
np = of_find_compatible_node(NULL, NULL, "arm,smp-twd");
|
||||
if (!twd_base) {
|
||||
twd_base = of_iomap(np, 0);
|
||||
WARN_ON(!twd_base);
|
||||
}
|
||||
evt->irq = irq_of_parse_and_map(np, 0);
|
||||
twd_timer_setup(evt);
|
||||
|
||||
return 0;
|
||||
}
|
@ -21,6 +21,7 @@
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/phy.h>
|
||||
#include <linux/micrel_phy.h>
|
||||
#include <asm/smp_twd.h>
|
||||
#include <asm/hardware/cache-l2x0.h>
|
||||
#include <asm/hardware/gic.h>
|
||||
#include <asm/mach/arch.h>
|
||||
@ -119,6 +120,7 @@ static void __init imx6q_init_irq(void)
|
||||
static void __init imx6q_timer_init(void)
|
||||
{
|
||||
mx6q_clocks_init();
|
||||
twd_local_timer_of_register();
|
||||
}
|
||||
|
||||
static struct sys_timer imx6q_timer = {
|
||||
|
@ -127,6 +127,45 @@ static struct clocksource msm_clocksource = {
|
||||
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_LOCAL_TIMERS
|
||||
static int __cpuinit msm_local_timer_setup(struct clock_event_device *evt)
|
||||
{
|
||||
/* Use existing clock_event for cpu 0 */
|
||||
if (!smp_processor_id())
|
||||
return 0;
|
||||
|
||||
writel_relaxed(0, event_base + TIMER_ENABLE);
|
||||
writel_relaxed(0, event_base + TIMER_CLEAR);
|
||||
writel_relaxed(~0, event_base + TIMER_MATCH_VAL);
|
||||
evt->irq = msm_clockevent.irq;
|
||||
evt->name = "local_timer";
|
||||
evt->features = msm_clockevent.features;
|
||||
evt->rating = msm_clockevent.rating;
|
||||
evt->set_mode = msm_timer_set_mode;
|
||||
evt->set_next_event = msm_timer_set_next_event;
|
||||
evt->shift = msm_clockevent.shift;
|
||||
evt->mult = div_sc(GPT_HZ, NSEC_PER_SEC, evt->shift);
|
||||
evt->max_delta_ns = clockevent_delta2ns(0xf0000000, evt);
|
||||
evt->min_delta_ns = clockevent_delta2ns(4, evt);
|
||||
|
||||
*__this_cpu_ptr(msm_evt.percpu_evt) = evt;
|
||||
clockevents_register_device(evt);
|
||||
enable_percpu_irq(evt->irq, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void msm_local_timer_stop(struct clock_event_device *evt)
|
||||
{
|
||||
evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt);
|
||||
disable_percpu_irq(evt->irq);
|
||||
}
|
||||
|
||||
static struct local_timer_ops msm_local_timer_ops __cpuinitdata = {
|
||||
.setup = msm_local_timer_setup,
|
||||
.stop = msm_local_timer_stop,
|
||||
};
|
||||
#endif /* CONFIG_LOCAL_TIMERS */
|
||||
|
||||
static void __init msm_timer_init(void)
|
||||
{
|
||||
struct clock_event_device *ce = &msm_clockevent;
|
||||
@ -173,8 +212,12 @@ static void __init msm_timer_init(void)
|
||||
*__this_cpu_ptr(msm_evt.percpu_evt) = ce;
|
||||
res = request_percpu_irq(ce->irq, msm_timer_interrupt,
|
||||
ce->name, msm_evt.percpu_evt);
|
||||
if (!res)
|
||||
if (!res) {
|
||||
enable_percpu_irq(ce->irq, 0);
|
||||
#ifdef CONFIG_LOCAL_TIMERS
|
||||
local_timer_register(&msm_local_timer_ops);
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
msm_evt.evt = ce;
|
||||
res = request_irq(ce->irq, msm_timer_interrupt,
|
||||
@ -191,40 +234,6 @@ err:
|
||||
pr_err("clocksource_register failed\n");
|
||||
}
|
||||
|
||||
#ifdef CONFIG_LOCAL_TIMERS
|
||||
int __cpuinit local_timer_setup(struct clock_event_device *evt)
|
||||
{
|
||||
/* Use existing clock_event for cpu 0 */
|
||||
if (!smp_processor_id())
|
||||
return 0;
|
||||
|
||||
writel_relaxed(0, event_base + TIMER_ENABLE);
|
||||
writel_relaxed(0, event_base + TIMER_CLEAR);
|
||||
writel_relaxed(~0, event_base + TIMER_MATCH_VAL);
|
||||
evt->irq = msm_clockevent.irq;
|
||||
evt->name = "local_timer";
|
||||
evt->features = msm_clockevent.features;
|
||||
evt->rating = msm_clockevent.rating;
|
||||
evt->set_mode = msm_timer_set_mode;
|
||||
evt->set_next_event = msm_timer_set_next_event;
|
||||
evt->shift = msm_clockevent.shift;
|
||||
evt->mult = div_sc(GPT_HZ, NSEC_PER_SEC, evt->shift);
|
||||
evt->max_delta_ns = clockevent_delta2ns(0xf0000000, evt);
|
||||
evt->min_delta_ns = clockevent_delta2ns(4, evt);
|
||||
|
||||
*__this_cpu_ptr(msm_evt.percpu_evt) = evt;
|
||||
clockevents_register_device(evt);
|
||||
enable_percpu_irq(evt->irq, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void local_timer_stop(struct clock_event_device *evt)
|
||||
{
|
||||
evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt);
|
||||
disable_percpu_irq(evt->irq);
|
||||
}
|
||||
#endif /* CONFIG_LOCAL_TIMERS */
|
||||
|
||||
struct sys_timer msm_timer = {
|
||||
.init = msm_timer_init
|
||||
};
|
||||
|
@ -23,7 +23,6 @@ obj-$(CONFIG_TWL4030_CORE) += omap_twl.o
|
||||
|
||||
# SMP support ONLY available for OMAP4
|
||||
obj-$(CONFIG_SMP) += omap-smp.o omap-headsmp.o
|
||||
obj-$(CONFIG_LOCAL_TIMERS) += timer-mpu.o
|
||||
obj-$(CONFIG_HOTPLUG_CPU) += omap-hotplug.o
|
||||
obj-$(CONFIG_ARCH_OMAP4) += omap4-common.o omap-wakeupgen.o \
|
||||
sleep44xx.o
|
||||
|
@ -1,39 +0,0 @@
|
||||
/*
|
||||
* The MPU local timer source file. In OMAP4, both cortex-a9 cores have
|
||||
* own timer in it's MPU domain. These timers will be driving the
|
||||
* linux kernel SMP tick framework when active. These timers are not
|
||||
* part of the wake up domain.
|
||||
*
|
||||
* Copyright (C) 2009 Texas Instruments, Inc.
|
||||
*
|
||||
* Author:
|
||||
* Santosh Shilimkar <santosh.shilimkar@ti.com>
|
||||
*
|
||||
* This file is based on arm realview smp platform file.
|
||||
* Copyright (C) 2002 ARM 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/init.h>
|
||||
#include <linux/smp.h>
|
||||
#include <linux/clockchips.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/smp_twd.h>
|
||||
#include <asm/localtimer.h>
|
||||
|
||||
/*
|
||||
* Setup the local clock events for a CPU.
|
||||
*/
|
||||
int __cpuinit local_timer_setup(struct clock_event_device *evt)
|
||||
{
|
||||
/* Local timers are not supprted on OMAP4430 ES1.0 */
|
||||
if (omap_rev() == OMAP4430_REV_ES1_0)
|
||||
return -ENXIO;
|
||||
|
||||
evt->irq = OMAP44XX_IRQ_LOCALTIMER;
|
||||
twd_timer_setup(evt);
|
||||
return 0;
|
||||
}
|
||||
|
@ -39,7 +39,7 @@
|
||||
|
||||
#include <asm/mach/time.h>
|
||||
#include <plat/dmtimer.h>
|
||||
#include <asm/localtimer.h>
|
||||
#include <asm/smp_twd.h>
|
||||
#include <asm/sched_clock.h>
|
||||
#include "common.h"
|
||||
#include <plat/omap_hwmod.h>
|
||||
@ -324,14 +324,26 @@ OMAP_SYS_TIMER(3_secure)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARCH_OMAP4
|
||||
#ifdef CONFIG_LOCAL_TIMERS
|
||||
static DEFINE_TWD_LOCAL_TIMER(twd_local_timer,
|
||||
OMAP44XX_LOCAL_TWD_BASE,
|
||||
OMAP44XX_IRQ_LOCALTIMER);
|
||||
#endif
|
||||
|
||||
static void __init omap4_timer_init(void)
|
||||
{
|
||||
#ifdef CONFIG_LOCAL_TIMERS
|
||||
twd_base = ioremap(OMAP44XX_LOCAL_TWD_BASE, SZ_256);
|
||||
BUG_ON(!twd_base);
|
||||
#endif
|
||||
omap2_gp_clockevent_init(1, OMAP4_CLKEV_SOURCE);
|
||||
omap2_gp_clocksource_init(2, OMAP4_MPU_SOURCE);
|
||||
#ifdef CONFIG_LOCAL_TIMERS
|
||||
/* Local timers are not supprted on OMAP4430 ES1.0 */
|
||||
if (omap_rev() != OMAP4430_REV_ES1_0) {
|
||||
int err;
|
||||
|
||||
err = twd_local_timer_register(&twd_local_timer);
|
||||
if (err)
|
||||
pr_err("twd_local_timer_register failed %d\n", err);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
OMAP_SYS_TIMER(4)
|
||||
#endif
|
||||
|
@ -36,7 +36,7 @@
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/hardware/gic.h>
|
||||
#include <asm/hardware/cache-l2x0.h>
|
||||
#include <asm/localtimer.h>
|
||||
#include <asm/smp_twd.h>
|
||||
|
||||
#include <asm/mach/arch.h>
|
||||
#include <asm/mach/map.h>
|
||||
@ -383,6 +383,23 @@ static void realview_eb11mp_fixup(void)
|
||||
realview_eb_isp1761_resources[1].end = IRQ_EB11MP_USB;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HAVE_ARM_TWD
|
||||
static DEFINE_TWD_LOCAL_TIMER(twd_local_timer,
|
||||
REALVIEW_EB11MP_TWD_BASE,
|
||||
IRQ_LOCALTIMER);
|
||||
|
||||
static void __init realview_eb_twd_init(void)
|
||||
{
|
||||
if (core_tile_eb11mp() || core_tile_a9mp()) {
|
||||
int err = twd_local_timer_register(&twd_local_timer);
|
||||
if (err)
|
||||
pr_err("twd_local_timer_register failed %d\n", err);
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define realview_eb_twd_init() do { } while(0)
|
||||
#endif
|
||||
|
||||
static void __init realview_eb_timer_init(void)
|
||||
{
|
||||
unsigned int timer_irq;
|
||||
@ -392,15 +409,13 @@ static void __init realview_eb_timer_init(void)
|
||||
timer2_va_base = __io_address(REALVIEW_EB_TIMER2_3_BASE);
|
||||
timer3_va_base = __io_address(REALVIEW_EB_TIMER2_3_BASE) + 0x20;
|
||||
|
||||
if (core_tile_eb11mp() || core_tile_a9mp()) {
|
||||
#ifdef CONFIG_LOCAL_TIMERS
|
||||
twd_base = __io_address(REALVIEW_EB11MP_TWD_BASE);
|
||||
#endif
|
||||
if (core_tile_eb11mp() || core_tile_a9mp())
|
||||
timer_irq = IRQ_EB11MP_TIMER0_1;
|
||||
} else
|
||||
else
|
||||
timer_irq = IRQ_EB_TIMER0_1;
|
||||
|
||||
realview_timer_init(timer_irq);
|
||||
realview_eb_twd_init();
|
||||
}
|
||||
|
||||
static struct sys_timer realview_eb_timer = {
|
||||
|
@ -36,7 +36,7 @@
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/hardware/gic.h>
|
||||
#include <asm/hardware/cache-l2x0.h>
|
||||
#include <asm/localtimer.h>
|
||||
#include <asm/smp_twd.h>
|
||||
|
||||
#include <asm/mach/arch.h>
|
||||
#include <asm/mach/flash.h>
|
||||
@ -290,6 +290,21 @@ static void __init gic_init_irq(void)
|
||||
gic_cascade_irq(1, IRQ_TC11MP_PB_IRQ1);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HAVE_ARM_TWD
|
||||
static DEFINE_TWD_LOCAL_TIMER(twd_local_timer,
|
||||
REALVIEW_TC11MP_TWD_BASE,
|
||||
IRQ_LOCALTIMER);
|
||||
|
||||
static void __init realview_pb11mp_twd_init(void)
|
||||
{
|
||||
int err = twd_local_timer_register(&twd_local_timer);
|
||||
if (err)
|
||||
pr_err("twd_local_timer_register failed %d\n", err);
|
||||
}
|
||||
#else
|
||||
#define realview_pb11mp_twd_init() do {} while(0)
|
||||
#endif
|
||||
|
||||
static void __init realview_pb11mp_timer_init(void)
|
||||
{
|
||||
timer0_va_base = __io_address(REALVIEW_PB11MP_TIMER0_1_BASE);
|
||||
@ -297,10 +312,8 @@ static void __init realview_pb11mp_timer_init(void)
|
||||
timer2_va_base = __io_address(REALVIEW_PB11MP_TIMER2_3_BASE);
|
||||
timer3_va_base = __io_address(REALVIEW_PB11MP_TIMER2_3_BASE) + 0x20;
|
||||
|
||||
#ifdef CONFIG_LOCAL_TIMERS
|
||||
twd_base = __io_address(REALVIEW_TC11MP_TWD_BASE);
|
||||
#endif
|
||||
realview_timer_init(IRQ_TC11MP_TIMER0_1);
|
||||
realview_pb11mp_twd_init();
|
||||
}
|
||||
|
||||
static struct sys_timer realview_pb11mp_timer = {
|
||||
|
@ -298,6 +298,21 @@ static void __init gic_init_irq(void)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HAVE_ARM_TWD
|
||||
static DEFINE_TWD_LOCAL_TIMER(twd_local_timer,
|
||||
REALVIEW_PBX_TILE_TWD_BASE,
|
||||
IRQ_LOCALTIMER);
|
||||
|
||||
static void __init realview_pbx_twd_init(void)
|
||||
{
|
||||
int err = twd_local_timer_register(&twd_local_timer);
|
||||
if (err)
|
||||
pr_err("twd_local_timer_register failed %d\n", err);
|
||||
}
|
||||
#else
|
||||
#define realview_pbx_twd_init() do { } while(0)
|
||||
#endif
|
||||
|
||||
static void __init realview_pbx_timer_init(void)
|
||||
{
|
||||
timer0_va_base = __io_address(REALVIEW_PBX_TIMER0_1_BASE);
|
||||
@ -305,11 +320,8 @@ static void __init realview_pbx_timer_init(void)
|
||||
timer2_va_base = __io_address(REALVIEW_PBX_TIMER2_3_BASE);
|
||||
timer3_va_base = __io_address(REALVIEW_PBX_TIMER2_3_BASE) + 0x20;
|
||||
|
||||
#ifdef CONFIG_LOCAL_TIMERS
|
||||
if (core_tile_pbx11mp() || core_tile_pbxa9mp())
|
||||
twd_base = __io_address(REALVIEW_PBX_TILE_TWD_BASE);
|
||||
#endif
|
||||
realview_timer_init(IRQ_PBX_TIMER0_1);
|
||||
realview_pbx_twd_init();
|
||||
}
|
||||
|
||||
static struct sys_timer realview_pbx_timer = {
|
||||
|
@ -16,7 +16,6 @@ obj-$(CONFIG_ARCH_R8A7779) += setup-r8a7779.o clock-r8a7779.o intc-r8a7779.o
|
||||
# SMP objects
|
||||
smp-y := platsmp.o headsmp.o
|
||||
smp-$(CONFIG_HOTPLUG_CPU) += hotplug.o
|
||||
smp-$(CONFIG_LOCAL_TIMERS) += localtimer.o
|
||||
smp-$(CONFIG_ARCH_SH73A0) += smp-sh73a0.o
|
||||
smp-$(CONFIG_ARCH_R8A7779) += smp-r8a7779.o
|
||||
|
||||
|
@ -2,6 +2,8 @@
|
||||
#define __ARCH_MACH_COMMON_H
|
||||
|
||||
extern struct sys_timer shmobile_timer;
|
||||
struct twd_local_timer;
|
||||
void shmobile_twd_init(struct twd_local_timer *twd_local_timer);
|
||||
extern void shmobile_setup_console(void);
|
||||
extern void shmobile_secondary_vector(void);
|
||||
extern int shmobile_platform_cpu_kill(unsigned int cpu);
|
||||
|
@ -1,26 +0,0 @@
|
||||
/*
|
||||
* SMP support for R-Mobile / SH-Mobile - local timer portion
|
||||
*
|
||||
* Copyright (C) 2010 Magnus Damm
|
||||
*
|
||||
* Based on vexpress, 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/smp.h>
|
||||
#include <linux/clockchips.h>
|
||||
#include <asm/smp_twd.h>
|
||||
#include <asm/localtimer.h>
|
||||
|
||||
/*
|
||||
* Setup the local clock events for a CPU.
|
||||
*/
|
||||
int __cpuinit local_timer_setup(struct clock_event_device *evt)
|
||||
{
|
||||
evt->irq = 29;
|
||||
twd_timer_setup(evt);
|
||||
return 0;
|
||||
}
|
@ -17,7 +17,6 @@
|
||||
#include <linux/smp.h>
|
||||
#include <linux/io.h>
|
||||
#include <asm/hardware/gic.h>
|
||||
#include <asm/localtimer.h>
|
||||
#include <asm/mach-types.h>
|
||||
#include <mach/common.h>
|
||||
|
||||
|
@ -64,6 +64,8 @@ static void __iomem *scu_base_addr(void)
|
||||
static DEFINE_SPINLOCK(scu_lock);
|
||||
static unsigned long tmp;
|
||||
|
||||
static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, 0xf0000600, 29);
|
||||
|
||||
static void modify_scu_cpu_psr(unsigned long set, unsigned long clr)
|
||||
{
|
||||
void __iomem *scu_base = scu_base_addr();
|
||||
@ -82,11 +84,7 @@ unsigned int __init r8a7779_get_core_count(void)
|
||||
{
|
||||
void __iomem *scu_base = scu_base_addr();
|
||||
|
||||
#ifdef CONFIG_HAVE_ARM_TWD
|
||||
/* twd_base needs to be initialized before percpu_timer_setup() */
|
||||
twd_base = (void __iomem *)0xf0000600;
|
||||
#endif
|
||||
|
||||
shmobile_twd_init(&twd_local_timer);
|
||||
return scu_get_core_count(scu_base);
|
||||
}
|
||||
|
||||
|
@ -42,6 +42,8 @@ static void __iomem *scu_base_addr(void)
|
||||
static DEFINE_SPINLOCK(scu_lock);
|
||||
static unsigned long tmp;
|
||||
|
||||
static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, 0xf0000600, 29);
|
||||
|
||||
static void modify_scu_cpu_psr(unsigned long set, unsigned long clr)
|
||||
{
|
||||
void __iomem *scu_base = scu_base_addr();
|
||||
@ -60,11 +62,7 @@ unsigned int __init sh73a0_get_core_count(void)
|
||||
{
|
||||
void __iomem *scu_base = scu_base_addr();
|
||||
|
||||
#ifdef CONFIG_HAVE_ARM_TWD
|
||||
/* twd_base needs to be initialized before percpu_timer_setup() */
|
||||
twd_base = (void __iomem *)0xf0000600;
|
||||
#endif
|
||||
|
||||
shmobile_twd_init(&twd_local_timer);
|
||||
return scu_get_core_count(scu_base);
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,7 @@
|
||||
*/
|
||||
#include <linux/platform_device.h>
|
||||
#include <asm/mach/time.h>
|
||||
#include <asm/smp_twd.h>
|
||||
|
||||
static void __init shmobile_late_time_init(void)
|
||||
{
|
||||
@ -41,6 +42,15 @@ static void __init shmobile_timer_init(void)
|
||||
late_time_init = shmobile_late_time_init;
|
||||
}
|
||||
|
||||
void __init shmobile_twd_init(struct twd_local_timer *twd_local_timer)
|
||||
{
|
||||
#ifdef CONFIG_HAVE_ARM_TWD
|
||||
int err = twd_local_timer_register(twd_local_timer);
|
||||
if (err)
|
||||
pr_err("twd_local_timer_register failed %d\n", err);
|
||||
#endif
|
||||
}
|
||||
|
||||
struct sys_timer shmobile_timer = {
|
||||
.init = shmobile_timer_init,
|
||||
};
|
||||
|
@ -13,7 +13,7 @@ obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra2_emc.o
|
||||
obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += pinmux-tegra20-tables.o
|
||||
obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += pinmux-tegra30-tables.o
|
||||
obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += board-dt-tegra30.o
|
||||
obj-$(CONFIG_SMP) += platsmp.o localtimer.o headsmp.o
|
||||
obj-$(CONFIG_SMP) += platsmp.o headsmp.o
|
||||
obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
|
||||
obj-$(CONFIG_TEGRA_SYSTEM_DMA) += dma.o
|
||||
obj-$(CONFIG_CPU_FREQ) += cpu-tegra.o
|
||||
|
@ -1,26 +0,0 @@
|
||||
/*
|
||||
* arch/arm/mach-tegra/localtimer.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/smp.h>
|
||||
#include <linux/clockchips.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/smp_twd.h>
|
||||
#include <asm/localtimer.h>
|
||||
|
||||
/*
|
||||
* Setup the local clock events for a CPU.
|
||||
*/
|
||||
int __cpuinit local_timer_setup(struct clock_event_device *evt)
|
||||
{
|
||||
evt->irq = IRQ_LOCALTIMER;
|
||||
twd_timer_setup(evt);
|
||||
return 0;
|
||||
}
|
@ -28,7 +28,7 @@
|
||||
#include <linux/io.h>
|
||||
|
||||
#include <asm/mach/time.h>
|
||||
#include <asm/localtimer.h>
|
||||
#include <asm/smp_twd.h>
|
||||
#include <asm/sched_clock.h>
|
||||
|
||||
#include <mach/iomap.h>
|
||||
@ -162,6 +162,21 @@ static struct irqaction tegra_timer_irq = {
|
||||
.irq = INT_TMR3,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_HAVE_ARM_TWD
|
||||
static DEFINE_TWD_LOCAL_TIMER(twd_local_timer,
|
||||
TEGRA_ARM_PERIF_BASE + 0x600,
|
||||
IRQ_LOCALTIMER);
|
||||
|
||||
static void __init tegra_twd_init(void)
|
||||
{
|
||||
int err = twd_local_timer_register(&twd_local_timer);
|
||||
if (err)
|
||||
pr_err("twd_local_timer_register failed %d\n", err);
|
||||
}
|
||||
#else
|
||||
#define tegra_twd_init() do {} while(0)
|
||||
#endif
|
||||
|
||||
static void __init tegra_init_timer(void)
|
||||
{
|
||||
struct clk *clk;
|
||||
@ -188,10 +203,6 @@ static void __init tegra_init_timer(void)
|
||||
else
|
||||
clk_enable(clk);
|
||||
|
||||
#ifdef CONFIG_HAVE_ARM_TWD
|
||||
twd_base = IO_ADDRESS(TEGRA_ARM_PERIF_BASE + 0x600);
|
||||
#endif
|
||||
|
||||
switch (rate) {
|
||||
case 12000000:
|
||||
timer_writel(0x000b, TIMERUS_USEC_CFG);
|
||||
@ -231,6 +242,7 @@ static void __init tegra_init_timer(void)
|
||||
tegra_clockevent.cpumask = cpu_all_mask;
|
||||
tegra_clockevent.irq = tegra_timer_irq.irq;
|
||||
clockevents_register_device(&tegra_clockevent);
|
||||
tegra_twd_init();
|
||||
}
|
||||
|
||||
struct sys_timer tegra_timer = {
|
||||
|
@ -15,7 +15,6 @@ obj-$(CONFIG_MACH_U8500) += board-mop500.o board-mop500-sdi.o \
|
||||
obj-$(CONFIG_MACH_U5500) += board-u5500.o board-u5500-sdi.o
|
||||
obj-$(CONFIG_SMP) += platsmp.o headsmp.o
|
||||
obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
|
||||
obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o
|
||||
obj-$(CONFIG_U5500_MODEM_IRQ) += modem-irq-db5500.o
|
||||
obj-$(CONFIG_U5500_MBOX) += mbox-db5500.o
|
||||
|
||||
|
@ -14,7 +14,6 @@
|
||||
|
||||
#include <asm/hardware/gic.h>
|
||||
#include <asm/mach/map.h>
|
||||
#include <asm/localtimer.h>
|
||||
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/setup.h>
|
||||
|
@ -1,29 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2009 ST-Ericsson
|
||||
* Srinidhi Kasagar <srinidhi.kasagar@stericsson.com>
|
||||
*
|
||||
* This file is heavily based on relaview platform, almost a copy.
|
||||
*
|
||||
* Copyright (C) 2002 ARM 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/init.h>
|
||||
#include <linux/smp.h>
|
||||
#include <linux/clockchips.h>
|
||||
|
||||
#include <asm/irq.h>
|
||||
#include <asm/smp_twd.h>
|
||||
#include <asm/localtimer.h>
|
||||
|
||||
/*
|
||||
* Setup the local clock events for a CPU.
|
||||
*/
|
||||
int __cpuinit local_timer_setup(struct clock_event_device *evt)
|
||||
{
|
||||
evt->irq = IRQ_LOCALTIMER;
|
||||
twd_timer_setup(evt);
|
||||
return 0;
|
||||
}
|
@ -8,28 +8,45 @@
|
||||
#include <linux/errno.h>
|
||||
#include <linux/clksrc-dbx500-prcmu.h>
|
||||
|
||||
#include <asm/localtimer.h>
|
||||
#include <asm/smp_twd.h>
|
||||
|
||||
#include <plat/mtu.h>
|
||||
|
||||
#include <mach/setup.h>
|
||||
#include <mach/hardware.h>
|
||||
|
||||
#ifdef CONFIG_HAVE_ARM_TWD
|
||||
static DEFINE_TWD_LOCAL_TIMER(u5500_twd_local_timer,
|
||||
U5500_TWD_BASE, IRQ_LOCALTIMER);
|
||||
static DEFINE_TWD_LOCAL_TIMER(u8500_twd_local_timer,
|
||||
U8500_TWD_BASE, IRQ_LOCALTIMER);
|
||||
|
||||
static void __init ux500_twd_init(void)
|
||||
{
|
||||
struct twd_local_timer *twd_local_timer;
|
||||
int err;
|
||||
|
||||
twd_local_timer = cpu_is_u5500() ? &u5500_twd_local_timer :
|
||||
&u8500_twd_local_timer;
|
||||
|
||||
err = twd_local_timer_register(twd_local_timer);
|
||||
if (err)
|
||||
pr_err("twd_local_timer_register failed %d\n", err);
|
||||
}
|
||||
#else
|
||||
#define ux500_twd_init() do { } while(0)
|
||||
#endif
|
||||
|
||||
static void __init ux500_timer_init(void)
|
||||
{
|
||||
void __iomem *mtu_timer_base;
|
||||
void __iomem *prcmu_timer_base;
|
||||
int err;
|
||||
|
||||
if (cpu_is_u5500()) {
|
||||
#ifdef CONFIG_LOCAL_TIMERS
|
||||
twd_base = __io_address(U5500_TWD_BASE);
|
||||
#endif
|
||||
mtu_timer_base = __io_address(U5500_MTU0_BASE);
|
||||
prcmu_timer_base = __io_address(U5500_PRCMU_TIMER_3_BASE);
|
||||
} else if (cpu_is_u8500()) {
|
||||
#ifdef CONFIG_LOCAL_TIMERS
|
||||
twd_base = __io_address(U8500_TWD_BASE);
|
||||
#endif
|
||||
mtu_timer_base = __io_address(U8500_MTU0_BASE);
|
||||
prcmu_timer_base = __io_address(U8500_PRCMU_TIMER_4_BASE);
|
||||
} else {
|
||||
@ -55,6 +72,7 @@ static void __init ux500_timer_init(void)
|
||||
|
||||
nmdk_timer_init(mtu_timer_base);
|
||||
clksrc_dbx500_prcmu_init(prcmu_timer_base);
|
||||
ux500_twd_init();
|
||||
}
|
||||
|
||||
static void ux500_timer_reset(void)
|
||||
|
@ -42,15 +42,26 @@ static struct map_desc ct_ca9x4_io_desc[] __initdata = {
|
||||
static void __init ct_ca9x4_map_io(void)
|
||||
{
|
||||
iotable_init(ct_ca9x4_io_desc, ARRAY_SIZE(ct_ca9x4_io_desc));
|
||||
#ifdef CONFIG_LOCAL_TIMERS
|
||||
twd_base = ioremap(A9_MPCORE_TWD, SZ_32);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HAVE_ARM_TWD
|
||||
static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, A9_MPCORE_TWD, IRQ_LOCALTIMER);
|
||||
|
||||
static void __init ca9x4_twd_init(void)
|
||||
{
|
||||
int err = twd_local_timer_register(&twd_local_timer);
|
||||
if (err)
|
||||
pr_err("twd_local_timer_register failed %d\n", err);
|
||||
}
|
||||
#else
|
||||
#define ca9x4_twd_init() do {} while(0)
|
||||
#endif
|
||||
|
||||
static void __init ct_ca9x4_init_irq(void)
|
||||
{
|
||||
gic_init(0, 29, ioremap(A9_MPCORE_GIC_DIST, SZ_4K),
|
||||
ioremap(A9_MPCORE_GIC_CPU, SZ_256));
|
||||
ca9x4_twd_init();
|
||||
}
|
||||
|
||||
static void ct_ca9x4_clcd_enable(struct clcd_fb *fb)
|
||||
|
@ -1,5 +1,4 @@
|
||||
obj-y := clock.o
|
||||
obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o
|
||||
obj-$(CONFIG_PLAT_VERSATILE_CLCD) += clcd.o
|
||||
obj-$(CONFIG_PLAT_VERSATILE_FPGA_IRQ) += fpga-irq.o
|
||||
obj-$(CONFIG_PLAT_VERSATILE_LEDS) += leds.o
|
||||
|
@ -1,53 +0,0 @@
|
||||
/*
|
||||
* linux/arch/arm/plat-versatile/localtimer.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/smp.h>
|
||||
#include <linux/clockchips.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
|
||||
#include <asm/smp_twd.h>
|
||||
#include <asm/localtimer.h>
|
||||
#include <mach/irqs.h>
|
||||
|
||||
const static struct of_device_id twd_of_match[] __initconst = {
|
||||
{ .compatible = "arm,cortex-a9-twd-timer", },
|
||||
{ .compatible = "arm,cortex-a5-twd-timer", },
|
||||
{ .compatible = "arm,arm11mp-twd-timer", },
|
||||
{ },
|
||||
};
|
||||
|
||||
/*
|
||||
* Setup the local clock events for a CPU.
|
||||
*/
|
||||
int __cpuinit local_timer_setup(struct clock_event_device *evt)
|
||||
{
|
||||
#if defined(CONFIG_OF)
|
||||
static int dt_node_probed;
|
||||
|
||||
/* Look for TWD node only once */
|
||||
if (!dt_node_probed) {
|
||||
struct device_node *node = of_find_matching_node(NULL,
|
||||
twd_of_match);
|
||||
|
||||
if (node)
|
||||
twd_base = of_iomap(node, 0);
|
||||
|
||||
dt_node_probed = 1;
|
||||
}
|
||||
#endif
|
||||
if (!twd_base)
|
||||
return -ENXIO;
|
||||
|
||||
evt->irq = IRQ_LOCALTIMER;
|
||||
twd_timer_setup(evt);
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user