From 047410f8e201cf332babbac4ec10a26180d0b59e Mon Sep 17 00:00:00 2001 From: Siva Durga Prasad Paladugu Date: Tue, 8 Jul 2014 15:31:01 +0530 Subject: [PATCH] zynqmp: Changes to bring up on ep108 A53 RTL 3.1 Changes to bring up on ep108 A53. ARM global timer is not working that's why TTC timer is used instead. Fixing GIC address and GIC version to fit RTL 3.1. Signed-off-by: Siva Durga Prasad Paladugu Signed-off-by: Michal Simek --- arch/arm/cpu/armv8/generic_timer.c | 2 + arch/arm/cpu/armv8/zynqmp/Makefile | 1 + arch/arm/cpu/armv8/zynqmp/clk.c | 5 + arch/arm/cpu/armv8/zynqmp/timer.c | 156 ++++++++++++++++++++ arch/arm/include/asm/arch-zynqmp/clk.h | 1 + arch/arm/include/asm/arch-zynqmp/hardware.h | 2 + board/xilinx/zynqmp/zynqmp.c | 5 - 7 files changed, 167 insertions(+), 5 deletions(-) create mode 100644 arch/arm/cpu/armv8/zynqmp/timer.c diff --git a/arch/arm/cpu/armv8/generic_timer.c b/arch/arm/cpu/armv8/generic_timer.c index 223b95e210e..f0994693f36 100644 --- a/arch/arm/cpu/armv8/generic_timer.c +++ b/arch/arm/cpu/armv8/generic_timer.c @@ -9,6 +9,7 @@ #include #include +#ifndef XILINX_ZYNQMP /* * Generic timer implementation of get_tbclk() */ @@ -18,6 +19,7 @@ unsigned long get_tbclk(void) asm volatile("mrs %0, cntfrq_el0" : "=r" (cntfrq)); return cntfrq; } +#endif /* * Generic timer implementation of timer_read_counter() diff --git a/arch/arm/cpu/armv8/zynqmp/Makefile b/arch/arm/cpu/armv8/zynqmp/Makefile index 831d0256a4a..2db71f1e25a 100644 --- a/arch/arm/cpu/armv8/zynqmp/Makefile +++ b/arch/arm/cpu/armv8/zynqmp/Makefile @@ -6,3 +6,4 @@ # obj-y += clk.o +obj-y += timer.o diff --git a/arch/arm/cpu/armv8/zynqmp/clk.c b/arch/arm/cpu/armv8/zynqmp/clk.c index 41fb60e9ba7..fef7cb7a8f1 100644 --- a/arch/arm/cpu/armv8/zynqmp/clk.c +++ b/arch/arm/cpu/armv8/zynqmp/clk.c @@ -9,3 +9,8 @@ unsigned long get_uart_clk(int dev_id) { return 25000000; } + +unsigned long get_ttc_clk(int dev_id) +{ + return 25000000; +} diff --git a/arch/arm/cpu/armv8/zynqmp/timer.c b/arch/arm/cpu/armv8/zynqmp/timer.c new file mode 100644 index 00000000000..a51e11f981f --- /dev/null +++ b/arch/arm/cpu/armv8/zynqmp/timer.c @@ -0,0 +1,156 @@ +/* + * Copyright (C) 2012 Michal Simek + * Copyright (C) 2011-2012 Xilinx, Inc. All rights reserved. + * + * (C) Copyright 2008 + * Guennadi Liakhovetki, DENX Software Engineering, + * + * (C) Copyright 2004 + * Philippe Robin, ARM Ltd. + * + * (C) Copyright 2002-2004 + * Gary Jennejohn, DENX Software Engineering, + * + * (C) Copyright 2003 + * Texas Instruments + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH + * Marius Groeger + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH + * Alex Zuepke + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +struct ttc0_timer { + u32 clkctrl; /* Timer Load Register */ + u32 reserved0[2]; + u32 cntctrl; /* Timer Counter Register */ + u32 reserved1[2]; + u32 counter; /* Timer Control Register */ +}; + +static struct ttc0_timer *timer_base = + (struct ttc0_timer *)ZYNQ_TTC_BASEADDR0; + +#define TIMER_LOAD_VAL 0xFFFFFFFF + +#define PRESCALE_EXPONENT 11 /* 2 ^ PRESCALE_EXPONENT = PRESCALE */ +#define PRESCALE 2048 /* The exponent must match this */ +#define CLK_CNTRL_PRESCALE ((PRESCALE_EXPONENT - 1) << 1) +#define CLK_CNTRL_PRESCALE_EN 1 +#define CNT_CNTRL_RESET (1 << 4) + +int timer_init(void) +{ + gd->arch.timer_rate_hz = get_ttc_clk(0) / PRESCALE; + + writel(CLK_CNTRL_PRESCALE | CLK_CNTRL_PRESCALE_EN, + &timer_base->clkctrl); + writel(CNT_CNTRL_RESET, &timer_base->cntctrl); + + /* Reset time */ + gd->arch.lastinc = readl(&timer_base->counter) / + (gd->arch.timer_rate_hz / CONFIG_SYS_HZ); + gd->arch.tbl = 0; + + return 0; +} + +/* + * This function is derived from PowerPC code (read timebase as long long). + * On ARM it just returns the timer value. + */ +ulong get_timer_masked(void) +{ + ulong now; + + now = readl(&timer_base->counter) / + (gd->arch.timer_rate_hz / CONFIG_SYS_HZ); + + if (gd->arch.lastinc <= now) { + /* Normal mode */ + gd->arch.tbl += now - gd->arch.lastinc; + } else { + /* We have an overflow ... */ + gd->arch.tbl += now + TIMER_LOAD_VAL - gd->arch.lastinc + 1; + } + gd->arch.lastinc = now; + + return gd->arch.tbl; +} +void __udelay(unsigned long usec) +{ + u32 countticks; + u32 timeend; + u32 timediff; + u32 timenow; + + if (usec == 0) + return; + + countticks = lldiv(((unsigned long long)gd->arch.timer_rate_hz * usec), + 1000000); + + /* decrementing timer */ + timeend = readl(&timer_base->counter) + countticks; + +#if TIMER_LOAD_VAL != 0xFFFFFFFF + /* do not manage multiple overflow */ + if (countticks >= TIMER_LOAD_VAL) + countticks = TIMER_LOAD_VAL - 1; +#endif + + do { + timenow = readl(&timer_base->counter); + + if (timenow <= timeend) { + /* normal case */ + timediff = timeend - timenow; + } else { + if ((TIMER_LOAD_VAL - timenow + timeend) <= + countticks) { + /* overflow */ + timediff = TIMER_LOAD_VAL - timenow + timeend; + } else { + /* missed the exact match */ + break; + } + } + } while (timediff > 0); +} + +/* Timer without interrupts */ +ulong get_timer(ulong base) +{ + return get_timer_masked() - base; +} + +/* + * This function is derived from PowerPC code (read timebase as long long). + * On ARM it just returns the timer value. + */ +unsigned long long get_ticks(void) +{ + return get_timer(0); +} + +/* + * This function is derived from PowerPC code (timebase clock frequency). + * On ARM it returns the number of timer ticks per second. + */ +ulong get_tbclk(void) +{ + return CONFIG_SYS_HZ; +} diff --git a/arch/arm/include/asm/arch-zynqmp/clk.h b/arch/arm/include/asm/arch-zynqmp/clk.h index 9f18ea9be0b..9b5c6ef7beb 100644 --- a/arch/arm/include/asm/arch-zynqmp/clk.h +++ b/arch/arm/include/asm/arch-zynqmp/clk.h @@ -9,5 +9,6 @@ #define _ASM_ARCH_CLK_H_ unsigned long get_uart_clk(int dev_id); +unsigned long get_ttc_clk(int dev_id); #endif /* _ASM_ARCH_CLK_H_ */ diff --git a/arch/arm/include/asm/arch-zynqmp/hardware.h b/arch/arm/include/asm/arch-zynqmp/hardware.h index f6ede5b050d..f1c16a0092d 100644 --- a/arch/arm/include/asm/arch-zynqmp/hardware.h +++ b/arch/arm/include/asm/arch-zynqmp/hardware.h @@ -16,6 +16,8 @@ #define ZYNQ_GEM_BASEADDR2 0xFF00B000 #define ZYNQ_GEM_BASEADDR3 0xFF00C000 +#define ZYNQ_TTC_BASEADDR0 0xFF00F000 + #define ZYNQ_QSPI_BASEADDR 0xFF00D000 #define ZYNQ_SDHCI_BASEADDR0 0xFF014000 diff --git a/board/xilinx/zynqmp/zynqmp.c b/board/xilinx/zynqmp/zynqmp.c index d477402753f..5120160c70e 100644 --- a/board/xilinx/zynqmp/zynqmp.c +++ b/board/xilinx/zynqmp/zynqmp.c @@ -25,11 +25,6 @@ int dram_init(void) return 0; } -int timer_init(void) -{ - return 0; -} - void reset_cpu(ulong addr) { } -- 2.47.3