[PATCH 00/10] bootstage: Migrate from timer_get_boot_us() to timer_get_us()

While working on the bootstage support for Armada XP (orion-timer) I noticed, that we currently have two API's supporting early timer functionality. These are:
a) timer_early_get_rate() & timer_early_get_count() which integrates into the "normal" timer functions like timer_get() & timer_get_us() in the early boot phase, if CONFIG_TIMER_EARLY is enabled b) timer_get_boot_us(), which was introduced with bootstage IIUTC
IMHO it makes more sense to not introduce a new API for this early timer functionality but re-use the "normal" API instead. This patchset migrates the timer_get_boot_us() implementations to the timer_early functions. This is done by:
- Implementing the timer_early functions in the drivers currently supporting timer_get_boot_us() - Migrating bootcount to using timer_get_us() instead of timer_get_boot_us() - Completely removing timer_get_boot_us()
With some minor tweaks in board_r/f for the dm_timer_init() and timer_init() call.
I've tested this on Armada XP and sandbox.
Thanks, Stefan
Stefan Roese (10): arm: arch_timer: Add timer_early functions arm: imx: syscounter: Add timer_early functions arm: armv8: generic_timer: Add timer_early functions timer: cadence-ttc: Add timer_early functions timer: omap-timer: Add timer_early functions timer: rockchip_timer: Add timer_early functions board_f/r: Allow selection of CONFIG_TIMER_EARLY w/o CONFIG_TIMER board_f/r: Don't call timer_init() when TIMER is enabled bootstage: Migrate from timer_get_boot_us() to timer_get_us() bootstage/timer: Treewide remove timer_get_boot_us()
arch/arm/cpu/armv7/arch_timer.c | 15 ++++++++--- arch/arm/cpu/armv8/generic_timer.c | 9 ++++--- arch/arm/mach-imx/syscounter.c | 12 +++++++-- arch/sandbox/cpu/cpu.c | 11 -------- boot/Kconfig | 1 + common/board_f.c | 4 +-- common/board_r.c | 5 ++-- common/bootstage.c | 26 +++++++++--------- drivers/timer/Kconfig | 1 - drivers/timer/cadence-ttc.c | 9 ++++--- drivers/timer/omap-timer.c | 9 ++++--- drivers/timer/orion-timer.c | 8 ------ drivers/timer/rockchip_timer.c | 42 ++++++++++++++++-------------- drivers/timer/tsc_timer.c | 5 ---- include/bootstage.h | 17 ++++-------- lib/time.c | 20 -------------- 16 files changed, 87 insertions(+), 107 deletions(-)

Currently this timer driver provides timer_get_boot_us() to support the BOOTSTAGE functionality. This patch adds the timer_early functions so that the "normal" timer functions can be used, when CONFIG_TIMER_EARLY is enabled.
timer_get_boot_us() will get removed in a follow-up patch, once the BOOTSTAGE interface is migrated to timer_get_us().
Signed-off-by: Stefan Roese sr@denx.de Cc: Patrick Delaunay patrick.delaunay@st.com --- arch/arm/cpu/armv7/arch_timer.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)
diff --git a/arch/arm/cpu/armv7/arch_timer.c b/arch/arm/cpu/armv7/arch_timer.c index d96406f7626f..80cfaf2d09a4 100644 --- a/arch/arm/cpu/armv7/arch_timer.c +++ b/arch/arm/cpu/armv7/arch_timer.c @@ -62,3 +62,19 @@ ulong get_tbclk(void) { return gd->arch.timer_rate_hz; } + +unsigned long notrace timer_early_get_rate(void) +{ + if (!gd->arch.timer_rate_hz) + timer_init(); + + return gd->arch.timer_rate_hz; +} + +u64 notrace timer_early_get_count(void) +{ + if (!gd->arch.timer_rate_hz) + timer_init(); + + return get_ticks(); +}

On Wed, 21 Sept 2022 at 08:06, Stefan Roese sr@denx.de wrote:
Currently this timer driver provides timer_get_boot_us() to support the BOOTSTAGE functionality. This patch adds the timer_early functions so that the "normal" timer functions can be used, when CONFIG_TIMER_EARLY is enabled.
timer_get_boot_us() will get removed in a follow-up patch, once the BOOTSTAGE interface is migrated to timer_get_us().
Signed-off-by: Stefan Roese sr@denx.de Cc: Patrick Delaunay patrick.delaunay@st.com
arch/arm/cpu/armv7/arch_timer.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)
Reviewed-by: Simon Glass sjg@chromium.org

Currently this timer driver provides timer_get_boot_us() to support the BOOTSTAGE functionality. This patch adds the timer_early functions so that the "normal" timer functions can be used, when CONFIG_TIMER_EARLY is enabled.
timer_get_boot_us() will get removed in a follow-up patch, once the BOOTSTAGE interface is migrated to timer_get_us().
Signed-off-by: Stefan Roese sr@denx.de Cc: Jun Nie jun.nie@linaro.org Cc: Shawn Guo shawn.guo@linaro.org Cc: Fabio Estevam festevam@denx.de Cc: Stefano Babic sbabic@denx.de --- arch/arm/mach-imx/syscounter.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)
diff --git a/arch/arm/mach-imx/syscounter.c b/arch/arm/mach-imx/syscounter.c index df478a232637..dbe55ee3913d 100644 --- a/arch/arm/mach-imx/syscounter.c +++ b/arch/arm/mach-imx/syscounter.c @@ -109,6 +109,22 @@ ulong timer_get_boot_us(void) return tick_to_time(get_ticks()); }
+unsigned long notrace timer_early_get_rate(void) +{ + if (!gd->arch.timer_rate_hz) + timer_init(); + + return gd->arch.timer_rate_hz; +} + +u64 notrace timer_early_get_count(void) +{ + if (!gd->arch.timer_rate_hz) + timer_init(); + + return get_ticks(); +} + void __udelay(unsigned long usec) { unsigned long long tmp;

On Wed, 21 Sept 2022 at 08:06, Stefan Roese sr@denx.de wrote:
Currently this timer driver provides timer_get_boot_us() to support the BOOTSTAGE functionality. This patch adds the timer_early functions so that the "normal" timer functions can be used, when CONFIG_TIMER_EARLY is enabled.
timer_get_boot_us() will get removed in a follow-up patch, once the BOOTSTAGE interface is migrated to timer_get_us().
Signed-off-by: Stefan Roese sr@denx.de Cc: Jun Nie jun.nie@linaro.org Cc: Shawn Guo shawn.guo@linaro.org Cc: Fabio Estevam festevam@denx.de Cc: Stefano Babic sbabic@denx.de
arch/arm/mach-imx/syscounter.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)
Reviewed-by: Simon Glass sjg@chromium.org

Currently this timer driver provides timer_get_boot_us() to support the BOOTSTAGE functionality. This patch adds the timer_early functions so that the "normal" timer functions can be used, when CONFIG_TIMER_EARLY is enabled.
timer_get_boot_us() will get removed in a follow-up patch, once the BOOTSTAGE interface is migrated to timer_get_us().
Signed-off-by: Stefan Roese sr@denx.de Cc: Michal Simek michal.simek@xilinx.com Cc: Andre Przywara andre.przywara@arm.com --- arch/arm/cpu/armv8/generic_timer.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
diff --git a/arch/arm/cpu/armv8/generic_timer.c b/arch/arm/cpu/armv8/generic_timer.c index f27a74b9d09b..01a1a167311e 100644 --- a/arch/arm/cpu/armv8/generic_timer.c +++ b/arch/arm/cpu/armv8/generic_timer.c @@ -115,3 +115,13 @@ ulong timer_get_boot_us(void)
return val / get_tbclk(); } + +unsigned long notrace timer_early_get_rate(void) +{ + return get_tbclk(); +} + +u64 notrace timer_early_get_count(void) +{ + return get_ticks(); +}

On Wed, 21 Sept 2022 at 08:06, Stefan Roese sr@denx.de wrote:
Currently this timer driver provides timer_get_boot_us() to support the BOOTSTAGE functionality. This patch adds the timer_early functions so that the "normal" timer functions can be used, when CONFIG_TIMER_EARLY is enabled.
timer_get_boot_us() will get removed in a follow-up patch, once the BOOTSTAGE interface is migrated to timer_get_us().
Signed-off-by: Stefan Roese sr@denx.de Cc: Michal Simek michal.simek@xilinx.com Cc: Andre Przywara andre.przywara@arm.com
arch/arm/cpu/armv8/generic_timer.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
Reviewed-by: Simon Glass sjg@chromium.org

