[PATCH 1/3] timer-uclass: add timer_get_ops() macro

Align timer uclass with the other subsystems and provide a timer_get_ops() convenience macro.
Using this instead of the generic device_get_ops() also prevents -Wdiscarded-qualifiers warnings when used with non-const variables.
Signed-off-by: Ovidiu Panait ovpanait@gmail.com ---
drivers/timer/timer-uclass.c | 2 +- include/timer.h | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/timer/timer-uclass.c b/drivers/timer/timer-uclass.c index cbc3647698..bdc77b3822 100644 --- a/drivers/timer/timer-uclass.c +++ b/drivers/timer/timer-uclass.c @@ -32,7 +32,7 @@ DECLARE_GLOBAL_DATA_PTR;
int notrace timer_get_count(struct udevice *dev, u64 *count) { - const struct timer_ops *ops = device_get_ops(dev); + struct timer_ops *ops = timer_get_ops(dev);
if (!ops->get_count) return -ENOSYS; diff --git a/include/timer.h b/include/timer.h index a044cb034e..d33a26e28f 100644 --- a/include/timer.h +++ b/include/timer.h @@ -6,6 +6,8 @@ #ifndef _TIMER_H_ #define _TIMER_H_
+#define timer_get_ops(dev) ((struct timer_ops *)(dev)->driver->ops) + /** * dm_timer_init() - initialize a timer for time keeping. On success * initializes gd->timer so that lib/timer can use it for future

Relocate timer_ops pointers when CONFIG_NEEDS_MANUAL_RELOC is enabled.
The (gd->flags & GD_FLG_RELOC) check was added to make sure the reloc_done logic works for drivers that use DM_FLAG_PRE_RELOC.
Signed-off-by: Ovidiu Panait ovpanait@gmail.com ---
drivers/timer/timer-uclass.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+)
diff --git a/drivers/timer/timer-uclass.c b/drivers/timer/timer-uclass.c index bdc77b3822..bb71979213 100644 --- a/drivers/timer/timer-uclass.c +++ b/drivers/timer/timer-uclass.c @@ -18,6 +18,7 @@ #include <init.h> #include <timer.h> #include <linux/err.h> +#include <relocate.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -50,6 +51,19 @@ unsigned long notrace timer_get_rate(struct udevice *dev)
static int timer_pre_probe(struct udevice *dev) { + if (IS_ENABLED(CONFIG_NEEDS_MANUAL_RELOC) && + (gd->flags & GD_FLG_RELOC)) { + struct timer_ops *ops = timer_get_ops(dev); + static int reloc_done; + + if (!reloc_done) { + if (ops->get_count) + MANUAL_RELOC(ops->get_count); + + reloc_done++; + } + } + if (CONFIG_IS_ENABLED(OF_REAL)) { struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev); struct clk timer_clk;

On Tue, 11 Oct 2022 at 23:37, Ovidiu Panait ovpanait@gmail.com wrote:
Relocate timer_ops pointers when CONFIG_NEEDS_MANUAL_RELOC is enabled.
The (gd->flags & GD_FLG_RELOC) check was added to make sure the reloc_done logic works for drivers that use DM_FLAG_PRE_RELOC.
Signed-off-by: Ovidiu Panait ovpanait@gmail.com
drivers/timer/timer-uclass.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+)
Reviewed-by: Simon Glass sjg@chromium.org
Which (broken) toolchain are you using?

Hi Simon,
On 10/12/22 15:59, Simon Glass wrote:
On Tue, 11 Oct 2022 at 23:37, Ovidiu Panait ovpanait@gmail.com wrote:
Relocate timer_ops pointers when CONFIG_NEEDS_MANUAL_RELOC is enabled.
The (gd->flags & GD_FLG_RELOC) check was added to make sure the reloc_done logic works for drivers that use DM_FLAG_PRE_RELOC.
Signed-off-by: Ovidiu Panait ovpanait@gmail.com
drivers/timer/timer-uclass.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+)
Reviewed-by: Simon Glass sjg@chromium.org
Which (broken) toolchain are you using?
Microblaze and m68k still use CONFIG_NEEDS_MANUAL_RELOC=y by default. I was testing on microblaze.
Ovidiu

