diff options
author | Alexandre Belloni <alexandre.belloni@free-electrons.com> | 2015-09-17 00:47:39 +0300 |
---|---|---|
committer | Alexandre Belloni <alexandre.belloni@free-electrons.com> | 2016-02-17 19:52:59 +0300 |
commit | 99a81706526fb167029a940ef1f7bfbe882abd3e (patch) | |
tree | f35afa9e90b6a0825bf3f527160482fda286e91c /drivers/clk/at91/clk-utmi.c | |
parent | 1bdf02326b71eae7e9b4b335b881856aaf9d1af6 (diff) | |
download | linux-99a81706526fb167029a940ef1f7bfbe882abd3e.tar.xz |
clk: at91: remove IRQ handling and use polling
The AT91 clock drivers make use of IRQs to avoid polling when waiting for
some clocks to be enabled. Unfortunately, this leads to a crash when those
IRQs are threaded (which happens when using preempt-rt) because they are
registered before thread creation is possible.
Use polling on those clocks instead to avoid the problem.
Acked-by: Stephen Boyd <sboyd@codeaurora.org>
Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
Diffstat (limited to 'drivers/clk/at91/clk-utmi.c')
-rw-r--r-- | drivers/clk/at91/clk-utmi.c | 49 |
1 files changed, 5 insertions, 44 deletions
diff --git a/drivers/clk/at91/clk-utmi.c b/drivers/clk/at91/clk-utmi.c index 58a310e5768c..61fcf399e58c 100644 --- a/drivers/clk/at91/clk-utmi.c +++ b/drivers/clk/at91/clk-utmi.c @@ -11,14 +11,7 @@ #include <linux/clk-provider.h> #include <linux/clkdev.h> #include <linux/clk/at91_pmc.h> -#include <linux/interrupt.h> -#include <linux/irq.h> #include <linux/of.h> -#include <linux/of_address.h> -#include <linux/of_irq.h> -#include <linux/io.h> -#include <linux/sched.h> -#include <linux/wait.h> #include <linux/mfd/syscon.h> #include <linux/regmap.h> @@ -29,22 +22,10 @@ struct clk_utmi { struct clk_hw hw; struct regmap *regmap; - unsigned int irq; - wait_queue_head_t wait; }; #define to_clk_utmi(hw) container_of(hw, struct clk_utmi, hw) -static irqreturn_t clk_utmi_irq_handler(int irq, void *dev_id) -{ - struct clk_utmi *utmi = (struct clk_utmi *)dev_id; - - wake_up(&utmi->wait); - disable_irq_nosync(utmi->irq); - - return IRQ_HANDLED; -} - static inline bool clk_utmi_ready(struct regmap *regmap) { unsigned int status; @@ -62,11 +43,8 @@ static int clk_utmi_prepare(struct clk_hw *hw) regmap_update_bits(utmi->regmap, AT91_CKGR_UCKR, uckr, uckr); - while (!clk_utmi_ready(utmi->regmap)) { - enable_irq(utmi->irq); - wait_event(utmi->wait, - clk_utmi_ready(utmi->regmap)); - } + while (!clk_utmi_ready(utmi->regmap)) + cpu_relax(); return 0; } @@ -100,10 +78,9 @@ static const struct clk_ops utmi_ops = { }; static struct clk * __init -at91_clk_register_utmi(struct regmap *regmap, unsigned int irq, +at91_clk_register_utmi(struct regmap *regmap, const char *name, const char *parent_name) { - int ret; struct clk_utmi *utmi; struct clk *clk = NULL; struct clk_init_data init; @@ -120,28 +97,16 @@ at91_clk_register_utmi(struct regmap *regmap, unsigned int irq, utmi->hw.init = &init; utmi->regmap = regmap; - utmi->irq = irq; - init_waitqueue_head(&utmi->wait); - irq_set_status_flags(utmi->irq, IRQ_NOAUTOEN); - ret = request_irq(utmi->irq, clk_utmi_irq_handler, - IRQF_TRIGGER_HIGH, "clk-utmi", utmi); - if (ret) { - kfree(utmi); - return ERR_PTR(ret); - } clk = clk_register(NULL, &utmi->hw); - if (IS_ERR(clk)) { - free_irq(utmi->irq, utmi); + if (IS_ERR(clk)) kfree(utmi); - } return clk; } static void __init of_at91sam9x5_clk_utmi_setup(struct device_node *np) { - unsigned int irq; struct clk *clk; const char *parent_name; const char *name = np->name; @@ -151,15 +116,11 @@ static void __init of_at91sam9x5_clk_utmi_setup(struct device_node *np) of_property_read_string(np, "clock-output-names", &name); - irq = irq_of_parse_and_map(np, 0); - if (!irq) - return; - regmap = syscon_node_to_regmap(of_get_parent(np)); if (IS_ERR(regmap)) return; - clk = at91_clk_register_utmi(regmap, irq, name, parent_name); + clk = at91_clk_register_utmi(regmap, name, parent_name); if (IS_ERR(clk)) return; |