From: Dinh Nguyen <dinguyen@kernel.org>
To: daniel.lezcano@linaro.org
Cc: dinguyen@kernel.org, linux-kernel@vger.kernel.org,
tglx@linutronix.de, Jisheng.Zhang@synaptics.com, arnd@arndb.de
Subject: [PATCHv3] clocksource: dw_apb_timer_of: add error handling if no clock available
Date: Sat, 5 Dec 2020 04:52:23 -0600 [thread overview]
Message-ID: <20201205105223.208604-1-dinguyen@kernel.org> (raw)
commit ("b0fc70ce1f02 arm64: berlin: Select DW_APB_TIMER_OF") added the
support for the dw_apb_timer into the arm64 defconfig. However, for some
platforms like the Intel Stratix10 and Agilex, the clock manager doesn't
get loaded until after the timer driver get loaded. Thus, the driver hits
the panic "No clock nor clock-frequency property for" because it cannot
properly get the clock.
This patch adds the error handling needed for the timer driver so that
the kernel can continue booting instead of just hitting the panic.
Signed-off-by: Dinh Nguyen <dinguyen@kernel.org>
---
v3: check for IS_ERR(timer_clk) in timer_get_base_and_rate
v2: address comments from Daniel Lezcano
update commit message
---
drivers/clocksource/dw_apb_timer_of.c | 57 ++++++++++++++++++---------
1 file changed, 39 insertions(+), 18 deletions(-)
diff --git a/drivers/clocksource/dw_apb_timer_of.c b/drivers/clocksource/dw_apb_timer_of.c
index ab3ddebe8344..42e7e43b8fcd 100644
--- a/drivers/clocksource/dw_apb_timer_of.c
+++ b/drivers/clocksource/dw_apb_timer_of.c
@@ -14,12 +14,13 @@
#include <linux/reset.h>
#include <linux/sched_clock.h>
-static void __init timer_get_base_and_rate(struct device_node *np,
+static int __init timer_get_base_and_rate(struct device_node *np,
void __iomem **base, u32 *rate)
{
struct clk *timer_clk;
struct clk *pclk;
struct reset_control *rstc;
+ int ret;
*base = of_iomap(np, 0);
@@ -46,55 +47,67 @@ static void __init timer_get_base_and_rate(struct device_node *np,
pr_warn("pclk for %pOFn is present, but could not be activated\n",
np);
+ if (!of_property_read_u32(np, "clock-freq", rate) &&
+ !of_property_read_u32(np, "clock-frequency", rate))
+ return 0;
+
timer_clk = of_clk_get_by_name(np, "timer");
if (IS_ERR(timer_clk))
- goto try_clock_freq;
+ return PTR_ERR(timer_clk);
- if (!clk_prepare_enable(timer_clk)) {
- *rate = clk_get_rate(timer_clk);
- return;
- }
+ ret = clk_prepare_enable(timer_clk);
+ if (ret)
+ return ret;
+
+ *rate = clk_get_rate(timer_clk);
+ if (!(*rate))
+ return -EINVAL;
-try_clock_freq:
- if (of_property_read_u32(np, "clock-freq", rate) &&
- of_property_read_u32(np, "clock-frequency", rate))
- panic("No clock nor clock-frequency property for %pOFn", np);
+ return 0;
}
-static void __init add_clockevent(struct device_node *event_timer)
+static int __init add_clockevent(struct device_node *event_timer)
{
void __iomem *iobase;
struct dw_apb_clock_event_device *ced;
u32 irq, rate;
+ int ret = 0;
irq = irq_of_parse_and_map(event_timer, 0);
if (irq == 0)
panic("No IRQ for clock event timer");
- timer_get_base_and_rate(event_timer, &iobase, &rate);
+ ret = timer_get_base_and_rate(event_timer, &iobase, &rate);
+ if (ret)
+ return ret;
ced = dw_apb_clockevent_init(-1, event_timer->name, 300, iobase, irq,
rate);
if (!ced)
- panic("Unable to initialise clockevent device");
+ return -EINVAL;
dw_apb_clockevent_register(ced);
+
+ return 0;
}
static void __iomem *sched_io_base;
static u32 sched_rate;
-static void __init add_clocksource(struct device_node *source_timer)
+static int __init add_clocksource(struct device_node *source_timer)
{
void __iomem *iobase;
struct dw_apb_clocksource *cs;
u32 rate;
+ int ret;
- timer_get_base_and_rate(source_timer, &iobase, &rate);
+ ret = timer_get_base_and_rate(source_timer, &iobase, &rate);
+ if (ret)
+ return ret;
cs = dw_apb_clocksource_init(300, source_timer->name, iobase, rate);
if (!cs)
- panic("Unable to initialise clocksource device");
+ return -EINVAL;
dw_apb_clocksource_start(cs);
dw_apb_clocksource_register(cs);
@@ -106,6 +119,8 @@ static void __init add_clocksource(struct device_node *source_timer)
*/
sched_io_base = iobase + 0x04;
sched_rate = rate;
+
+ return 0;
}
static u64 notrace read_sched_clock(void)
@@ -146,10 +161,14 @@ static struct delay_timer dw_apb_delay_timer = {
static int num_called;
static int __init dw_apb_timer_init(struct device_node *timer)
{
+ int ret = 0;
+
switch (num_called) {
case 1:
pr_debug("%s: found clocksource timer\n", __func__);
- add_clocksource(timer);
+ ret = add_clocksource(timer);
+ if (ret)
+ return ret;
init_sched_clock();
#ifdef CONFIG_ARM
dw_apb_delay_timer.freq = sched_rate;
@@ -158,7 +177,9 @@ static int __init dw_apb_timer_init(struct device_node *timer)
break;
default:
pr_debug("%s: found clockevent timer\n", __func__);
- add_clockevent(timer);
+ ret = add_clockevent(timer);
+ if (ret)
+ return ret;
break;
}
--
2.25.1
next reply other threads:[~2020-12-05 10:56 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-12-05 10:52 Dinh Nguyen [this message]
2020-12-12 12:58 ` [tip: timers/core] clocksource/drivers/dw_apb_timer_of: Add " tip-bot2 for Dinh Nguyen
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20201205105223.208604-1-dinguyen@kernel.org \
--to=dinguyen@kernel.org \
--cc=Jisheng.Zhang@synaptics.com \
--cc=arnd@arndb.de \
--cc=daniel.lezcano@linaro.org \
--cc=linux-kernel@vger.kernel.org \
--cc=tglx@linutronix.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Powered by JetHome