[platform][zynq] more zynq tweaks

-Make sure all peripheral irqs are routed to cpu 0
-Implement cortex-a9's private timer
This commit is contained in:
Travis Geiselbrecht
2014-04-20 22:12:32 -07:00
parent 8b03bacc79
commit 72e00b9b01
3 changed files with 111 additions and 37 deletions

View File

@@ -59,18 +59,10 @@
#define GIC_DISTRIB_BASE (CPUPRIV_BASE + 0x1000)
#define L2CACHE_BASE (CPUPRIV_BASE + 0x2000)
#if 0
#define TIMER0 (0x10011000)
#define TIMER1 (0x10011020)
#define TIMER2 (0x10012000)
#define TIMER3 (0x10012020)
#define TIMER4 (0x10018000)
#define TIMER5 (0x10018020)
#define TIMER6 (0x10019000)
#define TIMER7 (0x10019020)
#endif
/* interrupts */
#define CPU_GLOB_TIMER 27 // cortex-a9 specific timers
#define CPU_PRIV_TIMER 29
#define CPU_WATCHDOG 30
#define TTC0_A_INT 42
#define TTC0_B_INT 43
#define TTC0_C_INT 44

View File

@@ -123,36 +123,12 @@ void platform_init_interrupts(void)
}
for (int i = 32/4; i < MAX_INT / 4; i++) {
GICDISTREG(_TARGET + i * 4) = 0;
GICDISTREG(_TARGET + i * 4) = 0x01010101; // assign all irqs to cpu 0
GICDISTREG(PRIORITY + i * 4) = 0x80808080;
}
GICDISTREG(DISTCONTROL) = 1; // enable GIC0, IRQ only
GICCPUREG(CONTROL) = (0<<3)|(0<<2)||1; // enable GIC0, IRQ only, group 0 set to IRQ
#if 0
hexdump((void *)GIC_PROC_BASE, 0x20);
hexdump((void *)GIC_DISTRIB_BASE, 0x10);
printf("config: "); hexdump((void *)GIC_DISTRIB_BASE + CONFIG, 0x10);
printf("group: "); hexdump((void *)GIC_DISTRIB_BASE + GROUP, 0x10);
printf("priority: "); hexdump((void *)GIC_DISTRIB_BASE + PRIORITY, 0x40);
printf("enable: "); hexdump((void *)GIC_DISTRIB_BASE + SETENABLE, 0x10);
printf("pending: "); hexdump((void *)GIC_DISTRIB_BASE + SETPEND, 0x10);
printf("active: "); hexdump((void *)GIC_DISTRIB_BASE + SETACTIVE, 0x10);
// trigger interrupt
gic_set_enable(34, true);
//GICDISTREG(SETPEND + 4) = (1<<2);
//GICDISTREG(SETACTIVE + 4) = (1<<2);
GICDISTREG(SGIR) = (2 << 24) | 1;
printf("ISR 0x%x\n", (uint32_t)ARM64_READ_SYSREG(isr_el1));
printf("daif 0x%x\n", (uint32_t)ARM64_READ_SYSREG(daif));
arch_enable_interrupts();
printf("daif 0x%x\n", (uint32_t)ARM64_READ_SYSREG(daif));
#endif
}
status_t mask_interrupt(unsigned int vector)

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2008-2012 Travis Geiselbrecht
* Copyright (c) 2014 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
@@ -33,6 +33,111 @@
#include <platform/zynq.h>
#include "platform_p.h"
/* driver for cortex-a9's private timer */
#define LOCAL_TRACE 1
#define TIMREG(reg) (*REG32(PRIV_TIMER_BASE + (reg)))
#define TIMER_LOAD (0x00)
#define TIMER_COUNTER (0x04)
#define TIMER_CONTROL (0x08)
#define TIMER_ISR (0x0c)
#define GTIMREG(reg) (*REG32(GLOBAL_TIMER_BASE + (reg)))
#define GTIMER_COUNT_LO (0x00)
#define GTIMER_COUNT_HI (0x04)
#define GTIMER_CONTROL (0x08)
#define GTIMER_ISR (0x0c)
#define GTIMER_COMPARE_LO (0x10)
#define GTIMER_COMPARE_HI (0x14)
#define GTIMER_INCREMENT (0x18)
// XXX pull from someplace better
#define TIMER_INPUT_CLOCK (325000000)
static platform_timer_callback t_callback;
static volatile uint ticks = 0;
static lk_time_t periodic_interval;
uint64_t get_global_val(void)
{
uint32_t lo, hi;
retry:
hi = GTIMREG(GTIMER_COUNT_HI);
lo = GTIMREG(GTIMER_COUNT_LO);
if (GTIMREG(GTIMER_COUNT_HI) != hi)
goto retry;
return ((uint64_t)hi << 32 | lo);
}
status_t platform_set_periodic_timer(platform_timer_callback callback, void *arg, lk_time_t interval)
{
enter_critical_section();
LTRACEF("callback %p, arg %p, interval %lu\n", callback, arg, interval);
t_callback = callback;
periodic_interval = interval;
// disable timer
TIMREG(TIMER_CONTROL) = 0;
TIMREG(TIMER_LOAD) = (((uint64_t)TIMER_INPUT_CLOCK * interval) / 1000);
TIMREG(TIMER_CONTROL) = (1<<2) | (1<<1) | (1<<0); // irq enable, autoreload, enable
unmask_interrupt(CPU_PRIV_TIMER);
exit_critical_section();
return NO_ERROR;
}
lk_bigtime_t current_time_hires(void)
{
lk_bigtime_t time;
time = ticks * periodic_interval * 1000ULL;
return time;
}
lk_time_t current_time(void)
{
lk_time_t time;
time = ticks * periodic_interval;
return time;
}
static enum handler_return platform_tick(void *arg)
{
ticks++;
TIMREG(TIMER_ISR) = 1; // ack the irq
if (t_callback) {
return t_callback(arg, current_time());
} else {
return INT_NO_RESCHEDULE;
}
}
void platform_init_timer(void)
{
/* disable timer */
TIMREG(TIMER_CONTROL) = 0;
register_int_handler(CPU_PRIV_TIMER, &platform_tick, NULL);
}
#if 0
/* driver for Cadence triple timer counter (TTC) */
#define LOCAL_TRACE 0
@@ -126,5 +231,6 @@ void platform_init_timer(void)
register_int_handler(TTC0_B_INT, &platform_tick, NULL);
register_int_handler(TTC0_C_INT, &platform_tick, NULL);
}
#endif
/* vim: set ts=4 sw=4 expandtab: */