Currently this timer driver provides timer_get_boot_us() to support the BOOTSTAGE functionality. This patch adds the timer_early functions so that the "normal" timer functions can be used, when CONFIG_TIMER_EARLY is enabled.
timer_get_boot_us() will get removed in a follow-up patch, once the BOOTSTAGE interface is migrated to timer_get_us().
Signed-off-by: Stefan Roese sr@denx.de Cc: Michal Simek michal.simek@xilinx.com --- drivers/timer/cadence-ttc.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+)
diff --git a/drivers/timer/cadence-ttc.c b/drivers/timer/cadence-ttc.c index 2eff45060ad6..e26c7923a140 100644 --- a/drivers/timer/cadence-ttc.c +++ b/drivers/timer/cadence-ttc.c @@ -58,6 +58,31 @@ ulong timer_get_boot_us(void) } #endif
+unsigned long notrace timer_early_get_rate(void) +{ + return 1; +} + +u64 notrace timer_early_get_count(void) +{ + u64 ticks = 0; + u32 rate = 1; + u64 us; + int ret; + + ret = dm_timer_init(); + if (!ret) { + /* The timer is available */ + rate = timer_get_rate(gd->timer); + timer_get_count(gd->timer, &ticks); + } else { + return 0; + } + + us = (ticks * 1000) / rate; + return us; +} + static u64 cadence_ttc_get_count(struct udevice *dev) { struct cadence_ttc_priv *priv = dev_get_priv(dev);

Hi Stefan,
On Wed, 21 Sept 2022 at 08:06, Stefan Roese sr@denx.de wrote:
Currently this timer driver provides timer_get_boot_us() to support the BOOTSTAGE functionality. This patch adds the timer_early functions so that the "normal" timer functions can be used, when CONFIG_TIMER_EARLY is enabled.
timer_get_boot_us() will get removed in a follow-up patch, once the BOOTSTAGE interface is migrated to timer_get_us().
Signed-off-by: Stefan Roese sr@denx.de Cc: Michal Simek michal.simek@xilinx.com
drivers/timer/cadence-ttc.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+)
diff --git a/drivers/timer/cadence-ttc.c b/drivers/timer/cadence-ttc.c index 2eff45060ad6..e26c7923a140 100644 --- a/drivers/timer/cadence-ttc.c +++ b/drivers/timer/cadence-ttc.c @@ -58,6 +58,31 @@ ulong timer_get_boot_us(void) } #endif
+unsigned long notrace timer_early_get_rate(void) +{
return 1;
+}
+u64 notrace timer_early_get_count(void) +{
u64 ticks = 0;
u32 rate = 1;
u64 us;
int ret;
ret = dm_timer_init();
I don't think you can call this if you want to support bootstage, since driver model may not be inited.
if (!ret) {
/* The timer is available */
rate = timer_get_rate(gd->timer);
timer_get_count(gd->timer, &ticks);
} else {
return 0;
}
us = (ticks * 1000) / rate;
return us;
+}
static u64 cadence_ttc_get_count(struct udevice *dev) { struct cadence_ttc_priv *priv = dev_get_priv(dev); -- 2.37.3
REgards, Simon

Hi Simon, Hi Michal,
On 25.09.22 16:15, Simon Glass wrote:
Hi Stefan,
On Wed, 21 Sept 2022 at 08:06, Stefan Roese sr@denx.de wrote:
Currently this timer driver provides timer_get_boot_us() to support the BOOTSTAGE functionality. This patch adds the timer_early functions so that the "normal" timer functions can be used, when CONFIG_TIMER_EARLY is enabled.
timer_get_boot_us() will get removed in a follow-up patch, once the BOOTSTAGE interface is migrated to timer_get_us().
Signed-off-by: Stefan Roese sr@denx.de Cc: Michal Simek michal.simek@xilinx.com
drivers/timer/cadence-ttc.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+)
diff --git a/drivers/timer/cadence-ttc.c b/drivers/timer/cadence-ttc.c index 2eff45060ad6..e26c7923a140 100644 --- a/drivers/timer/cadence-ttc.c +++ b/drivers/timer/cadence-ttc.c @@ -58,6 +58,31 @@ ulong timer_get_boot_us(void) } #endif
+unsigned long notrace timer_early_get_rate(void) +{
return 1;
+}
+u64 notrace timer_early_get_count(void) +{
u64 ticks = 0;
u32 rate = 1;
u64 us;
int ret;
ret = dm_timer_init();
I don't think you can call this if you want to support bootstage, since driver model may not be inited.
Yes, thanks for noticing. Still, this code is copied from the original timer_get_boot_us() function in this driver. Which also has problems with early timer access AFAICT.
Michal, you are the author of the timer_get_boot_us() implementation in commit 56c0e646c4f6a ("timer: cadence: Implement timer_get_boot_us"). How is this supposed to work in the early boot phase, before DM is initialized?
Thanks, Stefan
if (!ret) {
/* The timer is available */
rate = timer_get_rate(gd->timer);
timer_get_count(gd->timer, &ticks);
} else {
return 0;
}
us = (ticks * 1000) / rate;
return us;
+}
- static u64 cadence_ttc_get_count(struct udevice *dev) { struct cadence_ttc_priv *priv = dev_get_priv(dev);
-- 2.37.3
REgards, Simon
Viele Grüße, Stefan Roese

On Mon, 26 Sept 2022 at 08:11, Stefan Roese sr@denx.de wrote:
Hi Simon, Hi Michal,
On 25.09.22 16:15, Simon Glass wrote:
Hi Stefan,
On Wed, 21 Sept 2022 at 08:06, Stefan Roese sr@denx.de wrote:
Currently this timer driver provides timer_get_boot_us() to support the BOOTSTAGE functionality. This patch adds the timer_early functions so that the "normal" timer functions can be used, when CONFIG_TIMER_EARLY is enabled.
timer_get_boot_us() will get removed in a follow-up patch, once the BOOTSTAGE interface is migrated to timer_get_us().
Signed-off-by: Stefan Roese sr@denx.de Cc: Michal Simek michal.simek@xilinx.com
drivers/timer/cadence-ttc.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+)
diff --git a/drivers/timer/cadence-ttc.c b/drivers/timer/cadence-ttc.c index 2eff45060ad6..e26c7923a140 100644 --- a/drivers/timer/cadence-ttc.c +++ b/drivers/timer/cadence-ttc.c @@ -58,6 +58,31 @@ ulong timer_get_boot_us(void) } #endif
+unsigned long notrace timer_early_get_rate(void) +{
return 1;
+}
+u64 notrace timer_early_get_count(void) +{
u64 ticks = 0;
u32 rate = 1;
u64 us;
int ret;
ret = dm_timer_init();
I don't think you can call this if you want to support bootstage, since driver model may not be inited.
Yes, thanks for noticing. Still, this code is copied from the original timer_get_boot_us() function in this driver. Which also has problems with early timer access AFAICT.
Yes, good point.
Reviewed-by: Simon Glass sjg@chromium.org
Michal, you are the author of the timer_get_boot_us() implementation in commit 56c0e646c4f6a ("timer: cadence: Implement timer_get_boot_us"). How is this supposed to work in the early boot phase, before DM is initialized?
Thanks, Stefan
if (!ret) {
/* The timer is available */
rate = timer_get_rate(gd->timer);
timer_get_count(gd->timer, &ticks);
} else {
return 0;
}
us = (ticks * 1000) / rate;
return us;
+}
- static u64 cadence_ttc_get_count(struct udevice *dev) { struct cadence_ttc_priv *priv = dev_get_priv(dev);
-- 2.37.3
REgards, Simon
Regards, Simon

Hi Simon and Stefan,
On 9/28/22 03:54, Simon Glass wrote:
Hi Simon, Hi Michal,
On 25.09.22 16:15, Simon Glass wrote:
Hi Stefan,
On Wed, 21 Sept 2022 at 08:06, Stefan Roese sr@denx.de wrote:
Currently this timer driver provides timer_get_boot_us() to support the BOOTSTAGE functionality. This patch adds the timer_early functions so that the "normal" timer functions can be used, when CONFIG_TIMER_EARLY is enabled.
timer_get_boot_us() will get removed in a follow-up patch, once the BOOTSTAGE interface is migrated to timer_get_us().
Signed-off-by: Stefan Roese sr@denx.de Cc: Michal Simek michal.simek@xilinx.com
drivers/timer/cadence-ttc.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+)
diff --git a/drivers/timer/cadence-ttc.c b/drivers/timer/cadence-ttc.c index 2eff45060ad6..e26c7923a140 100644 --- a/drivers/timer/cadence-ttc.c +++ b/drivers/timer/cadence-ttc.c @@ -58,6 +58,31 @@ ulong timer_get_boot_us(void) } #endif
+unsigned long notrace timer_early_get_rate(void) +{
return 1;
+}
+u64 notrace timer_early_get_count(void) +{
u64 ticks = 0;
u32 rate = 1;
u64 us;
int ret;
ret = dm_timer_init();
I don't think you can call this if you want to support bootstage, since driver model may not be inited.
Yes, thanks for noticing. Still, this code is copied from the original timer_get_boot_us() function in this driver. Which also has problems with early timer access AFAICT.
Yes, good point.
Reviewed-by: Simon Glass sjg@chromium.org
I looked at it and kind of interesting code. For getting this working with this whole series if ttc gets u-boot,dm-pre-reloc everthing is working fine.
diff --git a/arch/arm/dts/zynqmp-r5.dts b/arch/arm/dts/zynqmp-r5.dts index a72172ef2ea4..8059931f2162 100644 --- a/arch/arm/dts/zynqmp-r5.dts +++ b/arch/arm/dts/zynqmp-r5.dts @@ -56,6 +56,7 @@
ttc0: timer@ff110000 { compatible = "cdns,ttc"; + u-boot,dm-pre-reloc; status = "okay"; reg = <0xff110000 0x1000>; timer-width = <32>;
What I see based on behavior. Every bootstage call is asking for timer_early_get_count() and because dm_timer_init() is failing 0 is returned.
Inside initf_dm() dm_init_and_scan() is called and initialized timer uclass also with timer instance. With u-boot,dm-pre-reloc also cadence timer driver. On the next dm_timer_init() gd->timer is initialized and value is returned and initf_dm() passes.
Here is the log and output from bootstage.
U-Boot 2022.10-rc5-00130-g1be5bed207c9 (Sep 30 2022 - 14:00:08 +0200)
Model: Xilinx ZynqMP R5 DRAM: 512 MiB Core: 7 devices, 7 uclasses, devicetree: embed MMC: Loading Environment from nowhere... OK In: serial@ff010000 Out: serial@ff010000 Err: serial@ff010000 Net: No ethernet found. ZynqMP r5> dm tree Class Index Probed Driver Name ----------------------------------------------------------- root 0 [ + ] root_driver root_driver clk 0 [ + ] fixed_clock |-- clk100 simple_bus 0 [ + ] simple_bus |-- amba timer 0 [ + ] cadence_ttc | |-- timer@ff110000 serial 0 [ + ] serial_zynq | `-- serial@ff010000 bootstd 0 [ ] bootstd_drv `-- bootstd bootmeth 0 [ ] bootmeth_distro `-- distro ZynqMP r5> bootstage report Timer summary in microseconds (8 records): Mark Elapsed Stage 0 0 reset 0 0 board_init_f 0 0 dm_f 0 0 dm_r 16,319 16,319 eth_common_init 18,061 1,742 main_loop 18,281 220 cli_loop 29,249 10,968 board_init_r
Accumulated time:
Would be good if you can also add u-boot,dm-pre-reloc before 9/10 patch which enables CONFIG_TIMER_EARLY.
Thanks, Michal

Hi Michal,
On 30.09.22 14:02, Michal Simek wrote:
Hi Simon and Stefan,
On 9/28/22 03:54, Simon Glass wrote:
Hi Simon, Hi Michal,
On 25.09.22 16:15, Simon Glass wrote:
Hi Stefan,
On Wed, 21 Sept 2022 at 08:06, Stefan Roese sr@denx.de wrote:
Currently this timer driver provides timer_get_boot_us() to support the BOOTSTAGE functionality. This patch adds the timer_early functions so that the "normal" timer functions can be used, when CONFIG_TIMER_EARLY is enabled.
timer_get_boot_us() will get removed in a follow-up patch, once the BOOTSTAGE interface is migrated to timer_get_us().
Signed-off-by: Stefan Roese sr@denx.de Cc: Michal Simek michal.simek@xilinx.com
drivers/timer/cadence-ttc.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+)
diff --git a/drivers/timer/cadence-ttc.c b/drivers/timer/cadence-ttc.c index 2eff45060ad6..e26c7923a140 100644 --- a/drivers/timer/cadence-ttc.c +++ b/drivers/timer/cadence-ttc.c @@ -58,6 +58,31 @@ ulong timer_get_boot_us(void) } #endif
+unsigned long notrace timer_early_get_rate(void) +{ + return 1; +}
+u64 notrace timer_early_get_count(void) +{ + u64 ticks = 0; + u32 rate = 1; + u64 us; + int ret;
+ ret = dm_timer_init();
I don't think you can call this if you want to support bootstage, since driver model may not be inited.
Yes, thanks for noticing. Still, this code is copied from the original timer_get_boot_us() function in this driver. Which also has problems with early timer access AFAICT.
Yes, good point.
Reviewed-by: Simon Glass sjg@chromium.org
I looked at it and kind of interesting code. For getting this working with this whole series if ttc gets u-boot,dm-pre-reloc everthing is working fine.
Yes, makes sense that this is needed.
diff --git a/arch/arm/dts/zynqmp-r5.dts b/arch/arm/dts/zynqmp-r5.dts index a72172ef2ea4..8059931f2162 100644 --- a/arch/arm/dts/zynqmp-r5.dts +++ b/arch/arm/dts/zynqmp-r5.dts @@ -56,6 +56,7 @@
ttc0: timer@ff110000 { compatible = "cdns,ttc"; + u-boot,dm-pre-reloc; status = "okay"; reg = <0xff110000 0x1000>; timer-width = <32>;
What I see based on behavior. Every bootstage call is asking for timer_early_get_count() and because dm_timer_init() is failing 0 is returned.
Inside initf_dm() dm_init_and_scan() is called and initialized timer uclass also with timer instance. With u-boot,dm-pre-reloc also cadence timer driver. On the next dm_timer_init() gd->timer is initialized and value is returned and initf_dm() passes.
This "early" implementation of the counter is broken, as you have noticed above. Resulting in timer functions only returning valid values after dm_timer_init(). This timer driver needs re-written early_timer functions, that will return proper timer values even in the early boot phase. Please take a look at e.g. rockchip_timer.c, perhaps something similar works for the cadence timer driver as well?
Here is the log and output from bootstage.
U-Boot 2022.10-rc5-00130-g1be5bed207c9 (Sep 30 2022 - 14:00:08 +0200)
Model: Xilinx ZynqMP R5 DRAM: 512 MiB Core: 7 devices, 7 uclasses, devicetree: embed MMC: Loading Environment from nowhere... OK In: serial@ff010000 Out: serial@ff010000 Err: serial@ff010000 Net: No ethernet found. ZynqMP r5> dm tree Class Index Probed Driver Name
root 0 [ + ] root_driver root_driver clk 0 [ + ] fixed_clock |-- clk100 simple_bus 0 [ + ] simple_bus |-- amba timer 0 [ + ] cadence_ttc | |-- timer@ff110000 serial 0 [ + ] serial_zynq | `-- serial@ff010000 bootstd 0 [ ] bootstd_drv `-- bootstd bootmeth 0 [ ] bootmeth_distro `-- distro ZynqMP r5> bootstage report Timer summary in microseconds (8 records): Mark Elapsed Stage 0 0 reset 0 0 board_init_f 0 0 dm_f 0 0 dm_r 16,319 16,319 eth_common_init 18,061 1,742 main_loop 18,281 220 cli_loop 29,249 10,968 board_init_r
Accumulated time:
Take a look at sandbox - here you will get proper early timing values as well:
=> bootstage report Timer summary in microseconds (9 records): Mark Elapsed Stage 0 0 reset 1 1 board_init_f 7,908 7,907 board_init_r 8,306 398 eth_common_init 8,311 5 main_loop 561,229 552,918 cli_loop
Accumulated time: 9 of_live 39 dm_f 39 dm_r
Would be good if you can also add u-boot,dm-pre-reloc before 9/10 patch which enables CONFIG_TIMER_EARLY.
Will do.
Thanks, Stefan

Hi Stefan,
On 9/30/22 15:45, Stefan Roese wrote:
Hi Michal,
On 30.09.22 14:02, Michal Simek wrote:
Hi Simon and Stefan,
On 9/28/22 03:54, Simon Glass wrote:
Hi Simon, Hi Michal,
On 25.09.22 16:15, Simon Glass wrote:
Hi Stefan,
On Wed, 21 Sept 2022 at 08:06, Stefan Roese sr@denx.de wrote:
Currently this timer driver provides timer_get_boot_us() to support the BOOTSTAGE functionality. This patch adds the timer_early functions so that the "normal" timer functions can be used, when CONFIG_TIMER_EARLY is enabled.
timer_get_boot_us() will get removed in a follow-up patch, once the BOOTSTAGE interface is migrated to timer_get_us().
Signed-off-by: Stefan Roese sr@denx.de Cc: Michal Simek michal.simek@xilinx.com
drivers/timer/cadence-ttc.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+)
diff --git a/drivers/timer/cadence-ttc.c b/drivers/timer/cadence-ttc.c index 2eff45060ad6..e26c7923a140 100644 --- a/drivers/timer/cadence-ttc.c +++ b/drivers/timer/cadence-ttc.c @@ -58,6 +58,31 @@ ulong timer_get_boot_us(void) } #endif
+unsigned long notrace timer_early_get_rate(void) +{ + return 1; +}
+u64 notrace timer_early_get_count(void) +{ + u64 ticks = 0; + u32 rate = 1; + u64 us; + int ret;
+ ret = dm_timer_init();
I don't think you can call this if you want to support bootstage, since driver model may not be inited.
Yes, thanks for noticing. Still, this code is copied from the original timer_get_boot_us() function in this driver. Which also has problems with early timer access AFAICT.
Yes, good point.
Reviewed-by: Simon Glass sjg@chromium.org
I looked at it and kind of interesting code. For getting this working with this whole series if ttc gets u-boot,dm-pre-reloc everthing is working fine.
Yes, makes sense that this is needed.
diff --git a/arch/arm/dts/zynqmp-r5.dts b/arch/arm/dts/zynqmp-r5.dts index a72172ef2ea4..8059931f2162 100644 --- a/arch/arm/dts/zynqmp-r5.dts +++ b/arch/arm/dts/zynqmp-r5.dts @@ -56,6 +56,7 @@
ttc0: timer@ff110000 { compatible = "cdns,ttc"; + u-boot,dm-pre-reloc; status = "okay"; reg = <0xff110000 0x1000>; timer-width = <32>;
What I see based on behavior. Every bootstage call is asking for timer_early_get_count() and because dm_timer_init() is failing 0 is returned.
Inside initf_dm() dm_init_and_scan() is called and initialized timer uclass also with timer instance. With u-boot,dm-pre-reloc also cadence timer driver. On the next dm_timer_init() gd->timer is initialized and value is returned and initf_dm() passes.
This "early" implementation of the counter is broken, as you have noticed above. Resulting in timer functions only returning valid values after dm_timer_init(). This timer driver needs re-written early_timer functions, that will return proper timer values even in the early boot phase. Please take a look at e.g. rockchip_timer.c, perhaps something similar works for the cadence timer driver as well?
I looked at it and there is a code when OF_REAL is enabled. If not then 0 is returned. That's why I can't see any difference between rockchip and cadence when OF_REAL is not enabled.
And not sure how this is working in rockchip case. Who is starting timer in their case? I see start when probe happens but after it dm_timer_init() should return 0 and value can be obtained.
Here is the log and output from bootstage.
U-Boot 2022.10-rc5-00130-g1be5bed207c9 (Sep 30 2022 - 14:00:08 +0200)
Model: Xilinx ZynqMP R5 DRAM: 512 MiB Core: 7 devices, 7 uclasses, devicetree: embed MMC: Loading Environment from nowhere... OK In: serial@ff010000 Out: serial@ff010000 Err: serial@ff010000 Net: No ethernet found. ZynqMP r5> dm tree Class Index Probed Driver Name
root 0 [ + ] root_driver root_driver clk 0 [ + ] fixed_clock |-- clk100 simple_bus 0 [ + ] simple_bus |-- amba timer 0 [ + ] cadence_ttc | |-- timer@ff110000 serial 0 [ + ] serial_zynq | `-- serial@ff010000 bootstd 0 [ ] bootstd_drv `-- bootstd bootmeth 0 [ ] bootmeth_distro `-- distro ZynqMP r5> bootstage report Timer summary in microseconds (8 records): Mark Elapsed Stage 0 0 reset 0 0 board_init_f 0 0 dm_f 0 0 dm_r 16,319 16,319 eth_common_init 18,061 1,742 main_loop 18,281 220 cli_loop 29,249 10,968 board_init_r
Accumulated time:
Take a look at sandbox - here you will get proper early timing values as well:
I expect early functions are called before DM is ready that's why to get it work that early we would have to start timer on the first call of early function. It is definitely doable but is it worth to do it?
Is there any other use case where early timer counts are needed other then bootstage?
Thanks, Michal

Hi Michal,
(adding Kever & Philipp to Cc)
On 04.10.22 13:49, Michal Simek wrote:
Hi Stefan,
On 9/30/22 15:45, Stefan Roese wrote:
Hi Michal,
On 30.09.22 14:02, Michal Simek wrote:
Hi Simon and Stefan,
On 9/28/22 03:54, Simon Glass wrote:
Hi Simon, Hi Michal,
On 25.09.22 16:15, Simon Glass wrote:
Hi Stefan,
On Wed, 21 Sept 2022 at 08:06, Stefan Roese sr@denx.de wrote: > > Currently this timer driver provides timer_get_boot_us() to > support the > BOOTSTAGE functionality. This patch adds the timer_early > functions so > that the "normal" timer functions can be used, when > CONFIG_TIMER_EARLY > is enabled. > > timer_get_boot_us() will get removed in a follow-up patch, once the > BOOTSTAGE interface is migrated to timer_get_us(). > > Signed-off-by: Stefan Roese sr@denx.de > Cc: Michal Simek michal.simek@xilinx.com > --- > drivers/timer/cadence-ttc.c | 25 +++++++++++++++++++++++++ > 1 file changed, 25 insertions(+) > > diff --git a/drivers/timer/cadence-ttc.c > b/drivers/timer/cadence-ttc.c > index 2eff45060ad6..e26c7923a140 100644 > --- a/drivers/timer/cadence-ttc.c > +++ b/drivers/timer/cadence-ttc.c > @@ -58,6 +58,31 @@ ulong timer_get_boot_us(void) > } > #endif > > +unsigned long notrace timer_early_get_rate(void) > +{ > + return 1; > +} > + > +u64 notrace timer_early_get_count(void) > +{ > + u64 ticks = 0; > + u32 rate = 1; > + u64 us; > + int ret; > + > + ret = dm_timer_init();
I don't think you can call this if you want to support bootstage, since driver model may not be inited.
Yes, thanks for noticing. Still, this code is copied from the original timer_get_boot_us() function in this driver. Which also has problems with early timer access AFAICT.
Yes, good point.
Reviewed-by: Simon Glass sjg@chromium.org
I looked at it and kind of interesting code. For getting this working with this whole series if ttc gets u-boot,dm-pre-reloc everthing is working fine.
Yes, makes sense that this is needed.
diff --git a/arch/arm/dts/zynqmp-r5.dts b/arch/arm/dts/zynqmp-r5.dts index a72172ef2ea4..8059931f2162 100644 --- a/arch/arm/dts/zynqmp-r5.dts +++ b/arch/arm/dts/zynqmp-r5.dts @@ -56,6 +56,7 @@
ttc0: timer@ff110000 { compatible = "cdns,ttc"; + u-boot,dm-pre-reloc; status = "okay"; reg = <0xff110000 0x1000>; timer-width = <32>;
What I see based on behavior. Every bootstage call is asking for timer_early_get_count() and because dm_timer_init() is failing 0 is returned.
Inside initf_dm() dm_init_and_scan() is called and initialized timer uclass also with timer instance. With u-boot,dm-pre-reloc also cadence timer driver. On the next dm_timer_init() gd->timer is initialized and value is returned and initf_dm() passes.
This "early" implementation of the counter is broken, as you have noticed above. Resulting in timer functions only returning valid values after dm_timer_init(). This timer driver needs re-written early_timer functions, that will return proper timer values even in the early boot phase. Please take a look at e.g. rockchip_timer.c, perhaps something similar works for the cadence timer driver as well?
I looked at it and there is a code when OF_REAL is enabled. If not then 0 is returned. That's why I can't see any difference between rockchip and cadence when OF_REAL is not enabled.
And not sure how this is working in rockchip case. Who is starting timer in their case?
I have no idea. My best guess is that its already enabled when U-Boot starts.
I see start when probe happens but after it dm_timer_init() should return 0 and value can be obtained.
Kever / Philipp, could you perhaps shed some light in the current rockchip early timer implementation timer_get_boot_us(). How does it work?
Here is the log and output from bootstage.
U-Boot 2022.10-rc5-00130-g1be5bed207c9 (Sep 30 2022 - 14:00:08 +0200)
Model: Xilinx ZynqMP R5 DRAM: 512 MiB Core: 7 devices, 7 uclasses, devicetree: embed MMC: Loading Environment from nowhere... OK In: serial@ff010000 Out: serial@ff010000 Err: serial@ff010000 Net: No ethernet found. ZynqMP r5> dm tree Class Index Probed Driver Name
root 0 [ + ] root_driver root_driver clk 0 [ + ] fixed_clock |-- clk100 simple_bus 0 [ + ] simple_bus |-- amba timer 0 [ + ] cadence_ttc | |-- timer@ff110000 serial 0 [ + ] serial_zynq | `-- serial@ff010000 bootstd 0 [ ] bootstd_drv `-- bootstd bootmeth 0 [ ] bootmeth_distro `-- distro ZynqMP r5> bootstage report Timer summary in microseconds (8 records): Mark Elapsed Stage 0 0 reset 0 0 board_init_f 0 0 dm_f 0 0 dm_r 16,319 16,319 eth_common_init 18,061 1,742 main_loop 18,281 220 cli_loop 29,249 10,968 board_init_r
Accumulated time:
Take a look at sandbox - here you will get proper early timing values as well:
I expect early functions are called before DM is ready that's why to get it work that early we would have to start timer on the first call of early function. It is definitely doable but is it worth to do it?
Depends on your needs of course.
Is there any other use case where early timer counts are needed other then bootstage?
Definitely. I can think of early code that needs timer functionality, like udelay() etc. I'm pretty sure there are many occurrences for such timing usages before DM is initialized on some platforms.
Thanks, Stefan

Hi,
On Tue, 4 Oct 2022 at 05:50, Michal Simek michal.simek@amd.com wrote:
Hi Stefan,
On 9/30/22 15:45, Stefan Roese wrote:
Hi Michal,
On 30.09.22 14:02, Michal Simek wrote:
Hi Simon and Stefan,
On 9/28/22 03:54, Simon Glass wrote:
Hi Simon, Hi Michal,
On 25.09.22 16:15, Simon Glass wrote:
Hi Stefan,
On Wed, 21 Sept 2022 at 08:06, Stefan Roese sr@denx.de wrote: > > Currently this timer driver provides timer_get_boot_us() to support the > BOOTSTAGE functionality. This patch adds the timer_early functions so > that the "normal" timer functions can be used, when CONFIG_TIMER_EARLY > is enabled. > > timer_get_boot_us() will get removed in a follow-up patch, once the > BOOTSTAGE interface is migrated to timer_get_us(). > > Signed-off-by: Stefan Roese sr@denx.de > Cc: Michal Simek michal.simek@xilinx.com > --- > drivers/timer/cadence-ttc.c | 25 +++++++++++++++++++++++++ > 1 file changed, 25 insertions(+) > > diff --git a/drivers/timer/cadence-ttc.c b/drivers/timer/cadence-ttc.c > index 2eff45060ad6..e26c7923a140 100644 > --- a/drivers/timer/cadence-ttc.c > +++ b/drivers/timer/cadence-ttc.c > @@ -58,6 +58,31 @@ ulong timer_get_boot_us(void) > } > #endif > > +unsigned long notrace timer_early_get_rate(void) > +{ > + return 1; > +} > + > +u64 notrace timer_early_get_count(void) > +{ > + u64 ticks = 0; > + u32 rate = 1; > + u64 us; > + int ret; > + > + ret = dm_timer_init();
I don't think you can call this if you want to support bootstage, since driver model may not be inited.
Yes, thanks for noticing. Still, this code is copied from the original timer_get_boot_us() function in this driver. Which also has problems with early timer access AFAICT.
Yes, good point.
Reviewed-by: Simon Glass sjg@chromium.org
I looked at it and kind of interesting code. For getting this working with this whole series if ttc gets u-boot,dm-pre-reloc everthing is working fine.
Yes, makes sense that this is needed.
diff --git a/arch/arm/dts/zynqmp-r5.dts b/arch/arm/dts/zynqmp-r5.dts index a72172ef2ea4..8059931f2162 100644 --- a/arch/arm/dts/zynqmp-r5.dts +++ b/arch/arm/dts/zynqmp-r5.dts @@ -56,6 +56,7 @@
ttc0: timer@ff110000 { compatible = "cdns,ttc";
u-boot,dm-pre-reloc; status = "okay"; reg = <0xff110000 0x1000>; timer-width = <32>;
What I see based on behavior. Every bootstage call is asking for timer_early_get_count() and because dm_timer_init() is failing 0 is returned.
Inside initf_dm() dm_init_and_scan() is called and initialized timer uclass also with timer instance. With u-boot,dm-pre-reloc also cadence timer driver. On the next dm_timer_init() gd->timer is initialized and value is returned and initf_dm() passes.
This "early" implementation of the counter is broken, as you have noticed above. Resulting in timer functions only returning valid values after dm_timer_init(). This timer driver needs re-written early_timer functions, that will return proper timer values even in the early boot phase. Please take a look at e.g. rockchip_timer.c, perhaps something similar works for the cadence timer driver as well?
I looked at it and there is a code when OF_REAL is enabled. If not then 0 is returned. That's why I can't see any difference between rockchip and cadence when OF_REAL is not enabled.
And not sure how this is working in rockchip case. Who is starting timer in their case? I see start when probe happens but after it dm_timer_init() should return 0 and value can be obtained.
Here is the log and output from bootstage.
U-Boot 2022.10-rc5-00130-g1be5bed207c9 (Sep 30 2022 - 14:00:08 +0200)
Model: Xilinx ZynqMP R5 DRAM: 512 MiB Core: 7 devices, 7 uclasses, devicetree: embed MMC: Loading Environment from nowhere... OK In: serial@ff010000 Out: serial@ff010000 Err: serial@ff010000 Net: No ethernet found. ZynqMP r5> dm tree Class Index Probed Driver Name
root 0 [ + ] root_driver root_driver clk 0 [ + ] fixed_clock |-- clk100 simple_bus 0 [ + ] simple_bus |-- amba timer 0 [ + ] cadence_ttc | |-- timer@ff110000 serial 0 [ + ] serial_zynq | `-- serial@ff010000 bootstd 0 [ ] bootstd_drv `-- bootstd bootmeth 0 [ ] bootmeth_distro `-- distro ZynqMP r5> bootstage report Timer summary in microseconds (8 records): Mark Elapsed Stage 0 0 reset 0 0 board_init_f 0 0 dm_f 0 0 dm_r 16,319 16,319 eth_common_init 18,061 1,742 main_loop 18,281 220 cli_loop 29,249 10,968 board_init_r
Accumulated time:
Take a look at sandbox - here you will get proper early timing values as well:
I expect early functions are called before DM is ready that's why to get it work that early we would have to start timer on the first call of early function. It is definitely doable but is it worth to do it?
Is there any other use case where early timer counts are needed other then bootstage?
Here is how it should work, I think:
static void notrace ensure_timer_setup(void) { // set up the timer if not already done // avoid using any DM functions }
static u64 xx_get_count(void) { // read and return the timer counter }
u64 notrace timer_early_get_count(void) { ensure_timer_setup(); return xxx_get_count(); }
static u64 xx_timer_get_count(struct udevice *dev) { return xxx_get_count(); }
int xxx_timer_probe(struct udevice *dev) { ensure_timer_setup();
return 0; }
Regards, Simon

Hi,
On 10/4/22 18:29, Simon Glass wrote:
Hi,
On Tue, 4 Oct 2022 at 05:50, Michal Simek michal.simek@amd.com wrote:
Hi Stefan,
On 9/30/22 15:45, Stefan Roese wrote:
Hi Michal,
On 30.09.22 14:02, Michal Simek wrote:
Hi Simon and Stefan,
On 9/28/22 03:54, Simon Glass wrote:
Hi Simon, Hi Michal,
On 25.09.22 16:15, Simon Glass wrote: > Hi Stefan, > > On Wed, 21 Sept 2022 at 08:06, Stefan Roese sr@denx.de wrote: >> >> Currently this timer driver provides timer_get_boot_us() to support the >> BOOTSTAGE functionality. This patch adds the timer_early functions so >> that the "normal" timer functions can be used, when CONFIG_TIMER_EARLY >> is enabled. >> >> timer_get_boot_us() will get removed in a follow-up patch, once the >> BOOTSTAGE interface is migrated to timer_get_us(). >> >> Signed-off-by: Stefan Roese sr@denx.de >> Cc: Michal Simek michal.simek@xilinx.com >> --- >> drivers/timer/cadence-ttc.c | 25 +++++++++++++++++++++++++ >> 1 file changed, 25 insertions(+) >> >> diff --git a/drivers/timer/cadence-ttc.c b/drivers/timer/cadence-ttc.c >> index 2eff45060ad6..e26c7923a140 100644 >> --- a/drivers/timer/cadence-ttc.c >> +++ b/drivers/timer/cadence-ttc.c >> @@ -58,6 +58,31 @@ ulong timer_get_boot_us(void) >> } >> #endif >> >> +unsigned long notrace timer_early_get_rate(void) >> +{ >> + return 1; >> +} >> + >> +u64 notrace timer_early_get_count(void) >> +{ >> + u64 ticks = 0; >> + u32 rate = 1; >> + u64 us; >> + int ret; >> + >> + ret = dm_timer_init(); > > I don't think you can call this if you want to support bootstage, > since driver model may not be inited.
Yes, thanks for noticing. Still, this code is copied from the original timer_get_boot_us() function in this driver. Which also has problems with early timer access AFAICT.
Yes, good point.
Reviewed-by: Simon Glass sjg@chromium.org
I looked at it and kind of interesting code. For getting this working with this whole series if ttc gets u-boot,dm-pre-reloc everthing is working fine.
Yes, makes sense that this is needed.
diff --git a/arch/arm/dts/zynqmp-r5.dts b/arch/arm/dts/zynqmp-r5.dts index a72172ef2ea4..8059931f2162 100644 --- a/arch/arm/dts/zynqmp-r5.dts +++ b/arch/arm/dts/zynqmp-r5.dts @@ -56,6 +56,7 @@
ttc0: timer@ff110000 { compatible = "cdns,ttc";
u-boot,dm-pre-reloc; status = "okay"; reg = <0xff110000 0x1000>; timer-width = <32>;
What I see based on behavior. Every bootstage call is asking for timer_early_get_count() and because dm_timer_init() is failing 0 is returned.
Inside initf_dm() dm_init_and_scan() is called and initialized timer uclass also with timer instance. With u-boot,dm-pre-reloc also cadence timer driver. On the next dm_timer_init() gd->timer is initialized and value is returned and initf_dm() passes.
This "early" implementation of the counter is broken, as you have noticed above. Resulting in timer functions only returning valid values after dm_timer_init(). This timer driver needs re-written early_timer functions, that will return proper timer values even in the early boot phase. Please take a look at e.g. rockchip_timer.c, perhaps something similar works for the cadence timer driver as well?
I looked at it and there is a code when OF_REAL is enabled. If not then 0 is returned. That's why I can't see any difference between rockchip and cadence when OF_REAL is not enabled.
And not sure how this is working in rockchip case. Who is starting timer in their case? I see start when probe happens but after it dm_timer_init() should return 0 and value can be obtained.
Here is the log and output from bootstage.
U-Boot 2022.10-rc5-00130-g1be5bed207c9 (Sep 30 2022 - 14:00:08 +0200)
Model: Xilinx ZynqMP R5 DRAM: 512 MiB Core: 7 devices, 7 uclasses, devicetree: embed MMC: Loading Environment from nowhere... OK In: serial@ff010000 Out: serial@ff010000 Err: serial@ff010000 Net: No ethernet found. ZynqMP r5> dm tree Class Index Probed Driver Name
root 0 [ + ] root_driver root_driver clk 0 [ + ] fixed_clock |-- clk100 simple_bus 0 [ + ] simple_bus |-- amba timer 0 [ + ] cadence_ttc | |-- timer@ff110000 serial 0 [ + ] serial_zynq | `-- serial@ff010000 bootstd 0 [ ] bootstd_drv `-- bootstd bootmeth 0 [ ] bootmeth_distro `-- distro ZynqMP r5> bootstage report Timer summary in microseconds (8 records): Mark Elapsed Stage 0 0 reset 0 0 board_init_f 0 0 dm_f 0 0 dm_r 16,319 16,319 eth_common_init 18,061 1,742 main_loop 18,281 220 cli_loop 29,249 10,968 board_init_r
Accumulated time:
Take a look at sandbox - here you will get proper early timing values as well:
I expect early functions are called before DM is ready that's why to get it work that early we would have to start timer on the first call of early function. It is definitely doable but is it worth to do it?
Is there any other use case where early timer counts are needed other then bootstage?
Here is how it should work, I think:
static void notrace ensure_timer_setup(void) { // set up the timer if not already done // avoid using any DM functions }
static u64 xx_get_count(void) { // read and return the timer counter }
u64 notrace timer_early_get_count(void) { ensure_timer_setup(); return xxx_get_count(); }
static u64 xx_timer_get_count(struct udevice *dev) { return xxx_get_count(); }
int xxx_timer_probe(struct udevice *dev) { ensure_timer_setup();
return 0;
}
ok this is clear and understandable. As far as I see the only information we need is to have address where timer is.
Rockchip and uclass drivers are using tick-timer when multiple timers are described in DT. That's why for systems with only one timer this property is not needed. Also this option is enabled only when OF_REAL is enabled.
When it is clear which link to use for getting address from DT or via DM we can change drivers pretty easily.
Thanks, Michal

Currently this timer driver provides timer_get_boot_us() to support the BOOTSTAGE functionality. This patch adds the timer_early functions so that the "normal" timer functions can be used, when CONFIG_TIMER_EARLY is enabled.
timer_get_boot_us() will get removed in a follow-up patch, once the BOOTSTAGE interface is migrated to timer_get_us().
Signed-off-by: Stefan Roese sr@denx.de Cc: Christian Gmeiner christian.gmeiner@gmail.com Cc: Dario Binacchi dariobin@libero.it --- drivers/timer/omap-timer.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+)
diff --git a/drivers/timer/omap-timer.c b/drivers/timer/omap-timer.c index aa2e4360c1bb..315dbb634aa7 100644 --- a/drivers/timer/omap-timer.c +++ b/drivers/timer/omap-timer.c @@ -106,6 +106,31 @@ ulong timer_get_boot_us(void) } #endif
+unsigned long notrace timer_early_get_rate(void) +{ + return 1; +} + +u64 notrace timer_early_get_count(void) +{ + u64 ticks = 0; + u32 rate = 1; + u64 us; + int ret; + + ret = dm_timer_init(); + if (!ret) { + /* The timer is available */ + rate = timer_get_rate(gd->timer); + timer_get_count(gd->timer, &ticks); + } else { + return 0; + } + + us = (ticks * 1000) / rate; + return us; +} + static const struct timer_ops omap_timer_ops = { .get_count = omap_timer_get_count, };

Currently this timer driver provides timer_get_boot_us() to support the BOOTSTAGE functionality. This patch adds the timer_early functions so that the "normal" timer functions can be used, when CONFIG_TIMER_EARLY is enabled.
timer_get_boot_us() will get removed in a follow-up patch, once the BOOTSTAGE interface is migrated to timer_get_us().
Signed-off-by: Stefan Roese sr@denx.de Cc: Kever Yang kever.yang@rock-chips.com Cc: Philipp Tomsich philipp.tomsich@theobroma-systems.com --- drivers/timer/rockchip_timer.c | 50 ++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+)
diff --git a/drivers/timer/rockchip_timer.c b/drivers/timer/rockchip_timer.c index 62eacb986890..6e3483edce72 100644 --- a/drivers/timer/rockchip_timer.c +++ b/drivers/timer/rockchip_timer.c @@ -87,6 +87,56 @@ ulong timer_get_boot_us(void) } #endif
+static u64 timer_early_get_count_rate(uint32_t *rate) +{ + uint64_t ticks = 0; + + *rate = 1; + if (CONFIG_IS_ENABLED(OF_REAL)) { + /* We have been called so early that the DM is not ready,... */ + ofnode node = offset_to_ofnode(-1); + struct rk_timer *timer = NULL; + + /* + * ... so we try to access the raw timer, if it is specified + * via the tick-timer property in /chosen. + */ + node = ofnode_get_chosen_node("tick-timer"); + if (!ofnode_valid(node)) { + debug("%s: no /chosen/tick-timer\n", __func__); + return 0; + } + + timer = (struct rk_timer *)ofnode_get_addr(node); + + /* This timer is down-counting */ + ticks = ~0ULL - rockchip_timer_get_curr_value(timer); + if (ofnode_read_u32(node, "clock-frequency", rate)) { + debug("%s: could not read clock-frequency\n", __func__); + return 0; + } + } else { + return 0; + } + + return ticks; +} + +unsigned long notrace timer_early_get_rate(void) +{ + uint32_t rate; + + timer_early_get_count_rate(&rate); + return rate; +} + +u64 notrace timer_early_get_count(void) +{ + uint32_t rate; + + return timer_early_get_count_rate(&rate); +} + static u64 rockchip_timer_get_count(struct udevice *dev) { struct rockchip_timer_priv *priv = dev_get_priv(dev);

On 2022/9/21 22:06, Stefan Roese wrote:
Currently this timer driver provides timer_get_boot_us() to support the BOOTSTAGE functionality. This patch adds the timer_early functions so that the "normal" timer functions can be used, when CONFIG_TIMER_EARLY is enabled.
timer_get_boot_us() will get removed in a follow-up patch, once the BOOTSTAGE interface is migrated to timer_get_us().
Signed-off-by: Stefan Roese sr@denx.de Cc: Kever Yang kever.yang@rock-chips.com Cc: Philipp Tomsich philipp.tomsich@theobroma-systems.com
Reviewed-by: Kever Yang kever.yang@rock-chips.com
Thanks, - Kever
drivers/timer/rockchip_timer.c | 50 ++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+)
diff --git a/drivers/timer/rockchip_timer.c b/drivers/timer/rockchip_timer.c index 62eacb986890..6e3483edce72 100644 --- a/drivers/timer/rockchip_timer.c +++ b/drivers/timer/rockchip_timer.c @@ -87,6 +87,56 @@ ulong timer_get_boot_us(void) } #endif
+static u64 timer_early_get_count_rate(uint32_t *rate) +{
- uint64_t ticks = 0;
- *rate = 1;
- if (CONFIG_IS_ENABLED(OF_REAL)) {
/* We have been called so early that the DM is not ready,... */
ofnode node = offset_to_ofnode(-1);
struct rk_timer *timer = NULL;
/*
* ... so we try to access the raw timer, if it is specified
* via the tick-timer property in /chosen.
*/
node = ofnode_get_chosen_node("tick-timer");
if (!ofnode_valid(node)) {
debug("%s: no /chosen/tick-timer\n", __func__);
return 0;
}
timer = (struct rk_timer *)ofnode_get_addr(node);
/* This timer is down-counting */
ticks = ~0ULL - rockchip_timer_get_curr_value(timer);
if (ofnode_read_u32(node, "clock-frequency", rate)) {
debug("%s: could not read clock-frequency\n", __func__);
return 0;
}
- } else {
return 0;
- }
- return ticks;
+}
+unsigned long notrace timer_early_get_rate(void) +{
- uint32_t rate;
- timer_early_get_count_rate(&rate);
- return rate;
+}
+u64 notrace timer_early_get_count(void) +{
- uint32_t rate;
- return timer_early_get_count_rate(&rate);
+}
- static u64 rockchip_timer_get_count(struct udevice *dev) { struct rockchip_timer_priv *priv = dev_get_priv(dev);

The early timer functions provided via CONFIG_TIMER_EARLY don't need CONFIG_TIMER to be enabled, as they don't make use of the DM timer and uclass interface. This patch now allow the selection of CONFIG_TIMER_EARLY w/o CONFIG_TIMER, enabling this early timer functionality also for non CONFIG_TIMER drivers.
With this change it's necessary to guard the dm_timer_init() call in initr_dm_devices() & initf_dm() additionally via CONFIG_TIMER.
Signed-off-by: Stefan Roese sr@denx.de --- common/board_f.c | 2 +- common/board_r.c | 2 +- drivers/timer/Kconfig | 1 - 3 files changed, 2 insertions(+), 3 deletions(-)
diff --git a/common/board_f.c b/common/board_f.c index f92d7b9faf4c..b1f67bfa72aa 100644 --- a/common/board_f.c +++ b/common/board_f.c @@ -787,7 +787,7 @@ static int initf_dm(void) if (ret) return ret;
- if (IS_ENABLED(CONFIG_TIMER_EARLY)) { + if (IS_ENABLED(CONFIG_TIMER) && IS_ENABLED(CONFIG_TIMER_EARLY)) { ret = dm_timer_init(); if (ret) return ret; diff --git a/common/board_r.c b/common/board_r.c index 50670b5615a5..56575e552df8 100644 --- a/common/board_r.c +++ b/common/board_r.c @@ -254,7 +254,7 @@ static int initr_dm_devices(void) { int ret;
- if (IS_ENABLED(CONFIG_TIMER_EARLY)) { + if (IS_ENABLED(CONFIG_TIMER) && IS_ENABLED(CONFIG_TIMER_EARLY)) { ret = dm_timer_init(); if (ret) return ret; diff --git a/drivers/timer/Kconfig b/drivers/timer/Kconfig index fd8745ffc2e0..91107b662b7e 100644 --- a/drivers/timer/Kconfig +++ b/drivers/timer/Kconfig @@ -39,7 +39,6 @@ config VPL_TIMER
config TIMER_EARLY bool "Allow timer to be used early in U-Boot" - depends on TIMER # initr_bootstage() requires a timer and is called before initr_dm() # so only the early timer is available default y if X86 && BOOTSTAGE

Hi Stefan,
On Wed, 21 Sept 2022 at 08:06, Stefan Roese sr@denx.de wrote:
The early timer functions provided via CONFIG_TIMER_EARLY don't need CONFIG_TIMER to be enabled, as they don't make use of the DM timer and uclass interface. This patch now allow the selection of CONFIG_TIMER_EARLY w/o CONFIG_TIMER, enabling this early timer functionality also for non CONFIG_TIMER drivers.
With this change it's necessary to guard the dm_timer_init() call in initr_dm_devices() & initf_dm() additionally via CONFIG_TIMER.
Signed-off-by: Stefan Roese sr@denx.de
common/board_f.c | 2 +- common/board_r.c | 2 +- drivers/timer/Kconfig | 1 - 3 files changed, 2 insertions(+), 3 deletions(-)
I don't like this as it complicates the logic and also seems to be adding a new feature to legacy code.
Instead, let's enable the early timer only for driver model.
Regards, Simon

Hi Simon,
On 25.09.22 16:15, Simon Glass wrote:
Hi Stefan,
On Wed, 21 Sept 2022 at 08:06, Stefan Roese sr@denx.de wrote:
The early timer functions provided via CONFIG_TIMER_EARLY don't need CONFIG_TIMER to be enabled, as they don't make use of the DM timer and uclass interface. This patch now allow the selection of CONFIG_TIMER_EARLY w/o CONFIG_TIMER, enabling this early timer functionality also for non CONFIG_TIMER drivers.
With this change it's necessary to guard the dm_timer_init() call in initr_dm_devices() & initf_dm() additionally via CONFIG_TIMER.
Signed-off-by: Stefan Roese sr@denx.de
common/board_f.c | 2 +- common/board_r.c | 2 +- drivers/timer/Kconfig | 1 - 3 files changed, 2 insertions(+), 3 deletions(-)
I don't like this as it complicates the logic and also seems to be adding a new feature to legacy code.
Instead, let's enable the early timer only for driver model.
Hmmm, not sure how this should work. Do you have this in mind (instead of this patch)?
diff --git a/drivers/timer/Kconfig b/drivers/timer/Kconfig index fd8745ffc2e0..30d6efe98f29 100644 --- a/drivers/timer/Kconfig +++ b/drivers/timer/Kconfig @@ -39,7 +39,7 @@ config VPL_TIMER
config TIMER_EARLY bool "Allow timer to be used early in U-Boot" - depends on TIMER + depends on DM # initr_bootstage() requires a timer and is called before initr_dm() # so only the early timer is available default y if X86 && BOOTSTAGE
This results in some compilation errors, like this:
$ make stm32mp15_basic_defconfig $ make -sj /opt/kernel.org/gcc-11.1.0-nolibc/arm-linux-gnueabi/bin/arm-linux-gnueabi-ld.bfd: common/board_f.o: in function `initf_dm': /home/stefan/git/u-boot/u-boot-marvell/common/board_f.c:791: undefined reference to `dm_timer_init' /opt/kernel.org/gcc-11.1.0-nolibc/arm-linux-gnueabi/bin/arm-linux-gnueabi-ld.bfd: common/board_r.o: in function `initr_dm_devices': /home/stefan/git/u-boot/u-boot-marvell/common/board_r.c:258: undefined reference to `dm_timer_init' make: *** [Makefile:1790: u-boot] Error 1
I might be missing something. Or it's not that easy and we still need my original implementation.
Thanks, Stefan

Hi Stefan,
On Mon, 26 Sept 2022 at 07:52, Stefan Roese sr@denx.de wrote:
Hi Simon,
On 25.09.22 16:15, Simon Glass wrote:
Hi Stefan,
On Wed, 21 Sept 2022 at 08:06, Stefan Roese sr@denx.de wrote:
The early timer functions provided via CONFIG_TIMER_EARLY don't need CONFIG_TIMER to be enabled, as they don't make use of the DM timer and uclass interface. This patch now allow the selection of CONFIG_TIMER_EARLY w/o CONFIG_TIMER, enabling this early timer functionality also for non CONFIG_TIMER drivers.
With this change it's necessary to guard the dm_timer_init() call in initr_dm_devices() & initf_dm() additionally via CONFIG_TIMER.
Signed-off-by: Stefan Roese sr@denx.de
common/board_f.c | 2 +- common/board_r.c | 2 +- drivers/timer/Kconfig | 1 - 3 files changed, 2 insertions(+), 3 deletions(-)
I don't like this as it complicates the logic and also seems to be adding a new feature to legacy code.
Instead, let's enable the early timer only for driver model.
Hmmm, not sure how this should work. Do you have this in mind (instead of this patch)?
diff --git a/drivers/timer/Kconfig b/drivers/timer/Kconfig index fd8745ffc2e0..30d6efe98f29 100644 --- a/drivers/timer/Kconfig +++ b/drivers/timer/Kconfig @@ -39,7 +39,7 @@ config VPL_TIMER
config TIMER_EARLY bool "Allow timer to be used early in U-Boot"
depends on TIMER
depends on DM # initr_bootstage() requires a timer and is called before
initr_dm() # so only the early timer is available default y if X86 && BOOTSTAGE
This results in some compilation errors, like this:
$ make stm32mp15_basic_defconfig $ make -sj /opt/kernel.org/gcc-11.1.0-nolibc/arm-linux-gnueabi/bin/arm-linux-gnueabi-ld.bfd: common/board_f.o: in function `initf_dm': /home/stefan/git/u-boot/u-boot-marvell/common/board_f.c:791: undefined reference to `dm_timer_init' /opt/kernel.org/gcc-11.1.0-nolibc/arm-linux-gnueabi/bin/arm-linux-gnueabi-ld.bfd: common/board_r.o: in function `initr_dm_devices': /home/stefan/git/u-boot/u-boot-marvell/common/board_r.c:258: undefined reference to `dm_timer_init' make: *** [Makefile:1790: u-boot] Error 1
I might be missing something. Or it's not that easy and we still need my original implementation.
Well, given that TIMER depends on DM, I don't think you need to change that.
Also, TIMER_EARLY depends on TIMER (as it should), you should just be able to check for IS_ENABLED(CONFIG_TIMER)
We can disable the early timer stuff for things that don't use CONFIG_TIMER
Regards, Simon

Hi Simon,
On 28.09.22 03:54, Simon Glass wrote:
Hi Stefan,
On Mon, 26 Sept 2022 at 07:52, Stefan Roese sr@denx.de wrote:
Hi Simon,
On 25.09.22 16:15, Simon Glass wrote:
Hi Stefan,
On Wed, 21 Sept 2022 at 08:06, Stefan Roese sr@denx.de wrote:
The early timer functions provided via CONFIG_TIMER_EARLY don't need CONFIG_TIMER to be enabled, as they don't make use of the DM timer and uclass interface. This patch now allow the selection of CONFIG_TIMER_EARLY w/o CONFIG_TIMER, enabling this early timer functionality also for non CONFIG_TIMER drivers.
With this change it's necessary to guard the dm_timer_init() call in initr_dm_devices() & initf_dm() additionally via CONFIG_TIMER.
Signed-off-by: Stefan Roese sr@denx.de
common/board_f.c | 2 +- common/board_r.c | 2 +- drivers/timer/Kconfig | 1 - 3 files changed, 2 insertions(+), 3 deletions(-)
I don't like this as it complicates the logic and also seems to be adding a new feature to legacy code.
Instead, let's enable the early timer only for driver model.
Hmmm, not sure how this should work. Do you have this in mind (instead of this patch)?
diff --git a/drivers/timer/Kconfig b/drivers/timer/Kconfig index fd8745ffc2e0..30d6efe98f29 100644 --- a/drivers/timer/Kconfig +++ b/drivers/timer/Kconfig @@ -39,7 +39,7 @@ config VPL_TIMER
config TIMER_EARLY bool "Allow timer to be used early in U-Boot"
depends on TIMER
depends on DM # initr_bootstage() requires a timer and is called before
initr_dm() # so only the early timer is available default y if X86 && BOOTSTAGE
This results in some compilation errors, like this:
$ make stm32mp15_basic_defconfig $ make -sj /opt/kernel.org/gcc-11.1.0-nolibc/arm-linux-gnueabi/bin/arm-linux-gnueabi-ld.bfd: common/board_f.o: in function `initf_dm': /home/stefan/git/u-boot/u-boot-marvell/common/board_f.c:791: undefined reference to `dm_timer_init' /opt/kernel.org/gcc-11.1.0-nolibc/arm-linux-gnueabi/bin/arm-linux-gnueabi-ld.bfd: common/board_r.o: in function `initr_dm_devices': /home/stefan/git/u-boot/u-boot-marvell/common/board_r.c:258: undefined reference to `dm_timer_init' make: *** [Makefile:1790: u-boot] Error 1
I might be missing something. Or it's not that easy and we still need my original implementation.
Well, given that TIMER depends on DM, I don't think you need to change that.
Also, TIMER_EARLY depends on TIMER (as it should), you should just be able to check for IS_ENABLED(CONFIG_TIMER)
We can disable the early timer stuff for things that don't use CONFIG_TIMER
The result of this would be, that BOOTSTAGE is not available for platforms that don't have TIMER_EARLY (& TIMER) enabled, like stm32mp15_basic and some others. Actually I think this is a good move, as it "encourages" people to move to enable CONFIG_TIMER.
So should I move forward this way? Depending BOOTSTAGE on TIMER?
Thanks, Stefan

Hi Stefan,
On Thu, 29 Sept 2022 at 23:36, Stefan Roese sr@denx.de wrote:
Hi Simon,
On 28.09.22 03:54, Simon Glass wrote:
Hi Stefan,
On Mon, 26 Sept 2022 at 07:52, Stefan Roese sr@denx.de wrote:
Hi Simon,
On 25.09.22 16:15, Simon Glass wrote:
Hi Stefan,
On Wed, 21 Sept 2022 at 08:06, Stefan Roese sr@denx.de wrote:
The early timer functions provided via CONFIG_TIMER_EARLY don't need CONFIG_TIMER to be enabled, as they don't make use of the DM timer and uclass interface. This patch now allow the selection of CONFIG_TIMER_EARLY w/o CONFIG_TIMER, enabling this early timer functionality also for non CONFIG_TIMER drivers.
With this change it's necessary to guard the dm_timer_init() call in initr_dm_devices() & initf_dm() additionally via CONFIG_TIMER.
Signed-off-by: Stefan Roese sr@denx.de
common/board_f.c | 2 +- common/board_r.c | 2 +- drivers/timer/Kconfig | 1 - 3 files changed, 2 insertions(+), 3 deletions(-)
I don't like this as it complicates the logic and also seems to be adding a new feature to legacy code.
Instead, let's enable the early timer only for driver model.
Hmmm, not sure how this should work. Do you have this in mind (instead of this patch)?
diff --git a/drivers/timer/Kconfig b/drivers/timer/Kconfig index fd8745ffc2e0..30d6efe98f29 100644 --- a/drivers/timer/Kconfig +++ b/drivers/timer/Kconfig @@ -39,7 +39,7 @@ config VPL_TIMER
config TIMER_EARLY bool "Allow timer to be used early in U-Boot"
depends on TIMER
depends on DM # initr_bootstage() requires a timer and is called before
initr_dm() # so only the early timer is available default y if X86 && BOOTSTAGE
This results in some compilation errors, like this:
$ make stm32mp15_basic_defconfig $ make -sj /opt/kernel.org/gcc-11.1.0-nolibc/arm-linux-gnueabi/bin/arm-linux-gnueabi-ld.bfd: common/board_f.o: in function `initf_dm': /home/stefan/git/u-boot/u-boot-marvell/common/board_f.c:791: undefined reference to `dm_timer_init' /opt/kernel.org/gcc-11.1.0-nolibc/arm-linux-gnueabi/bin/arm-linux-gnueabi-ld.bfd: common/board_r.o: in function `initr_dm_devices': /home/stefan/git/u-boot/u-boot-marvell/common/board_r.c:258: undefined reference to `dm_timer_init' make: *** [Makefile:1790: u-boot] Error 1
I might be missing something. Or it's not that easy and we still need my original implementation.
Well, given that TIMER depends on DM, I don't think you need to change that.
Also, TIMER_EARLY depends on TIMER (as it should), you should just be able to check for IS_ENABLED(CONFIG_TIMER)
We can disable the early timer stuff for things that don't use CONFIG_TIMER
The result of this would be, that BOOTSTAGE is not available for platforms that don't have TIMER_EARLY (& TIMER) enabled, like stm32mp15_basic and some others. Actually I think this is a good move, as it "encourages" people to move to enable CONFIG_TIMER.
So should I move forward this way? Depending BOOTSTAGE on TIMER?
Yes I think soas it is simplified things and we want people to migrate anyway.
Regards, Simon

Hi Simon,
On 30.09.22 15:28, Simon Glass wrote:
Hi Stefan,
On Thu, 29 Sept 2022 at 23:36, Stefan Roese sr@denx.de wrote:
Hi Simon,
On 28.09.22 03:54, Simon Glass wrote:
Hi Stefan,
On Mon, 26 Sept 2022 at 07:52, Stefan Roese sr@denx.de wrote:
Hi Simon,
On 25.09.22 16:15, Simon Glass wrote:
Hi Stefan,
On Wed, 21 Sept 2022 at 08:06, Stefan Roese sr@denx.de wrote:
The early timer functions provided via CONFIG_TIMER_EARLY don't need CONFIG_TIMER to be enabled, as they don't make use of the DM timer and uclass interface. This patch now allow the selection of CONFIG_TIMER_EARLY w/o CONFIG_TIMER, enabling this early timer functionality also for non CONFIG_TIMER drivers.
With this change it's necessary to guard the dm_timer_init() call in initr_dm_devices() & initf_dm() additionally via CONFIG_TIMER.
Signed-off-by: Stefan Roese sr@denx.de
common/board_f.c | 2 +- common/board_r.c | 2 +- drivers/timer/Kconfig | 1 - 3 files changed, 2 insertions(+), 3 deletions(-)
I don't like this as it complicates the logic and also seems to be adding a new feature to legacy code.
Instead, let's enable the early timer only for driver model.
Hmmm, not sure how this should work. Do you have this in mind (instead of this patch)?
diff --git a/drivers/timer/Kconfig b/drivers/timer/Kconfig index fd8745ffc2e0..30d6efe98f29 100644 --- a/drivers/timer/Kconfig +++ b/drivers/timer/Kconfig @@ -39,7 +39,7 @@ config VPL_TIMER
config TIMER_EARLY bool "Allow timer to be used early in U-Boot"
depends on TIMER
depends on DM # initr_bootstage() requires a timer and is called before
initr_dm() # so only the early timer is available default y if X86 && BOOTSTAGE
This results in some compilation errors, like this:
$ make stm32mp15_basic_defconfig $ make -sj /opt/kernel.org/gcc-11.1.0-nolibc/arm-linux-gnueabi/bin/arm-linux-gnueabi-ld.bfd: common/board_f.o: in function `initf_dm': /home/stefan/git/u-boot/u-boot-marvell/common/board_f.c:791: undefined reference to `dm_timer_init' /opt/kernel.org/gcc-11.1.0-nolibc/arm-linux-gnueabi/bin/arm-linux-gnueabi-ld.bfd: common/board_r.o: in function `initr_dm_devices': /home/stefan/git/u-boot/u-boot-marvell/common/board_r.c:258: undefined reference to `dm_timer_init' make: *** [Makefile:1790: u-boot] Error 1
I might be missing something. Or it's not that easy and we still need my original implementation.
Well, given that TIMER depends on DM, I don't think you need to change that.
Also, TIMER_EARLY depends on TIMER (as it should), you should just be able to check for IS_ENABLED(CONFIG_TIMER)
We can disable the early timer stuff for things that don't use CONFIG_TIMER
The result of this would be, that BOOTSTAGE is not available for platforms that don't have TIMER_EARLY (& TIMER) enabled, like stm32mp15_basic and some others. Actually I think this is a good move, as it "encourages" people to move to enable CONFIG_TIMER.
So should I move forward this way? Depending BOOTSTAGE on TIMER?
Yes I think soas it is simplified things and we want people to migrate anyway.
Ok, I'll move forward this way then.
Thanks, Stefan

The timer initialization is done implicitly when CONFIG_TIMER is enabled. There is no need to re-configure the timer again. Even worse, another call to the timer init function may lead to a re-init of the counter register and therefore non consecutive timer values.
This patch makes sure, that timer_init() is not called in case that CONFIG_TIMER is configured.
Signed-off-by: Stefan Roese sr@denx.de --- common/board_f.c | 2 +- common/board_r.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/common/board_f.c b/common/board_f.c index b1f67bfa72aa..fbc5d3e9d205 100644 --- a/common/board_f.c +++ b/common/board_f.c @@ -851,7 +851,7 @@ static const init_fnc_t init_sequence_f[] = { /* get CPU and bus clocks according to the environment variable */ get_clocks, /* get CPU and bus clocks (etc.) */ #endif -#if !defined(CONFIG_M68K) +#if !defined(CONFIG_M68K) && !IS_ENABLED(CONFIG_TIMER) timer_init, /* initialize timer */ #endif #if defined(CONFIG_BOARD_POSTCLK_INIT) diff --git a/common/board_r.c b/common/board_r.c index 56575e552df8..149cfdc3d351 100644 --- a/common/board_r.c +++ b/common/board_r.c @@ -745,7 +745,8 @@ static init_fnc_t init_sequence_r[] = { kgdb_init, #endif interrupt_init, -#if defined(CONFIG_MICROBLAZE) || defined(CONFIG_M68K) +#if (defined(CONFIG_MICROBLAZE) || defined(CONFIG_M68K)) && \ + !IS_ENABLED(CONFIG_TIMER) timer_init, /* initialize timer */ #endif #if defined(CONFIG_LED_STATUS)

This patch migrates the bootstage code from using the boot specific timer_get_boot_us() timer function to the common timer_get_us() function. This can only be done, also supporting the early boot phase, when CONFIG_TIMER_EARLY is enabled. This way, the common timer functions provide this functionality. Because of this, CONFIG_TIMER_EARLY is now selected via CONFIG_BOOTSTAGE.
Additionally all 'uint32_t' timer occurances are changed to 'ulong', as this is the return value of timer_get_us(). Otherwise this might lead to 32bit vs 64bit conversion issues on 64bit platforms.
Also the start time of the bootstage recording is now saved. Otherwise bigger timing offsets are seen on platforms where the timer does not start with 0.
Signed-off-by: Stefan Roese sr@denx.de --- boot/Kconfig | 1 + common/bootstage.c | 26 ++++++++++++++------------ include/bootstage.h | 17 +++++------------ 3 files changed, 20 insertions(+), 24 deletions(-)
diff --git a/boot/Kconfig b/boot/Kconfig index 6b3b8f072cb9..2ac7752a2eef 100644 --- a/boot/Kconfig +++ b/boot/Kconfig @@ -642,6 +642,7 @@ menu "Boot timing"
config BOOTSTAGE bool "Boot timing and reporting" + select TIMER_EARLY help Enable recording of boot time while booting. To use it, insert calls to bootstage_mark() with a suitable BOOTSTAGE_ID from diff --git a/common/bootstage.c b/common/bootstage.c index 326c40f1561f..6a655b20196b 100644 --- a/common/bootstage.c +++ b/common/bootstage.c @@ -30,7 +30,7 @@ enum {
struct bootstage_record { ulong time_us; - uint32_t start_us; + ulong start_us; const char *name; int flags; /* see enum bootstage_flags */ enum bootstage_id id; @@ -39,6 +39,7 @@ struct bootstage_record { struct bootstage_data { uint rec_count; uint next_id; + ulong start_time_us; struct bootstage_record record[RECORD_COUNT]; };
@@ -132,7 +133,7 @@ ulong bootstage_add_record(enum bootstage_id id, const char *name, if (!rec) { if (data->rec_count < RECORD_COUNT) { rec = &data->record[data->rec_count++]; - rec->time_us = mark; + rec->time_us = mark - data->start_time_us; rec->name = name; rec->flags = flags; rec->id = id; @@ -150,7 +151,7 @@ ulong bootstage_add_record(enum bootstage_id id, const char *name, ulong bootstage_error_name(enum bootstage_id id, const char *name) { return bootstage_add_record(id, name, BOOTSTAGEF_ERROR, - timer_get_boot_us()); + timer_get_us()); }
ulong bootstage_mark_name(enum bootstage_id id, const char *name) @@ -160,7 +161,7 @@ ulong bootstage_mark_name(enum bootstage_id id, const char *name) if (id == BOOTSTAGE_ID_ALLOC) flags = BOOTSTAGEF_ALLOC;
- return bootstage_add_record(id, name, flags, timer_get_boot_us()); + return bootstage_add_record(id, name, flags, timer_get_us()); }
ulong bootstage_mark_code(const char *file, const char *func, int linenum) @@ -190,11 +191,11 @@ ulong bootstage_mark_code(const char *file, const char *func, int linenum) return bootstage_mark_name(BOOTSTAGE_ID_ALLOC, str); }
-uint32_t bootstage_start(enum bootstage_id id, const char *name) +ulong bootstage_start(enum bootstage_id id, const char *name) { struct bootstage_data *data = gd->bootstage; struct bootstage_record *rec = ensure_id(data, id); - ulong start_us = timer_get_boot_us(); + ulong start_us = timer_get_us();
if (rec) { rec->start_us = start_us; @@ -204,15 +205,15 @@ uint32_t bootstage_start(enum bootstage_id id, const char *name) return start_us; }
-uint32_t bootstage_accum(enum bootstage_id id) +ulong bootstage_accum(enum bootstage_id id) { struct bootstage_data *data = gd->bootstage; struct bootstage_record *rec = ensure_id(data, id); - uint32_t duration; + ulong duration;
if (!rec) return 0; - duration = (uint32_t)timer_get_boot_us() - rec->start_us; + duration = timer_get_us() - rec->start_us; rec->time_us += duration;
return duration; @@ -239,11 +240,11 @@ static const char *get_record_name(char *buf, int len, return buf; }
-static uint32_t print_time_record(struct bootstage_record *rec, uint32_t prev) +static ulong print_time_record(struct bootstage_record *rec, ulong prev) { char buf[20];
- if (prev == -1U) { + if (prev == -1) { printf("%11s", ""); print_grouped_ull(rec->time_us, BOOTSTAGE_DIGITS); } else { @@ -331,7 +332,7 @@ void bootstage_report(void) { struct bootstage_data *data = gd->bootstage; struct bootstage_record *rec = data->record; - uint32_t prev; + ulong prev; int i;
printf("Timer summary in microseconds (%d records):\n", @@ -530,6 +531,7 @@ int bootstage_init(bool first) if (first) { data->next_id = BOOTSTAGE_ID_USER; bootstage_add_record(BOOTSTAGE_ID_AWAKE, "reset", 0, 0); + data->start_time_us = timer_get_us(); }
return 0; diff --git a/include/bootstage.h b/include/bootstage.h index 7088d0b875e4..e4516f5ca632 100644 --- a/include/bootstage.h +++ b/include/bootstage.h @@ -3,7 +3,7 @@ * This file implements recording of each stage of the boot process. It is * intended to implement timing of each stage, reporting this information * to the user and passing it to the OS for logging / further analysis. - * Note that it requires timer_get_boot_us() to be defined by the board + * Note that it requires CONFIG_TIMER_EARLY to be defined by the board * * Copyright (c) 2011 The Chromium OS Authors. */ @@ -215,13 +215,6 @@ enum bootstage_id { BOOTSTAGE_ID_ALLOC, };
-/* - * Return the time since boot in microseconds, This is needed for bootstage - * and should be defined in CPU- or board-specific code. If undefined then - * you will get a link error. - */ -ulong timer_get_boot_us(void); - #if defined(USE_HOSTCC) || !CONFIG_IS_ENABLED(SHOW_BOOT_PROGRESS) #define show_boot_progress(val) do {} while (0) #else @@ -313,7 +306,7 @@ ulong bootstage_mark_code(const char *file, const char *func, * @param name Textual name to display for this id in the report (maybe NULL) * Return: start timestamp in microseconds */ -uint32_t bootstage_start(enum bootstage_id id, const char *name); +ulong bootstage_start(enum bootstage_id id, const char *name);
/** * Mark the end of a bootstage activity @@ -327,7 +320,7 @@ uint32_t bootstage_start(enum bootstage_id id, const char *name); * less the start time recorded in the last bootstage_start() call * with this id. */ -uint32_t bootstage_accum(enum bootstage_id id); +ulong bootstage_accum(enum bootstage_id id);
/* Print a report about boot time */ void bootstage_report(void); @@ -418,12 +411,12 @@ static inline ulong bootstage_mark_code(const char *file, const char *func, return 0; }
-static inline uint32_t bootstage_start(enum bootstage_id id, const char *name) +static inline ulong bootstage_start(enum bootstage_id id, const char *name) { return 0; }
-static inline uint32_t bootstage_accum(enum bootstage_id id) +static inline ulong bootstage_accum(enum bootstage_id id) { return 0; }

On Wed, 21 Sept 2022 at 08:06, Stefan Roese sr@denx.de wrote:
This patch migrates the bootstage code from using the boot specific timer_get_boot_us() timer function to the common timer_get_us() function. This can only be done, also supporting the early boot phase, when CONFIG_TIMER_EARLY is enabled. This way, the common timer functions provide this functionality. Because of this, CONFIG_TIMER_EARLY is now selected via CONFIG_BOOTSTAGE.
Additionally all 'uint32_t' timer occurances are changed to 'ulong', as this is the return value of timer_get_us(). Otherwise this might lead to 32bit vs 64bit conversion issues on 64bit platforms.
Also the start time of the bootstage recording is now saved. Otherwise bigger timing offsets are seen on platforms where the timer does not start with 0.
Can you split this into three patches? You are changing three different things at once. Also please add a comment for start offset
Signed-off-by: Stefan Roese sr@denx.de
boot/Kconfig | 1 + common/bootstage.c | 26 ++++++++++++++------------ include/bootstage.h | 17 +++++------------ 3 files changed, 20 insertions(+), 24 deletions(-)
Regards, Simon

Hi Stefan,
st 21. 9. 2022 v 16:08 odesílatel Stefan Roese sr@denx.de napsal:
This patch migrates the bootstage code from using the boot specific timer_get_boot_us() timer function to the common timer_get_us() function. This can only be done, also supporting the early boot phase, when CONFIG_TIMER_EARLY is enabled. This way, the common timer functions provide this functionality. Because of this, CONFIG_TIMER_EARLY is now selected via CONFIG_BOOTSTAGE.
Additionally all 'uint32_t' timer occurances are changed to 'ulong', as this is the return value of timer_get_us(). Otherwise this might lead to 32bit vs 64bit conversion issues on 64bit platforms.
Also the start time of the bootstage recording is now saved. Otherwise bigger timing offsets are seen on platforms where the timer does not start with 0.
Signed-off-by: Stefan Roese sr@denx.de
boot/Kconfig | 1 + common/bootstage.c | 26 ++++++++++++++------------ include/bootstage.h | 17 +++++------------ 3 files changed, 20 insertions(+), 24 deletions(-)
diff --git a/boot/Kconfig b/boot/Kconfig index 6b3b8f072cb9..2ac7752a2eef 100644 --- a/boot/Kconfig +++ b/boot/Kconfig @@ -642,6 +642,7 @@ menu "Boot timing"
config BOOTSTAGE bool "Boot timing and reporting"
select TIMER_EARLY help Enable recording of boot time while booting. To use it, insert calls to bootstage_mark() with a suitable BOOTSTAGE_ID from
diff --git a/common/bootstage.c b/common/bootstage.c index 326c40f1561f..6a655b20196b 100644 --- a/common/bootstage.c +++ b/common/bootstage.c @@ -30,7 +30,7 @@ enum {
struct bootstage_record { ulong time_us;
uint32_t start_us;
ulong start_us; const char *name; int flags; /* see enum bootstage_flags */ enum bootstage_id id;
@@ -39,6 +39,7 @@ struct bootstage_record { struct bootstage_data { uint rec_count; uint next_id;
ulong start_time_us; struct bootstage_record record[RECORD_COUNT];
};
@@ -132,7 +133,7 @@ ulong bootstage_add_record(enum bootstage_id id, const char *name, if (!rec) { if (data->rec_count < RECORD_COUNT) { rec = &data->record[data->rec_count++];
rec->time_us = mark;
rec->time_us = mark - data->start_time_us; rec->name = name; rec->flags = flags; rec->id = id;
@@ -150,7 +151,7 @@ ulong bootstage_add_record(enum bootstage_id id, const char *name, ulong bootstage_error_name(enum bootstage_id id, const char *name) { return bootstage_add_record(id, name, BOOTSTAGEF_ERROR,
timer_get_boot_us());
timer_get_us());
}
ulong bootstage_mark_name(enum bootstage_id id, const char *name) @@ -160,7 +161,7 @@ ulong bootstage_mark_name(enum bootstage_id id, const char *name) if (id == BOOTSTAGE_ID_ALLOC) flags = BOOTSTAGEF_ALLOC;
return bootstage_add_record(id, name, flags, timer_get_boot_us());
return bootstage_add_record(id, name, flags, timer_get_us());
}
ulong bootstage_mark_code(const char *file, const char *func, int linenum) @@ -190,11 +191,11 @@ ulong bootstage_mark_code(const char *file, const char *func, int linenum) return bootstage_mark_name(BOOTSTAGE_ID_ALLOC, str); }
-uint32_t bootstage_start(enum bootstage_id id, const char *name) +ulong bootstage_start(enum bootstage_id id, const char *name) { struct bootstage_data *data = gd->bootstage; struct bootstage_record *rec = ensure_id(data, id);
ulong start_us = timer_get_boot_us();
ulong start_us = timer_get_us(); if (rec) { rec->start_us = start_us;
@@ -204,15 +205,15 @@ uint32_t bootstage_start(enum bootstage_id id, const char *name) return start_us; }
-uint32_t bootstage_accum(enum bootstage_id id) +ulong bootstage_accum(enum bootstage_id id) { struct bootstage_data *data = gd->bootstage; struct bootstage_record *rec = ensure_id(data, id);
uint32_t duration;
ulong duration; if (!rec) return 0;
duration = (uint32_t)timer_get_boot_us() - rec->start_us;
duration = timer_get_us() - rec->start_us; rec->time_us += duration; return duration;
@@ -239,11 +240,11 @@ static const char *get_record_name(char *buf, int len, return buf; }
-static uint32_t print_time_record(struct bootstage_record *rec, uint32_t prev) +static ulong print_time_record(struct bootstage_record *rec, ulong prev) { char buf[20];
if (prev == -1U) {
if (prev == -1) { printf("%11s", ""); print_grouped_ull(rec->time_us, BOOTSTAGE_DIGITS); } else {
@@ -331,7 +332,7 @@ void bootstage_report(void) { struct bootstage_data *data = gd->bootstage; struct bootstage_record *rec = data->record;
uint32_t prev;
ulong prev; int i; printf("Timer summary in microseconds (%d records):\n",
@@ -530,6 +531,7 @@ int bootstage_init(bool first) if (first) { data->next_id = BOOTSTAGE_ID_USER; bootstage_add_record(BOOTSTAGE_ID_AWAKE, "reset", 0, 0);
data->start_time_us = timer_get_us(); } return 0;
diff --git a/include/bootstage.h b/include/bootstage.h index 7088d0b875e4..e4516f5ca632 100644 --- a/include/bootstage.h +++ b/include/bootstage.h @@ -3,7 +3,7 @@
- This file implements recording of each stage of the boot process. It is
- intended to implement timing of each stage, reporting this information
- to the user and passing it to the OS for logging / further analysis.
- Note that it requires timer_get_boot_us() to be defined by the board
*/
- Note that it requires CONFIG_TIMER_EARLY to be defined by the board
- Copyright (c) 2011 The Chromium OS Authors.
@@ -215,13 +215,6 @@ enum bootstage_id { BOOTSTAGE_ID_ALLOC, };
-/*
- Return the time since boot in microseconds, This is needed for bootstage
- and should be defined in CPU- or board-specific code. If undefined then
- you will get a link error.
- */
-ulong timer_get_boot_us(void);
#if defined(USE_HOSTCC) || !CONFIG_IS_ENABLED(SHOW_BOOT_PROGRESS) #define show_boot_progress(val) do {} while (0) #else @@ -313,7 +306,7 @@ ulong bootstage_mark_code(const char *file, const char *func,
- @param name Textual name to display for this id in the report (maybe NULL)
- Return: start timestamp in microseconds
*/ -uint32_t bootstage_start(enum bootstage_id id, const char *name); +ulong bootstage_start(enum bootstage_id id, const char *name);
/**
- Mark the end of a bootstage activity
@@ -327,7 +320,7 @@ uint32_t bootstage_start(enum bootstage_id id, const char *name);
less the start time recorded in the last bootstage_start() call
with this id.
*/ -uint32_t bootstage_accum(enum bootstage_id id); +ulong bootstage_accum(enum bootstage_id id);
/* Print a report about boot time */ void bootstage_report(void); @@ -418,12 +411,12 @@ static inline ulong bootstage_mark_code(const char *file, const char *func, return 0; }
-static inline uint32_t bootstage_start(enum bootstage_id id, const char *name) +static inline ulong bootstage_start(enum bootstage_id id, const char *name) { return 0; }
-static inline uint32_t bootstage_accum(enum bootstage_id id) +static inline ulong bootstage_accum(enum bootstage_id id) { return 0; } -- 2.37.3
Just heads up this has been identified as a bad commit when I bisect it for zynqmp_r5 configuration. I will dig into it to find out what exactly is causing the issue. But initf_dm() is failing now.
Thanks, Michal
-- Michal Simek, Ing. (M.Eng), OpenPGP -> KeyID: FE3D1F91 w: www.monstr.eu p: +42-0-721842854 Maintainer of Linux kernel - Xilinx Microblaze Maintainer of Linux kernel - Xilinx Zynq ARM and ZynqMP ARM64 SoCs U-Boot custodian - Xilinx Microblaze/Zynq/ZynqMP/Versal SoCs

With the bootstage migration to timer_get_us() provided via CONFIG_TIMER_EARLY timer_get_boot_us() is superfluous now. This patch removes all occurances from the code.
Signed-off-by: Stefan Roese sr@denx.de Cc: Patrick Delaunay patrick.delaunay@st.com Cc: Jun Nie jun.nie@linaro.org Cc: Shawn Guo shawn.guo@linaro.org Cc: Fabio Estevam festevam@denx.de Cc: Stefano Babic sbabic@denx.de Cc: Michal Simek michal.simek@xilinx.com Cc: Andre Przywara andre.przywara@arm.com Cc: Christian Gmeiner christian.gmeiner@gmail.com Cc: Dario Binacchi dariobin@libero.it Cc: Kever Yang kever.yang@rock-chips.com Cc: Philipp Tomsich philipp.tomsich@theobroma-systems.com --- arch/arm/cpu/armv7/arch_timer.c | 9 ------ arch/arm/cpu/armv8/generic_timer.c | 7 ----- arch/arm/mach-imx/syscounter.c | 8 ------ arch/sandbox/cpu/cpu.c | 11 ------- drivers/timer/cadence-ttc.c | 22 -------------- drivers/timer/omap-timer.c | 22 -------------- drivers/timer/orion-timer.c | 8 ------ drivers/timer/rockchip_timer.c | 46 ------------------------------ drivers/timer/tsc_timer.c | 5 ---- lib/time.c | 20 ------------- 10 files changed, 158 deletions(-)
diff --git a/arch/arm/cpu/armv7/arch_timer.c b/arch/arm/cpu/armv7/arch_timer.c index 80cfaf2d09a4..375b7e2797ef 100644 --- a/arch/arm/cpu/armv7/arch_timer.c +++ b/arch/arm/cpu/armv7/arch_timer.c @@ -49,15 +49,6 @@ unsigned long long get_ticks(void) return (((unsigned long long)gd->arch.tbu) << 32) | gd->arch.tbl; }
- -ulong timer_get_boot_us(void) -{ - if (!gd->arch.timer_rate_hz) - timer_init(); - - return lldiv(get_ticks(), gd->arch.timer_rate_hz / 1000000); -} - ulong get_tbclk(void) { return gd->arch.timer_rate_hz; diff --git a/arch/arm/cpu/armv8/generic_timer.c b/arch/arm/cpu/armv8/generic_timer.c index 01a1a167311e..680c547eaf7d 100644 --- a/arch/arm/cpu/armv8/generic_timer.c +++ b/arch/arm/cpu/armv8/generic_timer.c @@ -109,13 +109,6 @@ unsigned long usec2ticks(unsigned long usec) return ticks; }
-ulong timer_get_boot_us(void) -{ - u64 val = get_ticks() * 1000000; - - return val / get_tbclk(); -} - unsigned long notrace timer_early_get_rate(void) { return get_tbclk(); diff --git a/arch/arm/mach-imx/syscounter.c b/arch/arm/mach-imx/syscounter.c index dbe55ee3913d..d592329c163e 100644 --- a/arch/arm/mach-imx/syscounter.c +++ b/arch/arm/mach-imx/syscounter.c @@ -101,14 +101,6 @@ ulong get_timer(ulong base) return tick_to_time(get_ticks()) - base; }
-ulong timer_get_boot_us(void) -{ - if (!gd->arch.timer_rate_hz) - timer_init(); - - return tick_to_time(get_ticks()); -} - unsigned long notrace timer_early_get_rate(void) { if (!gd->arch.timer_rate_hz) diff --git a/arch/sandbox/cpu/cpu.c b/arch/sandbox/cpu/cpu.c index d077948dd7bd..9c99839a1044 100644 --- a/arch/sandbox/cpu/cpu.c +++ b/arch/sandbox/cpu/cpu.c @@ -362,14 +362,3 @@ done: fail: return NULL; } - -ulong timer_get_boot_us(void) -{ - static uint64_t base_count; - uint64_t count = os_get_nsec(); - - if (!base_count) - base_count = count; - - return (count - base_count) / 1000; -} diff --git a/drivers/timer/cadence-ttc.c b/drivers/timer/cadence-ttc.c index e26c7923a140..39b97825318b 100644 --- a/drivers/timer/cadence-ttc.c +++ b/drivers/timer/cadence-ttc.c @@ -36,28 +36,6 @@ struct cadence_ttc_priv { struct cadence_ttc_regs *regs; };
-#if CONFIG_IS_ENABLED(BOOTSTAGE) -ulong timer_get_boot_us(void) -{ - u64 ticks = 0; - u32 rate = 1; - u64 us; - int ret; - - ret = dm_timer_init(); - if (!ret) { - /* The timer is available */ - rate = timer_get_rate(gd->timer); - timer_get_count(gd->timer, &ticks); - } else { - return 0; - } - - us = (ticks * 1000) / rate; - return us; -} -#endif - unsigned long notrace timer_early_get_rate(void) { return 1; diff --git a/drivers/timer/omap-timer.c b/drivers/timer/omap-timer.c index 315dbb634aa7..c680c4487154 100644 --- a/drivers/timer/omap-timer.c +++ b/drivers/timer/omap-timer.c @@ -84,28 +84,6 @@ static int omap_timer_of_to_plat(struct udevice *dev) return 0; }
-#if CONFIG_IS_ENABLED(BOOTSTAGE) -ulong timer_get_boot_us(void) -{ - u64 ticks = 0; - u32 rate = 1; - u64 us; - int ret; - - ret = dm_timer_init(); - if (!ret) { - /* The timer is available */ - rate = timer_get_rate(gd->timer); - timer_get_count(gd->timer, &ticks); - } else { - return 0; - } - - us = (ticks * 1000) / rate; - return us; -} -#endif - unsigned long notrace timer_early_get_rate(void) { return 1; diff --git a/drivers/timer/orion-timer.c b/drivers/timer/orion-timer.c index d0eab3ce781d..c0eadff81cf2 100644 --- a/drivers/timer/orion-timer.c +++ b/drivers/timer/orion-timer.c @@ -86,14 +86,6 @@ u64 notrace timer_early_get_count(void) return orion_timer_get_count((void *)MVEBU_TIMER_BASE); }
-ulong timer_get_boot_us(void) -{ - u64 ticks; - - ticks = timer_early_get_count(); - return lldiv(ticks * 1000, timer_early_get_rate()); -} - /* DM timer functions */ static uint64_t dm_orion_timer_get_count(struct udevice *dev) { diff --git a/drivers/timer/rockchip_timer.c b/drivers/timer/rockchip_timer.c index 6e3483edce72..7bf79d5f073e 100644 --- a/drivers/timer/rockchip_timer.c +++ b/drivers/timer/rockchip_timer.c @@ -41,52 +41,6 @@ static inline int64_t rockchip_timer_get_curr_value(struct rk_timer *timer) return cntr; }
-#if CONFIG_IS_ENABLED(BOOTSTAGE) -ulong timer_get_boot_us(void) -{ - uint64_t ticks = 0; - uint32_t rate; - uint64_t us; - int ret; - - ret = dm_timer_init(); - - if (!ret) { - /* The timer is available */ - rate = timer_get_rate(gd->timer); - timer_get_count(gd->timer, &ticks); - } else if (CONFIG_IS_ENABLED(OF_REAL) && ret == -EAGAIN) { - /* We have been called so early that the DM is not ready,... */ - ofnode node = offset_to_ofnode(-1); - struct rk_timer *timer = NULL; - - /* - * ... so we try to access the raw timer, if it is specified - * via the tick-timer property in /chosen. - */ - node = ofnode_get_chosen_node("tick-timer"); - if (!ofnode_valid(node)) { - debug("%s: no /chosen/tick-timer\n", __func__); - return 0; - } - - timer = (struct rk_timer *)ofnode_get_addr(node); - - /* This timer is down-counting */ - ticks = ~0uLL - rockchip_timer_get_curr_value(timer); - if (ofnode_read_u32(node, "clock-frequency", &rate)) { - debug("%s: could not read clock-frequency\n", __func__); - return 0; - } - } else { - return 0; - } - - us = (ticks * 1000) / rate; - return us; -} -#endif - static u64 timer_early_get_count_rate(uint32_t *rate) { uint64_t ticks = 0; diff --git a/drivers/timer/tsc_timer.c b/drivers/timer/tsc_timer.c index 192c7b71a5a3..3cb2abed0c67 100644 --- a/drivers/timer/tsc_timer.c +++ b/drivers/timer/tsc_timer.c @@ -363,11 +363,6 @@ ulong notrace timer_get_us(void) return get_ticks() / get_tbclk_mhz(); }
-ulong timer_get_boot_us(void) -{ - return timer_get_us(); -} - void __udelay(unsigned long usec) { u64 now = get_ticks(); diff --git a/lib/time.c b/lib/time.c index f3aaf472d103..7492b2bd9c62 100644 --- a/lib/time.c +++ b/lib/time.c @@ -42,26 +42,6 @@ unsigned long notrace timer_read_counter(void) return readl(CONFIG_SYS_TIMER_COUNTER); #endif } - -ulong timer_get_boot_us(void) -{ - ulong count = timer_read_counter(); - -#ifdef CONFIG_SYS_TIMER_RATE - const ulong timer_rate = CONFIG_SYS_TIMER_RATE; - - if (timer_rate == 1000000) - return count; - else if (timer_rate > 1000000) - return lldiv(count, timer_rate / 1000000); - else - return (unsigned long long)count * 1000000 / timer_rate; -#else - /* Assume the counter is in microseconds */ - return count; -#endif -} - #else extern unsigned long __weak timer_read_counter(void); #endif

On Wed, 21 Sept 2022 at 08:06, Stefan Roese sr@denx.de wrote:
With the bootstage migration to timer_get_us() provided via CONFIG_TIMER_EARLY timer_get_boot_us() is superfluous now. This patch removes all occurances from the code.
Signed-off-by: Stefan Roese sr@denx.de Cc: Patrick Delaunay patrick.delaunay@st.com Cc: Jun Nie jun.nie@linaro.org Cc: Shawn Guo shawn.guo@linaro.org Cc: Fabio Estevam festevam@denx.de Cc: Stefano Babic sbabic@denx.de Cc: Michal Simek michal.simek@xilinx.com Cc: Andre Przywara andre.przywara@arm.com Cc: Christian Gmeiner christian.gmeiner@gmail.com Cc: Dario Binacchi dariobin@libero.it Cc: Kever Yang kever.yang@rock-chips.com Cc: Philipp Tomsich philipp.tomsich@theobroma-systems.com
arch/arm/cpu/armv7/arch_timer.c | 9 ------ arch/arm/cpu/armv8/generic_timer.c | 7 ----- arch/arm/mach-imx/syscounter.c | 8 ------ arch/sandbox/cpu/cpu.c | 11 ------- drivers/timer/cadence-ttc.c | 22 -------------- drivers/timer/omap-timer.c | 22 -------------- drivers/timer/orion-timer.c | 8 ------ drivers/timer/rockchip_timer.c | 46 ------------------------------ drivers/timer/tsc_timer.c | 5 ---- lib/time.c | 20 ------------- 10 files changed, 158 deletions(-)
Reviewed-by: Simon Glass sjg@chromium.org
participants (5)
-
Kever Yang
-
Michal Simek
-
Michal Simek
-
Simon Glass
-
Stefan Roese