Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 188468
b: refs/heads/master
c: 0d152c2
h: refs/heads/master
v: v3
  • Loading branch information
Yi Li authored and Mike Frysinger committed Mar 9, 2010
1 parent 7250141 commit 4f3143c
Show file tree
Hide file tree
Showing 8 changed files with 147 additions and 124 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 682f5dc4ed7cdef1f55e40ee505c4346dfa6fa91
refs/heads/master: 0d152c27e336b5fd777da7dd3e814617e7305afd
26 changes: 13 additions & 13 deletions trunk/arch/blackfin/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ endchoice

config SMP
depends on BF561
select GENERIC_CLOCKEVENTS
select TICKSOURCE_CORETMR
bool "Symmetric multi-processing support"
---help---
This enables support for systems with more than one CPU,
Expand Down Expand Up @@ -610,23 +610,23 @@ config GENERIC_CLOCKEVENTS
bool "Generic clock events"
default y

choice
prompt "Kernel Tick Source"
menu "Clock event device"
depends on GENERIC_CLOCKEVENTS
default TICKSOURCE_CORETMR

config TICKSOURCE_GPTMR0
bool "Gptimer0 (SCLK domain)"
bool "GPTimer0"
depends on !SMP
select BFIN_GPTIMERS

config TICKSOURCE_CORETMR
bool "Core timer (CCLK domain)"

endchoice
bool "Core timer"
default y
endmenu

config CYCLES_CLOCKSOURCE
bool "Use 'CYCLES' as a clocksource"
menu "Clock souce"
depends on GENERIC_CLOCKEVENTS
config CYCLES_CLOCKSOURCE
bool "CYCLES"
default y
depends on !BFIN_SCRATCH_REG_CYCLES
depends on !SMP
help
Expand All @@ -637,10 +637,10 @@ config CYCLES_CLOCKSOURCE
writing the registers will most likely crash the kernel.

config GPTMR0_CLOCKSOURCE
bool "Use GPTimer0 as a clocksource"
bool "GPTimer0"
select BFIN_GPTIMERS
depends on GENERIC_CLOCKEVENTS
depends on !TICKSOURCE_GPTMR0
endmenu

config ARCH_USES_GETTIMEOFFSET
depends on !GENERIC_CLOCKEVENTS
Expand Down
6 changes: 5 additions & 1 deletion trunk/arch/blackfin/include/asm/time.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,9 @@ extern unsigned long long __bfin_cycles_off;
extern unsigned int __bfin_cycles_mod;
#endif

extern void __init setup_core_timer(void);
#if defined(CONFIG_TICKSOURCE_CORETMR)
extern void bfin_coretmr_init(void);
extern void bfin_coretmr_clockevent_init(void);
#endif

#endif
197 changes: 105 additions & 92 deletions trunk/arch/blackfin/kernel/time-ts.c
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,6 @@ static int __init bfin_cs_gptimer0_init(void)
# define bfin_cs_gptimer0_init()
#endif


#if defined(CONFIG_GPTMR0_CLOCKSOURCE) || defined(CONFIG_CYCLES_CLOCKSOURCE)
/* prefer to use cycles since it has higher rating */
notrace unsigned long long sched_clock(void)
Expand All @@ -145,47 +144,8 @@ notrace unsigned long long sched_clock(void)
}
#endif

#ifdef CONFIG_CORE_TIMER_IRQ_L1
__attribute__((l1_text))
#endif
irqreturn_t timer_interrupt(int irq, void *dev_id);

static int bfin_timer_set_next_event(unsigned long, \
struct clock_event_device *);

static void bfin_timer_set_mode(enum clock_event_mode, \
struct clock_event_device *);

static struct clock_event_device clockevent_bfin = {
#if defined(CONFIG_TICKSOURCE_GPTMR0)
.name = "bfin_gptimer0",
.rating = 300,
.irq = IRQ_TIMER0,
#else
.name = "bfin_core_timer",
.rating = 350,
.irq = IRQ_CORETMR,
#endif
.shift = 32,
.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
.set_next_event = bfin_timer_set_next_event,
.set_mode = bfin_timer_set_mode,
};

static struct irqaction bfin_timer_irq = {
#if defined(CONFIG_TICKSOURCE_GPTMR0)
.name = "Blackfin GPTimer0",
#else
.name = "Blackfin CoreTimer",
#endif
.flags = IRQF_DISABLED | IRQF_TIMER | \
IRQF_IRQPOLL | IRQF_PERCPU,
.handler = timer_interrupt,
.dev_id = &clockevent_bfin,
};

