| From db31f87a36c613de77ea50a58324cc2b3cd232b4 Mon Sep 17 00:00:00 2001 |
| From: Alexandre Belloni <alexandre.belloni@bootlin.com> |
| Date: Fri, 20 Sep 2019 17:39:06 +0200 |
| Subject: [PATCH] clk: at91: avoid sleeping early |
| MIME-Version: 1.0 |
| Content-Type: text/plain; charset=UTF-8 |
| Content-Transfer-Encoding: 8bit |
| |
| commit 658fd65cf0b0d511de1718e48d9a28844c385ae0 upstream. |
| |
| It is not allowed to sleep to early in the boot process and this may lead |
| to kernel issues if the bootloader didn't prepare the slow clock and main |
| clock. |
| |
| This results in the following error and dump stack on the AriettaG25: |
| bad: scheduling from the idle thread! |
| |
| Ensure it is possible to sleep, else simply have a delay. |
| |
| Reported-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> |
| Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com> |
| Link: https://lkml.kernel.org/r/20190920153906.20887-1-alexandre.belloni@bootlin.com |
| Fixes: 80eded6ce8bb ("clk: at91: add slow clks driver") |
| Tested-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> |
| Signed-off-by: Stephen Boyd <sboyd@kernel.org> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/drivers/clk/at91/clk-main.c b/drivers/clk/at91/clk-main.c |
| index 311cea0c3ae2..54b2b2dd2bb5 100644 |
| --- a/drivers/clk/at91/clk-main.c |
| +++ b/drivers/clk/at91/clk-main.c |
| @@ -297,7 +297,10 @@ static int clk_main_probe_frequency(struct regmap *regmap) |
| regmap_read(regmap, AT91_CKGR_MCFR, &mcfr); |
| if (mcfr & AT91_PMC_MAINRDY) |
| return 0; |
| - usleep_range(MAINF_LOOP_MIN_WAIT, MAINF_LOOP_MAX_WAIT); |
| + if (system_state < SYSTEM_RUNNING) |
| + udelay(MAINF_LOOP_MIN_WAIT); |
| + else |
| + usleep_range(MAINF_LOOP_MIN_WAIT, MAINF_LOOP_MAX_WAIT); |
| } while (time_before(prep_time, timeout)); |
| |
| return -ETIMEDOUT; |
| diff --git a/drivers/clk/at91/sckc.c b/drivers/clk/at91/sckc.c |
| index 45526f56f1ba..155cad28af36 100644 |
| --- a/drivers/clk/at91/sckc.c |
| +++ b/drivers/clk/at91/sckc.c |
| @@ -69,7 +69,10 @@ static int clk_slow_osc_prepare(struct clk_hw *hw) |
| |
| writel(tmp | AT91_SCKC_OSC32EN, sckcr); |
| |
| - usleep_range(osc->startup_usec, osc->startup_usec + 1); |
| + if (system_state < SYSTEM_RUNNING) |
| + udelay(osc->startup_usec); |
| + else |
| + usleep_range(osc->startup_usec, osc->startup_usec + 1); |
| |
| return 0; |
| } |
| @@ -170,7 +173,10 @@ static int clk_slow_rc_osc_prepare(struct clk_hw *hw) |
| |
| writel(readl(sckcr) | AT91_SCKC_RCEN, sckcr); |
| |
| - usleep_range(osc->startup_usec, osc->startup_usec + 1); |
| + if (system_state < SYSTEM_RUNNING) |
| + udelay(osc->startup_usec); |
| + else |
| + usleep_range(osc->startup_usec, osc->startup_usec + 1); |
| |
| return 0; |
| } |
| @@ -261,7 +267,10 @@ static int clk_sam9x5_slow_set_parent(struct clk_hw *hw, u8 index) |
| |
| writel(tmp, sckcr); |
| |
| - usleep_range(SLOWCK_SW_TIME_USEC, SLOWCK_SW_TIME_USEC + 1); |
| + if (system_state < SYSTEM_RUNNING) |
| + udelay(SLOWCK_SW_TIME_USEC); |
| + else |
| + usleep_range(SLOWCK_SW_TIME_USEC, SLOWCK_SW_TIME_USEC + 1); |
| |
| return 0; |
| } |
| @@ -398,7 +407,10 @@ static int clk_sama5d4_slow_osc_prepare(struct clk_hw *hw) |
| return 0; |
| } |
| |
| - usleep_range(osc->startup_usec, osc->startup_usec + 1); |
| + if (system_state < SYSTEM_RUNNING) |
| + udelay(osc->startup_usec); |
| + else |
| + usleep_range(osc->startup_usec, osc->startup_usec + 1); |
| osc->prepared = true; |
| |
| return 0; |
| -- |
| 2.7.4 |
| |