Skip to content

Commit

Permalink
microblaze: Support timer on AXI lite
Browse files Browse the repository at this point in the history
New microblaze systems uses two buses. One for memories
and flashes and the second for low-speed peripherals
which can run on different CLK. This is the reason
why the kernel is trying to read clock-frequency
directly from node. If there is then the kernel will
work with it. If not then cpu CLK is used.

Signed-off-by: Michal Simek <monstr@monstr.eu>
  • Loading branch information
Michal Simek committed Oct 21, 2010
1 parent 02b0804 commit ccea0e6
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 6 deletions.
1 change: 0 additions & 1 deletion arch/microblaze/include/asm/cpuinfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,6 @@ struct cpuinfo {
u32 num_rd_brk;
u32 num_wr_brk;
u32 cpu_clock_freq; /* store real freq of cpu */
u32 freq_div_hz; /* store freq/HZ */

/* FPGA family */
u32 fpga_family_code;
Expand Down
21 changes: 16 additions & 5 deletions arch/microblaze/kernel/timer.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ static unsigned int timer_baseaddr;
#define TIMER_BASE timer_baseaddr
#endif

unsigned int freq_div_hz;
unsigned int timer_clock_freq;

#define TCSR0 (0x00)
#define TLR0 (0x04)
#define TCR0 (0x08)
Expand Down Expand Up @@ -115,7 +118,7 @@ static void microblaze_timer_set_mode(enum clock_event_mode mode,
switch (mode) {
case CLOCK_EVT_MODE_PERIODIC:
printk(KERN_INFO "%s: periodic\n", __func__);
microblaze_timer0_start_periodic(cpuinfo.freq_div_hz);
microblaze_timer0_start_periodic(freq_div_hz);
break;
case CLOCK_EVT_MODE_ONESHOT:
printk(KERN_INFO "%s: oneshot\n", __func__);
Expand Down Expand Up @@ -168,7 +171,7 @@ static struct irqaction timer_irqaction = {
static __init void microblaze_clockevent_init(void)
{
clockevent_microblaze_timer.mult =
div_sc(cpuinfo.cpu_clock_freq, NSEC_PER_SEC,
div_sc(timer_clock_freq, NSEC_PER_SEC,
clockevent_microblaze_timer.shift);
clockevent_microblaze_timer.max_delta_ns =
clockevent_delta2ns((u32)~0, &clockevent_microblaze_timer);
Expand Down Expand Up @@ -201,7 +204,7 @@ static struct cyclecounter microblaze_cc = {

int __init init_microblaze_timecounter(void)
{
microblaze_cc.mult = div_sc(cpuinfo.cpu_clock_freq, NSEC_PER_SEC,
microblaze_cc.mult = div_sc(timer_clock_freq, NSEC_PER_SEC,
microblaze_cc.shift);

timecounter_init(&microblaze_tc, &microblaze_cc, sched_clock());
Expand All @@ -221,7 +224,7 @@ static struct clocksource clocksource_microblaze = {
static int __init microblaze_clocksource_init(void)
{
clocksource_microblaze.mult =
clocksource_hz2mult(cpuinfo.cpu_clock_freq,
clocksource_hz2mult(timer_clock_freq,
clocksource_microblaze.shift);
if (clocksource_register(&clocksource_microblaze))
panic("failed to register clocksource");
Expand All @@ -247,6 +250,7 @@ void __init time_init(void)
u32 irq, i = 0;
u32 timer_num = 1;
struct device_node *timer = NULL;
const void *prop;
#ifdef CONFIG_SELFMOD_TIMER
unsigned int timer_baseaddr = 0;
int arr_func[] = {
Expand Down Expand Up @@ -286,7 +290,14 @@ void __init time_init(void)
printk(KERN_INFO "%s #0 at 0x%08x, irq=%d\n",
timer_list[i], timer_baseaddr, irq);

cpuinfo.freq_div_hz = cpuinfo.cpu_clock_freq / HZ;
/* If there is clock-frequency property than use it */
prop = of_get_property(timer, "clock-frequency", NULL);
if (prop)
timer_clock_freq = be32_to_cpup(prop);
else
timer_clock_freq = cpuinfo.cpu_clock_freq;

freq_div_hz = timer_clock_freq / HZ;

setup_irq(irq, &timer_irqaction);
#ifdef CONFIG_HEART_BEAT
Expand Down

0 comments on commit ccea0e6

Please sign in to comment.