[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:
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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: */
|
||||
|
||||
Reference in New Issue
Block a user