Current xilinx_timer_get_count() implementation does not take into account the periodic 32-bit wrap arounds, as it directly returns the 32-bit counter register value. The roll-overs cause problems in the upper timer layers, as generic timer code expects an incrementing 64-bit value from get_count() to work correctly.
Add the missing 64-bit up-conversion to fix random hangs/delays in __udelay().
Fixes: a36d86720f ("microblaze: Convert axi timer to DM driver") Signed-off-by: Ovidiu Panait ovpanait@gmail.com ---
drivers/timer/xilinx-timer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/timer/xilinx-timer.c b/drivers/timer/xilinx-timer.c index 75b4473b63..172fd9f929 100644 --- a/drivers/timer/xilinx-timer.c +++ b/drivers/timer/xilinx-timer.c @@ -40,7 +40,7 @@ static u64 xilinx_timer_get_count(struct udevice *dev)
regmap_read(priv->regs, TIMER_COUNTER_OFFSET, &value);
- return value; + return timer_conv_64(value); }
static int xilinx_timer_probe(struct udevice *dev)

On 10/12/22 07:36, Ovidiu Panait wrote:
Current xilinx_timer_get_count() implementation does not take into account the periodic 32-bit wrap arounds, as it directly returns the 32-bit counter register value. The roll-overs cause problems in the upper timer layers, as generic timer code expects an incrementing 64-bit value from get_count() to work correctly.
Add the missing 64-bit up-conversion to fix random hangs/delays in __udelay().
Fixes: a36d86720f ("microblaze: Convert axi timer to DM driver") Signed-off-by: Ovidiu Panait ovpanait@gmail.com
drivers/timer/xilinx-timer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/timer/xilinx-timer.c b/drivers/timer/xilinx-timer.c index 75b4473b63..172fd9f929 100644 --- a/drivers/timer/xilinx-timer.c +++ b/drivers/timer/xilinx-timer.c @@ -40,7 +40,7 @@ static u64 xilinx_timer_get_count(struct udevice *dev)
regmap_read(priv->regs, TIMER_COUNTER_OFFSET, &value);
- return value;
return timer_conv_64(value); }
static int xilinx_timer_probe(struct udevice *dev)
Good catch. Reviewed-by: Michal Simek michal.simek@amd.com
I will let Simon to comment other two patches.
Thanks, Michal

On 10/12/22 07:36, Ovidiu Panait wrote:
Current xilinx_timer_get_count() implementation does not take into account the periodic 32-bit wrap arounds, as it directly returns the 32-bit counter register value. The roll-overs cause problems in the upper timer layers, as generic timer code expects an incrementing 64-bit value from get_count() to work correctly.
Add the missing 64-bit up-conversion to fix random hangs/delays in __udelay().
Fixes: a36d86720f ("microblaze: Convert axi timer to DM driver") Signed-off-by: Ovidiu Panait ovpanait@gmail.com
drivers/timer/xilinx-timer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/timer/xilinx-timer.c b/drivers/timer/xilinx-timer.c index 75b4473b63..172fd9f929 100644 --- a/drivers/timer/xilinx-timer.c +++ b/drivers/timer/xilinx-timer.c @@ -40,7 +40,7 @@ static u64 xilinx_timer_get_count(struct udevice *dev)
regmap_read(priv->regs, TIMER_COUNTER_OFFSET, &value);
- return value;
return timer_conv_64(value); }
static int xilinx_timer_probe(struct udevice *dev)
Applied all. M

On Tue, 11 Oct 2022 at 23:37, Ovidiu Panait ovpanait@gmail.com wrote:
Align timer uclass with the other subsystems and provide a timer_get_ops() convenience macro.
Using this instead of the generic device_get_ops() also prevents -Wdiscarded-qualifiers warnings when used with non-const variables.
Signed-off-by: Ovidiu Panait ovpanait@gmail.com
drivers/timer/timer-uclass.c | 2 +- include/timer.h | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-)
Reviewed-by: Simon Glass sjg@chromium.org
participants (3)
-
Michal Simek
-
Ovidiu Panait
-
Simon Glass