Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
adam.huang
Arm Trusted Firmware
Commits
e141aa03
Commit
e141aa03
authored
May 24, 2016
by
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
Changes
27
Hide whitespace changes
Inline
Side-by-side
bl31/aarch64/bl31_arch_setup.c
View file @
e141aa03
...
...
@@ -44,7 +44,7 @@
void
bl31_arch_setup
(
void
)
{
/* Program the counter frequency */
write_cntfrq_el0
(
plat_get_syscnt_freq
());
write_cntfrq_el0
(
plat_get_syscnt_freq
2
());
/* Initialize the cpu_ops pointer. */
init_cpu_ops
();
...
...
docs/porting-guide.md
View file @
e141aa03
...
...
@@ -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
should return NULL otherwise.
### Function : plat_get_syscnt_freq() [mandatory]
### Function : plat_get_syscnt_freq
2
() [mandatory]
Argument : void
Return : u
int64_
t
Return : u
nsigned in
t
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
...
...
docs/user-guide.md
View file @
e141aa03
...
...
@@ -492,6 +492,9 @@ map is explained in the [Firmware Design].
Trusted Firmware is configured for dual cluster topology and this option
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
...
...
drivers/delay_timer/delay_timer.c
View file @
e141aa03
...
...
@@ -48,19 +48,22 @@ void udelay(uint32_t usec)
(
ops
->
clk_div
!=
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
();
total_delta
=
(
usec
*
ops
->
clk_div
)
/
ops
->
clk_mult
;
do
{
cnt
=
ops
->
get_timer_value
();
if
(
cnt
>
start
)
{
delta
=
UINT32_MAX
-
cnt
;
delta
+=
start
;
}
else
delta
=
start
-
cnt
;
delta_us
=
(
delta
*
ops
->
clk_mult
)
/
ops
->
clk_div
;
}
while
(
delta_us
<
usec
);
/*
* If the timer value wraps around, the subtraction will
* overflow and it will still give the correct result.
*/
delta
=
start
-
ops
->
get_timer_value
();
/* Decreasing counter */
}
while
(
delta
<
total_delta
);
}
/***********************************************************
...
...
plat/mediatek/mt8173/plat
_delay_timer.c
→
drivers/delay_timer/generic
_delay_timer.c
View file @
e141aa03
/*
* Copyright (c) 201
5
, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 201
6
, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
...
...
@@ -27,25 +27,56 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <arch_helpers.h>
#include <assert.h>
#include <bl_common.h>
#include <debug.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
* 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
());
}
static
const
timer_ops_t
plat_timer_ops
=
{
.
get_timer_value
=
plat_get_timer_value
,
.
clk_mult
=
1
,
.
clk_div
=
SYS_COUNTER_FREQ_IN_MHZ
,
};
void
generic_delay_timer_init_args
(
uint32_t
mult
,
uint32_t
div
)
{
ops
.
get_timer_value
=
get_timer_value
;
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
);
}
plat/rockchip/common/plat
_delay_timer.
c
→
include/drivers/generic
_delay_timer.
h
View file @
e141aa03
...
...
@@ -28,27 +28,13 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <arch_helpers.h>
#include <delay_timer.h>
#include <platform_def.h>
#ifndef __GENERIC_DELAY_TIMER_H__
#define __GENERIC_DELAY_TIMER_H__
static
uint32_t
plat_get_timer_value
(
void
)
{
/*
* 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
());
}
#include <stdint.h>
static
const
timer_ops_t
plat_timer_ops
=
{
.
get_timer_value
=
plat_get_timer_value
,
.
clk_mult
=
1
,
.
clk_div
=
SYS_COUNTER_FREQ_IN_MHZ
,
};
void
generic_delay_timer_init_args
(
uint32_t
mult
,
uint32_t
div
);
void
plat_delay_timer_init
(
void
)
{
timer_init
(
&
plat_timer_ops
);
}
void
generic_delay_timer_init
(
void
);
#endif
/* __GENERIC_DELAY_TIMER_H__ */
include/plat/common/platform.h
View file @
e141aa03
...
...
@@ -56,7 +56,9 @@ struct image_desc;
/*******************************************************************************
* 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
,
uintptr_t
*
dev_handle
,
uintptr_t
*
image_spec
);
...
...
plat/arm/board/fvp/fvp_bl2_setup.c
View file @
e141aa03
...
...
@@ -28,6 +28,7 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <generic_delay_timer.h>
#include <mmio.h>
#include <plat_arm.h>
#include <sp804_delay_timer.h>
...
...
@@ -48,6 +49,7 @@ void bl2_platform_setup(void)
{
arm_bl2_platform_setup
();
#if FVP_USE_SP804_TIMER
/* 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 */
mmio_write_32
(
V2M_SP810_BASE
,
FVP_SP810_CTRL_TIM0_OV
);
...
...
@@ -55,4 +57,7 @@ void bl2_platform_setup(void)
/* Initialize delay timer driver using SP804 dual timer 0 */
sp804_timer_init
(
V2M_SP804_TIMER0_BASE
,
SP804_TIMER_CLKMULT
,
SP804_TIMER_CLKDIV
);
#else
generic_delay_timer_init
();
#endif
/* FVP_USE_SP804_TIMER */
}
plat/arm/board/fvp/platform.mk
View file @
e141aa03
...
...
@@ -30,6 +30,11 @@
# Use the GICv3 driver on the FVP by default
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.
$(eval
$(call
add_define,FVP_USE_GIC_DRIVER))
...
...
@@ -92,8 +97,7 @@ BL1_SOURCES += drivers/io/io_semihosting.c \
${FVP_INTERCONNECT_SOURCES}
BL2_SOURCES
+=
drivers/arm/sp804/sp804_delay_timer.c
\
drivers/io/io_semihosting.c
\
BL2_SOURCES
+=
drivers/io/io_semihosting.c
\
drivers/delay_timer/delay_timer.c
\
lib/semihosting/semihosting.c
\
lib/semihosting/aarch64/semihosting_call.S
\
...
...
@@ -102,6 +106,12 @@ BL2_SOURCES += drivers/arm/sp804/sp804_delay_timer.c \
plat/arm/board/fvp/fvp_io_storage.c
\
${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
\
${FVP_SECURITY_SOURCES}
...
...
plat/arm/common/aarch64/arm_common.c
View file @
e141aa03
...
...
@@ -29,6 +29,7 @@
*/
#include <arch.h>
#include <arch_helpers.h>
#include <assert.h>
#include <debug.h>
#include <mmio.h>
#include <plat_arm.h>
...
...
@@ -40,7 +41,14 @@ extern const mmap_region_t plat_arm_mmap[];
/* Weak definitions may be overridden in specific ARM standard platform */
#pragma weak plat_get_ns_image_entrypoint
#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
#endif
/*******************************************************************************
* 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)
}
#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
counter_base_frequency
;
#endif
/* ERROR_DEPRECATED */
/* Read the frequency from Frequency modes table */
counter_base_frequency
=
mmio_read_32
(
ARM_SYS_CNTCTL_BASE
+
CNTFID_OFF
);
...
...
@@ -177,4 +192,5 @@ unsigned long long plat_get_syscnt_freq(void)
return
counter_base_frequency
;
}
#endif
/* ARM_SYS_CNTCTL_BASE */
plat/common/aarch64/plat_common.c
View file @
e141aa03
...
...
@@ -40,6 +40,9 @@
#pragma weak bl31_plat_enable_mmu
#pragma weak bl32_plat_enable_mmu
#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
)
{
...
...
@@ -74,3 +77,14 @@ unsigned int platform_core_pos_helper(unsigned long mpidr)
}
#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 */
plat/mediatek/mt8173/aarch64/platform_common.c
View file @
e141aa03
...
...
@@ -84,7 +84,7 @@ const mmap_region_t plat_mmap[] = {
/* Define EL3 variants of the function initialising the MMU */
DEFINE_CONFIGURE_MMU_EL
(
3
)
unsigned
long
long
plat_get_syscnt_freq
(
void
)
unsigned
int
plat_get_syscnt_freq
2
(
void
)
{
return
SYS_COUNTER_FREQ_IN_TICKS
;
}
...
...
plat/mediatek/mt8173/bl31_plat_setup.c
View file @
e141aa03
/*
* Copyright (c) 2013-201
5
, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2013-201
6
, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
...
...
@@ -32,6 +32,7 @@
#include <bl_common.h>
#include <console.h>
#include <debug.h>
#include <generic_delay_timer.h>
#include <mcucfg.h>
#include <mmio.h>
#include <mtcmos.h>
...
...
@@ -167,7 +168,7 @@ void bl31_platform_setup(void)
platform_setup_cpu
();
platform_setup_sram
();
plat
_delay_timer_init
();
generic
_delay_timer_init
();
/* Initialize the gic cpu and distributor interfaces */
plat_mt_gic_init
();
...
...
plat/mediatek/mt8173/include/mt8173_def.h
View file @
e141aa03
...
...
@@ -83,7 +83,6 @@
* System counter frequency related constants
******************************************************************************/
#define SYS_COUNTER_FREQ_IN_TICKS 13000000
#define SYS_COUNTER_FREQ_IN_MHZ 13
/*******************************************************************************
* GIC-400 & interrupt handling related constants
...
...
plat/mediatek/mt8173/include/plat_private.h
View file @
e141aa03
...
...
@@ -51,6 +51,4 @@ void plat_mt_gic_init(void);
/* Declarations for plat_topology.c */
int
mt_setup_topology
(
void
);
void
plat_delay_timer_init
(
void
);
#endif
/* __PLAT_PRIVATE_H__ */
plat/mediatek/mt8173/platform.mk
View file @
e141aa03
...
...
@@ -52,6 +52,7 @@ BL31_SOURCES += drivers/arm/cci/cci.c \
drivers/arm/gic/gic_v3.c
\
drivers/console/console.S
\
drivers/delay_timer/delay_timer.c
\
drivers/delay_timer/generic_delay_timer.c
\
lib/cpus/aarch64/aem_generic.S
\
lib/cpus/aarch64/cortex_a53.S
\
lib/cpus/aarch64/cortex_a57.S
\
...
...
@@ -72,7 +73,6 @@ BL31_SOURCES += drivers/arm/cci/cci.c \
${MTK_PLAT_SOC}
/drivers/spm/spm_suspend.c
\
${MTK_PLAT_SOC}
/drivers/timer/mt_cpuxgpt.c
\
${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_pm.c
\
${MTK_PLAT_SOC}
/plat_sip_calls.c
\
...
...
plat/nvidia/tegra/include/tegra_private.h
View file @
e141aa03
...
...
@@ -52,7 +52,6 @@ int32_t tegra_soc_validate_power_state(unsigned int power_state,
/* Declarations for plat_setup.c */
const
mmap_region_t
*
plat_get_mmio_map
(
void
);
unsigned
long
long
plat_get_syscnt_freq
(
void
);
/* Declarations for plat_secondary.c */
void
plat_secondary_setup
(
void
);
...
...
plat/nvidia/tegra/soc/t132/plat_setup.c
View file @
e141aa03
...
...
@@ -74,7 +74,7 @@ const mmap_region_t *plat_get_mmio_map(void)
return
tegra_mmap
;
}
unsigned
long
long
plat_get_syscnt_freq
(
void
)
unsigned
int
plat_get_syscnt_freq
2
(
void
)
{
return
12000000
;
}
plat/nvidia/tegra/soc/t210/plat_setup.c
View file @
e141aa03
...
...
@@ -80,7 +80,7 @@ const mmap_region_t *plat_get_mmio_map(void)
/*******************************************************************************
* Handler to get the System Counter Frequency
******************************************************************************/
unsigned
long
long
plat_get_syscnt_freq
(
void
)
unsigned
int
plat_get_syscnt_freq
2
(
void
)
{
return
19200000
;
}
plat/rockchip/common/aarch64/platform_common.c
View file @
e141aa03
...
...
@@ -75,7 +75,7 @@ static const int cci_map[] = {
/* Define EL3 variants of the function initialising the MMU */
DEFINE_CONFIGURE_MMU_EL
(
3
)
unsigned
long
long
plat_get_syscnt_freq
(
void
)
unsigned
int
plat_get_syscnt_freq
2
(
void
)
{
return
SYS_COUNTER_FREQ_IN_TICKS
;
}
...
...
Prev
1
2
Next
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment