From: Anthony PERARD Date: Tue, 22 Jan 2013 16:29:49 +0000 (+0000) Subject: arm: exynos5,arndale: start generic timer. X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=85dae0e4c3f00a0495a99f6907df078d22951727;p=people%2Faperard%2Fxen-arm.git arm: exynos5,arndale: start generic timer. --- diff --git a/xen/arch/arm/arm32/mode_switch.S b/xen/arch/arm/arm32/mode_switch.S index 8add8c0116..3af68f76f9 100644 --- a/xen/arch/arm/arm32/mode_switch.S +++ b/xen/arch/arm/arm32/mode_switch.S @@ -72,7 +72,7 @@ enter_hyp_mode: * programmable in Secure state. Since we don't know where its * memory-mapped control registers live, we can't find out the * right frequency. Use the VE model's default frequency here. */ - ldr r0, =0x5f5e100 /* 100 MHz */ + ldr r0, =(24*1000*1000) /* 24 MHz for arndale */ mcr CP32(r0, CNTFRQ) ldr r0, =0x40c00 /* SMP, c11, c10 in non-secure mode */ mcr CP32(r0, NSACR) diff --git a/xen/arch/arm/time.c b/xen/arch/arm/time.c index 07628e1bc3..f6c381b1a2 100644 --- a/xen/arch/arm/time.c +++ b/xen/arch/arm/time.c @@ -38,7 +38,46 @@ * instead. */ #define USE_HYP_TIMER 1 +#define IRQ_SPI(x) (x) +#define EXYNOS5_IRQ_MCT_L0 IRQ_SPI(120) +#define EXYNOS5_IRQ_MCT_L1 IRQ_SPI(121) +#define MCT_BASE 0x101c0000 +#define EXYNOS4_MCTREG(x) (MCT_BASE + (x)) + +#define EXYNOS4_MCT_G_CNT_L EXYNOS4_MCTREG(0x100) +#define EXYNOS4_MCT_G_CNT_U EXYNOS4_MCTREG(0x104) +#define EXYNOS4_MCT_G_CNT_WSTAT EXYNOS4_MCTREG(0x110) + +#define EXYNOS4_MCT_G_COMP0_L EXYNOS4_MCTREG(0x200) +#define EXYNOS4_MCT_G_COMP0_U EXYNOS4_MCTREG(0x204) +#define EXYNOS4_MCT_G_COMP0_ADD_INCR EXYNOS4_MCTREG(0x208) + +#define EXYNOS4_MCT_G_TCON EXYNOS4_MCTREG(0x240) + +#define EXYNOS4_MCT_G_INT_CSTAT EXYNOS4_MCTREG(0x244) +#define EXYNOS4_MCT_G_INT_ENB EXYNOS4_MCTREG(0x248) +#define EXYNOS4_MCT_G_WSTAT EXYNOS4_MCTREG(0x24C) + +#define _EXYNOS4_MCT_L_BASE EXYNOS4_MCTREG(0x300) + // cpu nb +#define EXYNOS4_MCT_L_BASE(x) (_EXYNOS4_MCT_L_BASE + (0x100 * x)) +#define EXYNOS4_MCT_L_MASK (0xffffff00) + +#define MCT_L_TCNTB_OFFSET (0x00) +#define MCT_L_ICNTB_OFFSET (0x08) +#define MCT_L_TCON_OFFSET (0x20) +#define MCT_L_INT_CSTAT_OFFSET (0x30) +#define MCT_L_INT_ENB_OFFSET (0x34) +#define MCT_L_WSTAT_OFFSET (0x40) + +#define MCT_G_TCON_START (1 << 8) +#define MCT_G_TCON_COMP0_AUTO_INC (1 << 1) +#define MCT_G_TCON_COMP0_ENABLE (1 << 0) + +#define MCT_L_TCON_INTERVAL_MODE (1 << 2) +#define MCT_L_TCON_INT_START (1 << 1) +#define MCT_L_TCON_TIMER_START (1 << 0) uint64_t __read_mostly boot_count; /* For fine-grained timekeeping, we use the ARM "Generic Timer", a @@ -86,13 +125,41 @@ static uint32_t calibrate_timer(void) } */ +uint32_t read_register(uint32_t addr) +{ + volatile const uint32_t *reg; + uint32_t value; + set_fixmap(FIXMAP_MISC, addr >> PAGE_SHIFT, DEV_SHARED); + reg = (uint32_t *)(FIXMAP_ADDR(FIXMAP_MISC) + (addr & ~PAGE_MASK)); + value = *reg; + clear_fixmap(FIXMAP_MISC); + return value; +} + +void write_register(uint32_t addr, uint32_t value) +{ + volatile uint32_t *reg; + set_fixmap(FIXMAP_MISC, addr >> PAGE_SHIFT, DEV_SHARED); + reg = (uint32_t *)(FIXMAP_ADDR(FIXMAP_MISC) + (addr & ~PAGE_MASK)); + *reg = value; + clear_fixmap(FIXMAP_MISC); +} + /* Set up the timer on the boot CPU */ int __init init_xen_time(void) { + uint32_t reg; + /* Check that this CPU supports the Generic Timer interface */ if ( (READ_CP32(ID_PFR1) & ID_PFR1_GT_MASK) != ID_PFR1_GT_v1 ) panic("CPU does not support the Generic Timer v1 interface.\n"); + // enable timer on exynos5 arndale board + // should probably be done by u-boot + reg = read_register(EXYNOS4_MCT_G_TCON); + write_register(EXYNOS4_MCT_G_TCON, reg | MCT_G_TCON_START); + + cntfrq = READ_CP32(CNTFRQ); boot_count = READ_CP64(CNTPCT); printk("Using generic timer at %"PRIu32" Hz\n", cntfrq);