#if defined(CONFIG_TICKSOURCE_GPTMR0)
static int bfin_timer_set_next_event(unsigned long cycles,
static int bfin_gptmr0_set_next_event(unsigned long cycles,
struct clock_event_device *evt)
{
disable_gptimers(TIMER0bit);
Expand All @@ -196,7 +156,7 @@ static int bfin_timer_set_next_event(unsigned long cycles,
return 0;
}

static void bfin_timer_set_mode(enum clock_event_mode mode,
static void bfin_gptmr0_set_mode(enum clock_event_mode mode,
struct clock_event_device *evt)
{
switch (mode) {
Expand Down Expand Up @@ -224,25 +184,65 @@ static void bfin_timer_set_mode(enum clock_event_mode mode,
}
}

static void bfin_timer_ack(void)
static void bfin_gptmr0_ack(void)
{
set_gptimer_status(TIMER_GROUP1, TIMER_STATUS_TIMIL0);
}

static void __init bfin_timer_init(void)
static void __init bfin_gptmr0_init(void)
{
disable_gptimers(TIMER0bit);
}

static unsigned long __init bfin_clockevent_check(void)
#ifdef CONFIG_CORE_TIMER_IRQ_L1
__attribute__((l1_text))
#endif
irqreturn_t bfin_gptmr0_interrupt(int irq, void *dev_id)
{
setup_irq(IRQ_TIMER0, &bfin_timer_irq);
return get_sclk();
struct clock_event_device *evt = dev_id;
smp_mb();
evt->event_handler(evt);
bfin_gptmr0_ack();
return IRQ_HANDLED;
}

#else /* CONFIG_TICKSOURCE_CORETMR */
static struct irqaction gptmr0_irq = {
.name = "Blackfin GPTimer0",
.flags = IRQF_DISABLED | IRQF_TIMER | \
IRQF_IRQPOLL | IRQF_PERCPU,
.handler = bfin_gptmr0_interrupt,
};

static int bfin_timer_set_next_event(unsigned long cycles,
static struct clock_event_device clockevent_gptmr0 = {
.name = "bfin_gptimer0",
.rating = 300,
.irq = IRQ_TIMER0,
.shift = 32,
.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
.set_next_event = bfin_gptmr0_set_next_event,
.set_mode = bfin_gptmr0_set_mode,
};

static void __init bfin_gptmr0_clockevent_init(struct clock_event_device *evt)
{
unsigned long clock_tick;

clock_tick = get_sclk();
evt->mult = div_sc(clock_tick, NSEC_PER_SEC, evt->shift);
evt->max_delta_ns = clockevent_delta2ns(-1, evt);
evt->min_delta_ns = clockevent_delta2ns(100, evt);

evt->cpumask = cpumask_of(0);

clockevents_register_device(evt);
}
#endif /* CONFIG_TICKSOURCE_GPTMR0 */

#if defined(CONFIG_TICKSOURCE_CORETMR)
/* per-cpu local core timer */
static DEFINE_PER_CPU(struct clock_event_device, coretmr_events);

static int bfin_coretmr_set_next_event(unsigned long cycles,
struct clock_event_device *evt)
{
bfin_write_TCNTL(TMPWR);
Expand All @@ -253,7 +253,7 @@ static int bfin_timer_set_next_event(unsigned long cycles,
return 0;
}

static void bfin_timer_set_mode(enum clock_event_mode mode,
static void bfin_coretmr_set_mode(enum clock_event_mode mode,
struct clock_event_device *evt)
{
switch (mode) {
Expand Down Expand Up @@ -285,68 +285,65 @@ static void bfin_timer_set_mode(enum clock_event_mode mode,
}
}

static void bfin_timer_ack(void)
{
}

static void __init bfin_timer_init(void)
void bfin_coretmr_init(void)
{
/* power up the timer, but don't enable it just yet */
bfin_write_TCNTL(TMPWR);
CSYNC();

/*
* the TSCALE prescaler counter.
*/
/* the TSCALE prescaler counter. */
bfin_write_TSCALE(TIME_SCALE - 1);
bfin_write_TPERIOD(0);
bfin_write_TCOUNT(0);

CSYNC();
}

static unsigned long __init bfin_clockevent_check(void)
{
setup_irq(IRQ_CORETMR, &bfin_timer_irq);
return get_cclk() / TIME_SCALE;
}

void __init setup_core_timer(void)
#ifdef CONFIG_CORE_TIMER_IRQ_L1
__attribute__((l1_text))
#endif
irqreturn_t bfin_coretmr_interrupt(int irq, void *dev_id)
{
bfin_timer_init();
bfin_timer_set_mode(CLOCK_EVT_MODE_PERIODIC, NULL);
}
#endif /* CONFIG_TICKSOURCE_GPTMR0 */
int cpu = smp_processor_id();
struct clock_event_device *evt = &per_cpu(coretmr_events, cpu);

/*
* timer_interrupt() needs to keep up the real-time clock,
* as well as call the "do_timer()" routine every clocktick
*/
irqreturn_t timer_interrupt(int irq, void *dev_id)
{
struct clock_event_device *evt = dev_id;
smp_mb();
evt->event_handler(evt);
bfin_timer_ack();
return IRQ_HANDLED;
}

static int __init bfin_clockevent_init(void)
{
unsigned long timer_clk;

timer_clk = bfin_clockevent_check();

bfin_timer_init();

clockevent_bfin.mult = div_sc(timer_clk, NSEC_PER_SEC, clockevent_bfin.shift);
clockevent_bfin.max_delta_ns = clockevent_delta2ns(-1, &clockevent_bfin);
clockevent_bfin.min_delta_ns = clockevent_delta2ns(100, &clockevent_bfin);
clockevent_bfin.cpumask = cpumask_of(0);
clockevents_register_device(&clockevent_bfin);
static struct irqaction coretmr_irq = {
.name = "Blackfin CoreTimer",
.flags = IRQF_DISABLED | IRQF_TIMER | \
IRQF_IRQPOLL | IRQF_PERCPU,
.handler = bfin_coretmr_interrupt,
};

return 0;
void bfin_coretmr_clockevent_init(void)
{
unsigned long clock_tick;
unsigned int cpu = smp_processor_id();
struct clock_event_device *evt = &per_cpu(coretmr_events, cpu);

evt->name = "bfin_core_timer";
evt->rating = 350;
evt->irq = -1;
evt->shift = 32;
evt->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
evt->set_next_event = bfin_coretmr_set_next_event;
evt->set_mode = bfin_coretmr_set_mode;

clock_tick = get_cclk() / TIME_SCALE;
evt->mult = div_sc(clock_tick, NSEC_PER_SEC, evt->shift);
evt->max_delta_ns = clockevent_delta2ns(-1, evt);
evt->min_delta_ns = clockevent_delta2ns(100, evt);

evt->cpumask = cpumask_of(cpu);

clockevents_register_device(evt);
}
#endif /* CONFIG_TICKSOURCE_CORETMR */


void __init time_init(void)
{
Expand All @@ -370,5 +367,21 @@ void __init time_init(void)

bfin_cs_cycles_init();
bfin_cs_gptimer0_init();
bfin_clockevent_init();

#if defined(CONFIG_TICKSOURCE_CORETMR)
bfin_coretmr_init();
setup_irq(IRQ_CORETMR, &coretmr_irq);
bfin_coretmr_clockevent_init();
#endif

#if defined(CONFIG_TICKSOURCE_GPTMR0)
bfin_gptmr0_init();
setup_irq(IRQ_TIMER0, &gptmr0_irq);
gptmr0_irq.dev_id = &clockevent_gptmr0;
bfin_gptmr0_clockevent_init(&clockevent_gptmr0);
#endif

#if !defined(CONFIG_TICKSOURCE_CORETMR) && !defined(CONFIG_TICKSOURCE_GPTMR0)
# error at least one clock event device is required
#endif
}
2 changes: 2 additions & 0 deletions trunk/arch/blackfin/mach-bf561/include/mach/smp.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,6 @@ void platform_send_ipi_cpu(unsigned int cpu);

void platform_clear_ipi(unsigned int cpu);

void bfin_local_timer_setup(void);

#endif /* !_MACH_BF561_SMP */
18 changes: 18 additions & 0 deletions trunk/arch/blackfin/mach-bf561/smp.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <linux/delay.h>
#include <asm/smp.h>
#include <asm/dma.h>
#include <asm/time.h>

static DEFINE_SPINLOCK(boot_lock);

Expand Down Expand Up @@ -144,3 +145,20 @@ void platform_clear_ipi(unsigned int cpu)
bfin_write_SICB_SYSCR(bfin_read_SICB_SYSCR() | (1 << (10 + cpu)));
SSYNC();
}

/*
* Setup core B's local core timer.
* In SMP, core timer is used for clock event device.
*/
void __cpuinit bfin_local_timer_setup(void)
{
#if defined(CONFIG_TICKSOURCE_CORETMR)
bfin_coretmr_init();
bfin_coretmr_clockevent_init();
get_irq_chip(IRQ_CORETMR)->unmask(IRQ_CORETMR);
#else
/* Power down the core timer, just to play safe. */
bfin_write_TCNTL(0);
#endif

}
3 changes: 0 additions & 3 deletions trunk/arch/blackfin/mach-common/ints-priority.c
Original file line number Diff line number Diff line change
Expand Up @@ -1073,9 +1073,6 @@ int __init init_arch_irq(void)
#endif

#ifdef CONFIG_SMP
#ifdef CONFIG_TICKSOURCE_GPTMR0
case IRQ_TIMER0:
#endif
#ifdef CONFIG_TICKSOURCE_CORETMR
case IRQ_CORETMR:
#endif
Expand Down
Loading

0 comments on commit 4f3143c

Please sign in to comment.