Commit e141aa03 authored by danh-arm's avatar danh-arm
Browse files

Merge pull request #625 from antonio-nino-diaz-arm/an/delay-timer-v2

Implement generic delay timer and use it on platforms
parents d1d71653 6704f425
...@@ -44,7 +44,7 @@ ...@@ -44,7 +44,7 @@
void bl31_arch_setup(void) void bl31_arch_setup(void)
{ {
/* Program the counter frequency */ /* Program the counter frequency */
write_cntfrq_el0(plat_get_syscnt_freq()); write_cntfrq_el0(plat_get_syscnt_freq2());
/* Initialize the cpu_ops pointer. */ /* Initialize the cpu_ops pointer. */
init_cpu_ops(); init_cpu_ops();
......
...@@ -1529,10 +1529,10 @@ state. This function must return a pointer to the `entry_point_info` structure ...@@ -1529,10 +1529,10 @@ state. This function must return a pointer to the `entry_point_info` structure
(that was copied during `bl31_early_platform_setup()`) if the image exists. It (that was copied during `bl31_early_platform_setup()`) if the image exists. It
should return NULL otherwise. should return NULL otherwise.
### Function : plat_get_syscnt_freq() [mandatory] ### Function : plat_get_syscnt_freq2() [mandatory]
Argument : void Argument : void
Return : uint64_t Return : unsigned int
This function is used by the architecture setup code to retrieve the counter This function is used by the architecture setup code to retrieve the counter
frequency for the CPU's generic timer. This value will be programmed into the frequency for the CPU's generic timer. This value will be programmed into the
......
...@@ -492,6 +492,9 @@ map is explained in the [Firmware Design]. ...@@ -492,6 +492,9 @@ map is explained in the [Firmware Design].
Trusted Firmware is configured for dual cluster topology and this option Trusted Firmware is configured for dual cluster topology and this option
can be used to override the default value. can be used to override the default value.
* `FVP_USE_SP804_TIMER` : Use the SP804 timer instead of the Generic Timer
for functions that wait for an arbitrary time length (udelay and mdelay).
The default value is 0.
### Debugging options ### Debugging options
......
...@@ -48,19 +48,22 @@ void udelay(uint32_t usec) ...@@ -48,19 +48,22 @@ void udelay(uint32_t usec)
(ops->clk_div != 0) && (ops->clk_div != 0) &&
(ops->get_timer_value != 0)); (ops->get_timer_value != 0));
uint32_t start, cnt, delta, delta_us; uint32_t start, delta, total_delta;
assert(usec < UINT32_MAX / ops->clk_div);
/* counter is decreasing */
start = ops->get_timer_value(); start = ops->get_timer_value();
total_delta = (usec * ops->clk_div) / ops->clk_mult;
do { do {
cnt = ops->get_timer_value(); /*
if (cnt > start) { * If the timer value wraps around, the subtraction will
delta = UINT32_MAX - cnt; * overflow and it will still give the correct result.
delta += start; */
} else delta = start - ops->get_timer_value(); /* Decreasing counter */
delta = start - cnt;
delta_us = (delta * ops->clk_mult) / ops->clk_div; } while (delta < total_delta);
} while (delta_us < usec);
} }
/*********************************************************** /***********************************************************
......
/* /*
* Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
...@@ -27,25 +27,56 @@ ...@@ -27,25 +27,56 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <arch_helpers.h> #include <arch_helpers.h>
#include <assert.h>
#include <bl_common.h>
#include <debug.h>
#include <delay_timer.h> #include <delay_timer.h>
#include <mt8173_def.h> #include <platform.h>
/* Ticks elapsed in one second by a signal of 1 MHz */
#define MHZ_TICKS_PER_SEC 1000000
static timer_ops_t ops;
static uint32_t plat_get_timer_value(void) static uint32_t get_timer_value(void)
{ {
/* Generic delay timer implementation expects the timer to be a down /*
* Generic delay timer implementation expects the timer to be a down
* counter. We apply bitwise NOT operator to the tick values returned * counter. We apply bitwise NOT operator to the tick values returned
* by read_cntpct_el0() to simulate the down counter. */ * by read_cntpct_el0() to simulate the down counter. The value is
* clipped from 64 to 32 bits.
*/
return (uint32_t)(~read_cntpct_el0()); return (uint32_t)(~read_cntpct_el0());
} }
static const timer_ops_t plat_timer_ops = { void generic_delay_timer_init_args(uint32_t mult, uint32_t div)
.get_timer_value = plat_get_timer_value, {
.clk_mult = 1, ops.get_timer_value = get_timer_value;
.clk_div = SYS_COUNTER_FREQ_IN_MHZ, ops.clk_mult = mult;
}; ops.clk_div = div;
timer_init(&ops);
void plat_delay_timer_init(void) VERBOSE("Generic delay timer configured with mult=%u and div=%u\n",
mult, div);
}
void generic_delay_timer_init(void)
{ {
timer_init(&plat_timer_ops); /* Value in ticks */
unsigned int mult = MHZ_TICKS_PER_SEC;
/* Value in ticks per second (Hz) */
unsigned int div = plat_get_syscnt_freq2();
/* Reduce multiplier and divider by dividing them repeatedly by 10 */
while ((mult % 10 == 0) && (div % 10 == 0)) {
mult /= 10;
div /= 10;
}
generic_delay_timer_init_args(mult, div);
} }
...@@ -28,27 +28,13 @@ ...@@ -28,27 +28,13 @@
* POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <arch_helpers.h> #ifndef __GENERIC_DELAY_TIMER_H__
#include <delay_timer.h> #define __GENERIC_DELAY_TIMER_H__
#include <platform_def.h>
static uint32_t plat_get_timer_value(void) #include <stdint.h>
{
/*
* Generic delay timer implementation expects the timer to be a down
* counter. We apply bitwise NOT operator to the tick values returned
* by read_cntpct_el0() to simulate the down counter.
*/
return (uint32_t)(~read_cntpct_el0());
}
static const timer_ops_t plat_timer_ops = { void generic_delay_timer_init_args(uint32_t mult, uint32_t div);
.get_timer_value = plat_get_timer_value,
.clk_mult = 1,
.clk_div = SYS_COUNTER_FREQ_IN_MHZ,
};
void plat_delay_timer_init(void) void generic_delay_timer_init(void);
{
timer_init(&plat_timer_ops); #endif /* __GENERIC_DELAY_TIMER_H__ */
}
...@@ -56,7 +56,9 @@ struct image_desc; ...@@ -56,7 +56,9 @@ struct image_desc;
/******************************************************************************* /*******************************************************************************
* Mandatory common functions * Mandatory common functions
******************************************************************************/ ******************************************************************************/
unsigned long long plat_get_syscnt_freq(void); unsigned long long plat_get_syscnt_freq(void) __deprecated;
unsigned int plat_get_syscnt_freq2(void);
int plat_get_image_source(unsigned int image_id, int plat_get_image_source(unsigned int image_id,
uintptr_t *dev_handle, uintptr_t *dev_handle,
uintptr_t *image_spec); uintptr_t *image_spec);
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
* POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <generic_delay_timer.h>
#include <mmio.h> #include <mmio.h>
#include <plat_arm.h> #include <plat_arm.h>
#include <sp804_delay_timer.h> #include <sp804_delay_timer.h>
...@@ -48,6 +49,7 @@ void bl2_platform_setup(void) ...@@ -48,6 +49,7 @@ void bl2_platform_setup(void)
{ {
arm_bl2_platform_setup(); arm_bl2_platform_setup();
#if FVP_USE_SP804_TIMER
/* Enable the clock override for SP804 timer 0, which means that no /* Enable the clock override for SP804 timer 0, which means that no
* clock dividers are applied and the raw (35 MHz) clock will be used */ * clock dividers are applied and the raw (35 MHz) clock will be used */
mmio_write_32(V2M_SP810_BASE, FVP_SP810_CTRL_TIM0_OV); mmio_write_32(V2M_SP810_BASE, FVP_SP810_CTRL_TIM0_OV);
...@@ -55,4 +57,7 @@ void bl2_platform_setup(void) ...@@ -55,4 +57,7 @@ void bl2_platform_setup(void)
/* Initialize delay timer driver using SP804 dual timer 0 */ /* Initialize delay timer driver using SP804 dual timer 0 */
sp804_timer_init(V2M_SP804_TIMER0_BASE, sp804_timer_init(V2M_SP804_TIMER0_BASE,
SP804_TIMER_CLKMULT, SP804_TIMER_CLKDIV); SP804_TIMER_CLKMULT, SP804_TIMER_CLKDIV);
#else
generic_delay_timer_init();
#endif /* FVP_USE_SP804_TIMER */
} }
...@@ -30,6 +30,11 @@ ...@@ -30,6 +30,11 @@
# Use the GICv3 driver on the FVP by default # Use the GICv3 driver on the FVP by default
FVP_USE_GIC_DRIVER := FVP_GICV3 FVP_USE_GIC_DRIVER := FVP_GICV3
# Use the SP804 timer instead of the generic one
FVP_USE_SP804_TIMER := 0
$(eval $(call assert_boolean,FVP_USE_SP804_TIMER))
$(eval $(call add_define,FVP_USE_SP804_TIMER))
# The FVP platform depends on this macro to build with correct GIC driver. # The FVP platform depends on this macro to build with correct GIC driver.
$(eval $(call add_define,FVP_USE_GIC_DRIVER)) $(eval $(call add_define,FVP_USE_GIC_DRIVER))
...@@ -92,8 +97,7 @@ BL1_SOURCES += drivers/io/io_semihosting.c \ ...@@ -92,8 +97,7 @@ BL1_SOURCES += drivers/io/io_semihosting.c \
${FVP_INTERCONNECT_SOURCES} ${FVP_INTERCONNECT_SOURCES}
BL2_SOURCES += drivers/arm/sp804/sp804_delay_timer.c \ BL2_SOURCES += drivers/io/io_semihosting.c \
drivers/io/io_semihosting.c \
drivers/delay_timer/delay_timer.c \ drivers/delay_timer/delay_timer.c \
lib/semihosting/semihosting.c \ lib/semihosting/semihosting.c \
lib/semihosting/aarch64/semihosting_call.S \ lib/semihosting/aarch64/semihosting_call.S \
...@@ -102,6 +106,12 @@ BL2_SOURCES += drivers/arm/sp804/sp804_delay_timer.c \ ...@@ -102,6 +106,12 @@ BL2_SOURCES += drivers/arm/sp804/sp804_delay_timer.c \
plat/arm/board/fvp/fvp_io_storage.c \ plat/arm/board/fvp/fvp_io_storage.c \
${FVP_SECURITY_SOURCES} ${FVP_SECURITY_SOURCES}
ifeq (${FVP_USE_SP804_TIMER},1)
BL2_SOURCES += drivers/arm/sp804/sp804_delay_timer.c
else
BL2_SOURCES += drivers/delay_timer/generic_delay_timer.c
endif
BL2U_SOURCES += plat/arm/board/fvp/fvp_bl2u_setup.c \ BL2U_SOURCES += plat/arm/board/fvp/fvp_bl2u_setup.c \
${FVP_SECURITY_SOURCES} ${FVP_SECURITY_SOURCES}
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
*/ */
#include <arch.h> #include <arch.h>
#include <arch_helpers.h> #include <arch_helpers.h>
#include <assert.h>
#include <debug.h> #include <debug.h>
#include <mmio.h> #include <mmio.h>
#include <plat_arm.h> #include <plat_arm.h>
...@@ -40,7 +41,14 @@ extern const mmap_region_t plat_arm_mmap[]; ...@@ -40,7 +41,14 @@ extern const mmap_region_t plat_arm_mmap[];
/* Weak definitions may be overridden in specific ARM standard platform */ /* Weak definitions may be overridden in specific ARM standard platform */
#pragma weak plat_get_ns_image_entrypoint #pragma weak plat_get_ns_image_entrypoint
#pragma weak plat_arm_get_mmap #pragma weak plat_arm_get_mmap
/* Conditionally provide a weak definition of plat_get_syscnt_freq2 to avoid
* conflicts with the definition in plat/common. */
#if ERROR_DEPRECATED
#pragma weak plat_get_syscnt_freq2
#else
#pragma weak plat_get_syscnt_freq #pragma weak plat_get_syscnt_freq
#endif
/******************************************************************************* /*******************************************************************************
* Macro generating the code for the function setting up the pagetables as per * Macro generating the code for the function setting up the pagetables as per
...@@ -164,9 +172,16 @@ const mmap_region_t *plat_arm_get_mmap(void) ...@@ -164,9 +172,16 @@ const mmap_region_t *plat_arm_get_mmap(void)
} }
#ifdef ARM_SYS_CNTCTL_BASE #ifdef ARM_SYS_CNTCTL_BASE
#if ERROR_DEPRECATED
unsigned int plat_get_syscnt_freq2(void)
{
unsigned int counter_base_frequency
#else
unsigned long long plat_get_syscnt_freq(void) unsigned long long plat_get_syscnt_freq(void)
{ {
unsigned long long counter_base_frequency; unsigned long long counter_base_frequency;
#endif /* ERROR_DEPRECATED */
/* Read the frequency from Frequency modes table */ /* Read the frequency from Frequency modes table */
counter_base_frequency = mmio_read_32(ARM_SYS_CNTCTL_BASE + CNTFID_OFF); counter_base_frequency = mmio_read_32(ARM_SYS_CNTCTL_BASE + CNTFID_OFF);
...@@ -177,4 +192,5 @@ unsigned long long plat_get_syscnt_freq(void) ...@@ -177,4 +192,5 @@ unsigned long long plat_get_syscnt_freq(void)
return counter_base_frequency; return counter_base_frequency;
} }
#endif /* ARM_SYS_CNTCTL_BASE */ #endif /* ARM_SYS_CNTCTL_BASE */
...@@ -40,6 +40,9 @@ ...@@ -40,6 +40,9 @@
#pragma weak bl31_plat_enable_mmu #pragma weak bl31_plat_enable_mmu
#pragma weak bl32_plat_enable_mmu #pragma weak bl32_plat_enable_mmu
#pragma weak bl31_plat_runtime_setup #pragma weak bl31_plat_runtime_setup
#if !ERROR_DEPRECATED
#pragma weak plat_get_syscnt_freq2
#endif /* ERROR_DEPRECATED */
void bl31_plat_enable_mmu(uint32_t flags) void bl31_plat_enable_mmu(uint32_t flags)
{ {
...@@ -74,3 +77,14 @@ unsigned int platform_core_pos_helper(unsigned long mpidr) ...@@ -74,3 +77,14 @@ unsigned int platform_core_pos_helper(unsigned long mpidr)
} }
#endif #endif
#if !ERROR_DEPRECATED
unsigned int plat_get_syscnt_freq2(void)
{
unsigned long long freq = plat_get_syscnt_freq();
assert(freq >> 32 == 0);
return (unsigned int)freq;
}
#endif /* ERROR_DEPRECATED */
...@@ -84,7 +84,7 @@ const mmap_region_t plat_mmap[] = { ...@@ -84,7 +84,7 @@ const mmap_region_t plat_mmap[] = {
/* Define EL3 variants of the function initialising the MMU */ /* Define EL3 variants of the function initialising the MMU */
DEFINE_CONFIGURE_MMU_EL(3) DEFINE_CONFIGURE_MMU_EL(3)
unsigned long long plat_get_syscnt_freq(void) unsigned int plat_get_syscnt_freq2(void)
{ {
return SYS_COUNTER_FREQ_IN_TICKS; return SYS_COUNTER_FREQ_IN_TICKS;
} }
......
/* /*
* Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved. * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#include <bl_common.h> #include <bl_common.h>
#include <console.h> #include <console.h>
#include <debug.h> #include <debug.h>
#include <generic_delay_timer.h>
#include <mcucfg.h> #include <mcucfg.h>
#include <mmio.h> #include <mmio.h>
#include <mtcmos.h> #include <mtcmos.h>
...@@ -167,7 +168,7 @@ void bl31_platform_setup(void) ...@@ -167,7 +168,7 @@ void bl31_platform_setup(void)
platform_setup_cpu(); platform_setup_cpu();
platform_setup_sram(); platform_setup_sram();
plat_delay_timer_init(); generic_delay_timer_init();
/* Initialize the gic cpu and distributor interfaces */ /* Initialize the gic cpu and distributor interfaces */
plat_mt_gic_init(); plat_mt_gic_init();
......
...@@ -83,7 +83,6 @@ ...@@ -83,7 +83,6 @@
* System counter frequency related constants * System counter frequency related constants
******************************************************************************/ ******************************************************************************/
#define SYS_COUNTER_FREQ_IN_TICKS 13000000 #define SYS_COUNTER_FREQ_IN_TICKS 13000000
#define SYS_COUNTER_FREQ_IN_MHZ 13
/******************************************************************************* /*******************************************************************************
* GIC-400 & interrupt handling related constants * GIC-400 & interrupt handling related constants
......
...@@ -51,6 +51,4 @@ void plat_mt_gic_init(void); ...@@ -51,6 +51,4 @@ void plat_mt_gic_init(void);
/* Declarations for plat_topology.c */ /* Declarations for plat_topology.c */
int mt_setup_topology(void); int mt_setup_topology(void);
void plat_delay_timer_init(void);
#endif /* __PLAT_PRIVATE_H__ */ #endif /* __PLAT_PRIVATE_H__ */
...@@ -52,6 +52,7 @@ BL31_SOURCES += drivers/arm/cci/cci.c \ ...@@ -52,6 +52,7 @@ BL31_SOURCES += drivers/arm/cci/cci.c \
drivers/arm/gic/gic_v3.c \ drivers/arm/gic/gic_v3.c \
drivers/console/console.S \ drivers/console/console.S \
drivers/delay_timer/delay_timer.c \ drivers/delay_timer/delay_timer.c \
drivers/delay_timer/generic_delay_timer.c \
lib/cpus/aarch64/aem_generic.S \ lib/cpus/aarch64/aem_generic.S \
lib/cpus/aarch64/cortex_a53.S \ lib/cpus/aarch64/cortex_a53.S \
lib/cpus/aarch64/cortex_a57.S \ lib/cpus/aarch64/cortex_a57.S \
...@@ -72,7 +73,6 @@ BL31_SOURCES += drivers/arm/cci/cci.c \ ...@@ -72,7 +73,6 @@ BL31_SOURCES += drivers/arm/cci/cci.c \
${MTK_PLAT_SOC}/drivers/spm/spm_suspend.c \ ${MTK_PLAT_SOC}/drivers/spm/spm_suspend.c \
${MTK_PLAT_SOC}/drivers/timer/mt_cpuxgpt.c \ ${MTK_PLAT_SOC}/drivers/timer/mt_cpuxgpt.c \
${MTK_PLAT_SOC}/drivers/uart/8250_console.S \ ${MTK_PLAT_SOC}/drivers/uart/8250_console.S \
${MTK_PLAT_SOC}/plat_delay_timer.c \
${MTK_PLAT_SOC}/plat_mt_gic.c \ ${MTK_PLAT_SOC}/plat_mt_gic.c \
${MTK_PLAT_SOC}/plat_pm.c \ ${MTK_PLAT_SOC}/plat_pm.c \
${MTK_PLAT_SOC}/plat_sip_calls.c \ ${MTK_PLAT_SOC}/plat_sip_calls.c \
......
...@@ -52,7 +52,6 @@ int32_t tegra_soc_validate_power_state(unsigned int power_state, ...@@ -52,7 +52,6 @@ int32_t tegra_soc_validate_power_state(unsigned int power_state,
/* Declarations for plat_setup.c */ /* Declarations for plat_setup.c */
const mmap_region_t *plat_get_mmio_map(void); const mmap_region_t *plat_get_mmio_map(void);
unsigned long long plat_get_syscnt_freq(void);
/* Declarations for plat_secondary.c */ /* Declarations for plat_secondary.c */
void plat_secondary_setup(void); void plat_secondary_setup(void);
......
...@@ -74,7 +74,7 @@ const mmap_region_t *plat_get_mmio_map(void) ...@@ -74,7 +74,7 @@ const mmap_region_t *plat_get_mmio_map(void)
return tegra_mmap; return tegra_mmap;
} }
unsigned long long plat_get_syscnt_freq(void) unsigned int plat_get_syscnt_freq2(void)
{ {
return 12000000; return 12000000;
} }
...@@ -80,7 +80,7 @@ const mmap_region_t *plat_get_mmio_map(void) ...@@ -80,7 +80,7 @@ const mmap_region_t *plat_get_mmio_map(void)
/******************************************************************************* /*******************************************************************************
* Handler to get the System Counter Frequency * Handler to get the System Counter Frequency
******************************************************************************/ ******************************************************************************/
unsigned long long plat_get_syscnt_freq(void) unsigned int plat_get_syscnt_freq2(void)
{ {
return 19200000; return 19200000;
} }
...@@ -75,7 +75,7 @@ static const int cci_map[] = { ...@@ -75,7 +75,7 @@ static const int cci_map[] = {
/* Define EL3 variants of the function initialising the MMU */ /* Define EL3 variants of the function initialising the MMU */
DEFINE_CONFIGURE_MMU_EL(3) DEFINE_CONFIGURE_MMU_EL(3)
unsigned long long plat_get_syscnt_freq(void) unsigned int plat_get_syscnt_freq2(void)
{ {
return SYS_COUNTER_FREQ_IN_TICKS; return SYS_COUNTER_FREQ_IN_TICKS;
} }
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment