RealView: Use only the shadow mapping of ARM11MPCore local timers
All the cases where the local timer for a CPU is accessed happen on the corresponding current CPU, hence no need to access the per-CPU local timer mappings. Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
This commit is contained in:
Родитель
4c3ea37171
Коммит
ebac6546df
|
@ -114,7 +114,7 @@ extern void local_timer_interrupt(void);
|
||||||
/*
|
/*
|
||||||
* Stop a local timer interrupt.
|
* Stop a local timer interrupt.
|
||||||
*/
|
*/
|
||||||
extern void local_timer_stop(unsigned int cpu);
|
extern void local_timer_stop(void);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Platform provides this to acknowledge a local timer IRQ
|
* Platform provides this to acknowledge a local timer IRQ
|
||||||
|
@ -123,7 +123,7 @@ extern int local_timer_ack(void);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
static inline void local_timer_stop(unsigned int cpu)
|
static inline void local_timer_stop(void)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,7 +132,7 @@ static inline void local_timer_stop(unsigned int cpu)
|
||||||
/*
|
/*
|
||||||
* Setup a local timer interrupt for a CPU.
|
* Setup a local timer interrupt for a CPU.
|
||||||
*/
|
*/
|
||||||
extern void local_timer_setup(unsigned int cpu);
|
extern void local_timer_setup(void);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* show local interrupt info
|
* show local interrupt info
|
||||||
|
|
|
@ -181,7 +181,7 @@ int __cpuexit __cpu_disable(void)
|
||||||
/*
|
/*
|
||||||
* Stop the local timer for this CPU.
|
* Stop the local timer for this CPU.
|
||||||
*/
|
*/
|
||||||
local_timer_stop(cpu);
|
local_timer_stop();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Flush user cache and TLB mappings, and then remove this CPU
|
* Flush user cache and TLB mappings, and then remove this CPU
|
||||||
|
@ -284,7 +284,7 @@ asmlinkage void __cpuinit secondary_start_kernel(void)
|
||||||
/*
|
/*
|
||||||
* Setup local timer for this CPU.
|
* Setup local timer for this CPU.
|
||||||
*/
|
*/
|
||||||
local_timer_setup(cpu);
|
local_timer_setup();
|
||||||
|
|
||||||
calibrate_delay();
|
calibrate_delay();
|
||||||
|
|
||||||
|
|
|
@ -629,7 +629,7 @@ void __init realview_timer_init(unsigned int timer_irq)
|
||||||
* The dummy clock device has to be registered before the main device
|
* The dummy clock device has to be registered before the main device
|
||||||
* so that the latter will broadcast the clock events
|
* so that the latter will broadcast the clock events
|
||||||
*/
|
*/
|
||||||
local_timer_setup(smp_processor_id());
|
local_timer_setup();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -52,8 +52,7 @@ extern struct clk realview_clcd_clk;
|
||||||
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
|
#ifdef CONFIG_LOCAL_TIMERS
|
||||||
extern void __iomem *twd_base_addr;
|
extern void __iomem *twd_base;
|
||||||
extern unsigned int twd_size;
|
|
||||||
#endif
|
#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;
|
||||||
|
|
|
@ -49,16 +49,14 @@
|
||||||
#ifdef CONFIG_REALVIEW_EB_ARM11MP_REVB
|
#ifdef CONFIG_REALVIEW_EB_ARM11MP_REVB
|
||||||
#define REALVIEW_EB11MP_SCU_BASE 0x10100000 /* SCU registers */
|
#define REALVIEW_EB11MP_SCU_BASE 0x10100000 /* SCU registers */
|
||||||
#define REALVIEW_EB11MP_GIC_CPU_BASE 0x10100100 /* Generic interrupt controller CPU interface */
|
#define REALVIEW_EB11MP_GIC_CPU_BASE 0x10100100 /* Generic interrupt controller CPU interface */
|
||||||
#define REALVIEW_EB11MP_TWD_BASE 0x10100700
|
#define REALVIEW_EB11MP_TWD_BASE 0x10100600
|
||||||
#define REALVIEW_EB11MP_TWD_SIZE 0x00000100
|
|
||||||
#define REALVIEW_EB11MP_GIC_DIST_BASE 0x10101000 /* Generic interrupt controller distributor */
|
#define REALVIEW_EB11MP_GIC_DIST_BASE 0x10101000 /* Generic interrupt controller distributor */
|
||||||
#define REALVIEW_EB11MP_L220_BASE 0x10102000 /* L220 registers */
|
#define REALVIEW_EB11MP_L220_BASE 0x10102000 /* L220 registers */
|
||||||
#define REALVIEW_EB11MP_SYS_PLD_CTRL1 0xD8 /* Register offset for MPCore sysctl */
|
#define REALVIEW_EB11MP_SYS_PLD_CTRL1 0xD8 /* Register offset for MPCore sysctl */
|
||||||
#else
|
#else
|
||||||
#define REALVIEW_EB11MP_SCU_BASE 0x1F000000 /* SCU registers */
|
#define REALVIEW_EB11MP_SCU_BASE 0x1F000000 /* SCU registers */
|
||||||
#define REALVIEW_EB11MP_GIC_CPU_BASE 0x1F000100 /* Generic interrupt controller CPU interface */
|
#define REALVIEW_EB11MP_GIC_CPU_BASE 0x1F000100 /* Generic interrupt controller CPU interface */
|
||||||
#define REALVIEW_EB11MP_TWD_BASE 0x1F000700
|
#define REALVIEW_EB11MP_TWD_BASE 0x1F000600
|
||||||
#define REALVIEW_EB11MP_TWD_SIZE 0x00000100
|
|
||||||
#define REALVIEW_EB11MP_GIC_DIST_BASE 0x1F001000 /* Generic interrupt controller distributor */
|
#define REALVIEW_EB11MP_GIC_DIST_BASE 0x1F001000 /* Generic interrupt controller distributor */
|
||||||
#define REALVIEW_EB11MP_L220_BASE 0x1F002000 /* L220 registers */
|
#define REALVIEW_EB11MP_L220_BASE 0x1F002000 /* L220 registers */
|
||||||
#define REALVIEW_EB11MP_SYS_PLD_CTRL1 0x74 /* Register offset for MPCore sysctl */
|
#define REALVIEW_EB11MP_SYS_PLD_CTRL1 0x74 /* Register offset for MPCore sysctl */
|
||||||
|
|
|
@ -77,8 +77,7 @@
|
||||||
*/
|
*/
|
||||||
#define REALVIEW_TC11MP_SCU_BASE 0x1F000000 /* IRQ, Test chip */
|
#define REALVIEW_TC11MP_SCU_BASE 0x1F000000 /* IRQ, Test chip */
|
||||||
#define REALVIEW_TC11MP_GIC_CPU_BASE 0x1F000100 /* Test chip interrupt controller CPU interface */
|
#define REALVIEW_TC11MP_GIC_CPU_BASE 0x1F000100 /* Test chip interrupt controller CPU interface */
|
||||||
#define REALVIEW_TC11MP_TWD_BASE 0x1F000700
|
#define REALVIEW_TC11MP_TWD_BASE 0x1F000600
|
||||||
#define REALVIEW_TC11MP_TWD_SIZE 0x00000100
|
|
||||||
#define REALVIEW_TC11MP_GIC_DIST_BASE 0x1F001000 /* Test chip interrupt controller distributor */
|
#define REALVIEW_TC11MP_GIC_DIST_BASE 0x1F001000 /* Test chip interrupt controller distributor */
|
||||||
#define REALVIEW_TC11MP_L220_BASE 0x1F002000 /* L220 registers */
|
#define REALVIEW_TC11MP_L220_BASE 0x1F002000 /* L220 registers */
|
||||||
|
|
||||||
|
|
|
@ -38,18 +38,14 @@ void local_timer_interrupt(void)
|
||||||
|
|
||||||
#ifdef CONFIG_LOCAL_TIMERS
|
#ifdef CONFIG_LOCAL_TIMERS
|
||||||
|
|
||||||
#define TWD_BASE(cpu) (twd_base_addr + (cpu) * twd_size)
|
|
||||||
|
|
||||||
/* set up by the platform code */
|
/* set up by the platform code */
|
||||||
void __iomem *twd_base_addr;
|
void __iomem *twd_base;
|
||||||
unsigned int twd_size;
|
|
||||||
|
|
||||||
static unsigned long mpcore_timer_rate;
|
static unsigned long mpcore_timer_rate;
|
||||||
|
|
||||||
static void local_timer_set_mode(enum clock_event_mode mode,
|
static void local_timer_set_mode(enum clock_event_mode mode,
|
||||||
struct clock_event_device *clk)
|
struct clock_event_device *clk)
|
||||||
{
|
{
|
||||||
void __iomem *base = TWD_BASE(smp_processor_id());
|
|
||||||
unsigned long ctrl;
|
unsigned long ctrl;
|
||||||
|
|
||||||
switch(mode) {
|
switch(mode) {
|
||||||
|
@ -68,17 +64,16 @@ static void local_timer_set_mode(enum clock_event_mode mode,
|
||||||
ctrl = 0;
|
ctrl = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
__raw_writel(ctrl, base + TWD_TIMER_CONTROL);
|
__raw_writel(ctrl, twd_base + TWD_TIMER_CONTROL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int local_timer_set_next_event(unsigned long evt,
|
static int local_timer_set_next_event(unsigned long evt,
|
||||||
struct clock_event_device *unused)
|
struct clock_event_device *unused)
|
||||||
{
|
{
|
||||||
void __iomem *base = TWD_BASE(smp_processor_id());
|
unsigned long ctrl = __raw_readl(twd_base + TWD_TIMER_CONTROL);
|
||||||
unsigned long ctrl = __raw_readl(base + TWD_TIMER_CONTROL);
|
|
||||||
|
|
||||||
__raw_writel(evt, base + TWD_TIMER_COUNTER);
|
__raw_writel(evt, twd_base + TWD_TIMER_COUNTER);
|
||||||
__raw_writel(ctrl | TWD_TIMER_CONTROL_ENABLE, base + TWD_TIMER_CONTROL);
|
__raw_writel(ctrl | TWD_TIMER_CONTROL_ENABLE, twd_base + TWD_TIMER_CONTROL);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -91,19 +86,16 @@ static int local_timer_set_next_event(unsigned long evt,
|
||||||
*/
|
*/
|
||||||
int local_timer_ack(void)
|
int local_timer_ack(void)
|
||||||
{
|
{
|
||||||
void __iomem *base = TWD_BASE(smp_processor_id());
|
if (__raw_readl(twd_base + TWD_TIMER_INTSTAT)) {
|
||||||
|
__raw_writel(1, twd_base + TWD_TIMER_INTSTAT);
|
||||||
if (__raw_readl(base + TWD_TIMER_INTSTAT)) {
|
|
||||||
__raw_writel(1, base + TWD_TIMER_INTSTAT);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __cpuinit twd_calibrate_rate(unsigned int cpu)
|
static void __cpuinit twd_calibrate_rate(void)
|
||||||
{
|
{
|
||||||
void __iomem *base = TWD_BASE(cpu);
|
|
||||||
unsigned long load, count;
|
unsigned long load, count;
|
||||||
u64 waitjiffies;
|
u64 waitjiffies;
|
||||||
|
|
||||||
|
@ -124,15 +116,15 @@ static void __cpuinit twd_calibrate_rate(unsigned int cpu)
|
||||||
waitjiffies += 5;
|
waitjiffies += 5;
|
||||||
|
|
||||||
/* enable, no interrupt or reload */
|
/* enable, no interrupt or reload */
|
||||||
__raw_writel(0x1, base + TWD_TIMER_CONTROL);
|
__raw_writel(0x1, twd_base + TWD_TIMER_CONTROL);
|
||||||
|
|
||||||
/* maximum value */
|
/* maximum value */
|
||||||
__raw_writel(0xFFFFFFFFU, base + TWD_TIMER_COUNTER);
|
__raw_writel(0xFFFFFFFFU, twd_base + TWD_TIMER_COUNTER);
|
||||||
|
|
||||||
while (get_jiffies_64() < waitjiffies)
|
while (get_jiffies_64() < waitjiffies)
|
||||||
udelay(10);
|
udelay(10);
|
||||||
|
|
||||||
count = __raw_readl(base + TWD_TIMER_COUNTER);
|
count = __raw_readl(twd_base + TWD_TIMER_COUNTER);
|
||||||
|
|
||||||
mpcore_timer_rate = (0xFFFFFFFFU - count) * (HZ / 5);
|
mpcore_timer_rate = (0xFFFFFFFFU - count) * (HZ / 5);
|
||||||
|
|
||||||
|
@ -142,18 +134,19 @@ static void __cpuinit twd_calibrate_rate(unsigned int cpu)
|
||||||
|
|
||||||
load = mpcore_timer_rate / HZ;
|
load = mpcore_timer_rate / HZ;
|
||||||
|
|
||||||
__raw_writel(load, base + TWD_TIMER_LOAD);
|
__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(unsigned int cpu)
|
void __cpuinit local_timer_setup(void)
|
||||||
{
|
{
|
||||||
|
unsigned int cpu = smp_processor_id();
|
||||||
struct clock_event_device *clk = &per_cpu(local_clockevent, cpu);
|
struct clock_event_device *clk = &per_cpu(local_clockevent, cpu);
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
twd_calibrate_rate(cpu);
|
twd_calibrate_rate();
|
||||||
|
|
||||||
clk->name = "local_timer";
|
clk->name = "local_timer";
|
||||||
clk->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
|
clk->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
|
||||||
|
@ -178,9 +171,9 @@ void __cpuinit local_timer_setup(unsigned int cpu)
|
||||||
/*
|
/*
|
||||||
* take a local timer down
|
* take a local timer down
|
||||||
*/
|
*/
|
||||||
void __cpuexit local_timer_stop(unsigned int cpu)
|
void __cpuexit local_timer_stop(void)
|
||||||
{
|
{
|
||||||
__raw_writel(0, TWD_BASE(cpu) + TWD_TIMER_CONTROL);
|
__raw_writel(0, twd_base + TWD_TIMER_CONTROL);
|
||||||
}
|
}
|
||||||
|
|
||||||
#else /* CONFIG_LOCAL_TIMERS */
|
#else /* CONFIG_LOCAL_TIMERS */
|
||||||
|
@ -190,8 +183,9 @@ static void dummy_timer_set_mode(enum clock_event_mode mode,
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void __cpuinit local_timer_setup(unsigned int cpu)
|
void __cpuinit local_timer_setup(void)
|
||||||
{
|
{
|
||||||
|
unsigned int cpu = smp_processor_id();
|
||||||
struct clock_event_device *clk = &per_cpu(local_clockevent, cpu);
|
struct clock_event_device *clk = &per_cpu(local_clockevent, cpu);
|
||||||
|
|
||||||
clk->name = "dummy_timer";
|
clk->name = "dummy_timer";
|
||||||
|
|
|
@ -238,7 +238,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
|
||||||
if ((machine_is_realview_eb() &&
|
if ((machine_is_realview_eb() &&
|
||||||
(core_tile_eb11mp() || core_tile_a9mp())) ||
|
(core_tile_eb11mp() || core_tile_a9mp())) ||
|
||||||
machine_is_realview_pb11mp())
|
machine_is_realview_pb11mp())
|
||||||
local_timer_setup(cpu);
|
local_timer_setup();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -344,8 +344,7 @@ static void __init realview_eb_timer_init(void)
|
||||||
|
|
||||||
if (core_tile_eb11mp() || core_tile_a9mp()) {
|
if (core_tile_eb11mp() || core_tile_a9mp()) {
|
||||||
#ifdef CONFIG_LOCAL_TIMERS
|
#ifdef CONFIG_LOCAL_TIMERS
|
||||||
twd_base_addr = __io_address(REALVIEW_EB11MP_TWD_BASE);
|
twd_base = __io_address(REALVIEW_EB11MP_TWD_BASE);
|
||||||
twd_size = REALVIEW_EB11MP_TWD_SIZE;
|
|
||||||
#endif
|
#endif
|
||||||
timer_irq = IRQ_EB11MP_TIMER0_1;
|
timer_irq = IRQ_EB11MP_TIMER0_1;
|
||||||
} else
|
} else
|
||||||
|
|
|
@ -292,8 +292,7 @@ static void __init realview_pb11mp_timer_init(void)
|
||||||
timer3_va_base = __io_address(REALVIEW_PB11MP_TIMER2_3_BASE) + 0x20;
|
timer3_va_base = __io_address(REALVIEW_PB11MP_TIMER2_3_BASE) + 0x20;
|
||||||
|
|
||||||
#ifdef CONFIG_LOCAL_TIMERS
|
#ifdef CONFIG_LOCAL_TIMERS
|
||||||
twd_base_addr = __io_address(REALVIEW_TC11MP_TWD_BASE);
|
twd_base = __io_address(REALVIEW_TC11MP_TWD_BASE);
|
||||||
twd_size = REALVIEW_TC11MP_TWD_SIZE;
|
|
||||||
#endif
|
#endif
|
||||||
realview_timer_init(IRQ_TC11MP_TIMER0_1);
|
realview_timer_init(IRQ_TC11MP_TIMER0_1);
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче