These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / clk / at91 / clk-system.c
index a76d03f..8f35d81 100644 (file)
 #include <linux/clkdev.h>
 #include <linux/clk/at91_pmc.h>
 #include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/io.h>
-#include <linux/irq.h>
-#include <linux/of_irq.h>
-#include <linux/interrupt.h>
-#include <linux/wait.h>
-#include <linux/sched.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
 
 #include "pmc.h"
 
@@ -29,9 +24,7 @@
 #define to_clk_system(hw) container_of(hw, struct clk_system, hw)
 struct clk_system {
        struct clk_hw hw;
-       struct at91_pmc *pmc;
-       unsigned int irq;
-       wait_queue_head_t wait;
+       struct regmap *regmap;
        u8 id;
 };
 
@@ -39,58 +32,54 @@ static inline int is_pck(int id)
 {
        return (id >= 8) && (id <= 15);
 }
-static irqreturn_t clk_system_irq_handler(int irq, void *dev_id)
+
+static inline bool clk_system_ready(struct regmap *regmap, int id)
 {
-       struct clk_system *sys = (struct clk_system *)dev_id;
+       unsigned int status;
 
-       wake_up(&sys->wait);
-       disable_irq_nosync(sys->irq);
+       regmap_read(regmap, AT91_PMC_SR, &status);
 
-       return IRQ_HANDLED;
+       return status & (1 << id) ? 1 : 0;
 }
 
 static int clk_system_prepare(struct clk_hw *hw)
 {
        struct clk_system *sys = to_clk_system(hw);
-       struct at91_pmc *pmc = sys->pmc;
-       u32 mask = 1 << sys->id;
 
-       pmc_write(pmc, AT91_PMC_SCER, mask);
+       regmap_write(sys->regmap, AT91_PMC_SCER, 1 << sys->id);
 
        if (!is_pck(sys->id))
                return 0;
 
-       while (!(pmc_read(pmc, AT91_PMC_SR) & mask)) {
-               if (sys->irq) {
-                       enable_irq(sys->irq);
-                       wait_event(sys->wait,
-                                  pmc_read(pmc, AT91_PMC_SR) & mask);
-               } else
-                       cpu_relax();
-       }
+       while (!clk_system_ready(sys->regmap, sys->id))
+               cpu_relax();
+
        return 0;
 }
 
 static void clk_system_unprepare(struct clk_hw *hw)
 {
        struct clk_system *sys = to_clk_system(hw);
-       struct at91_pmc *pmc = sys->pmc;
 
-       pmc_write(pmc, AT91_PMC_SCDR, 1 << sys->id);
+       regmap_write(sys->regmap, AT91_PMC_SCDR, 1 << sys->id);
 }
 
 static int clk_system_is_prepared(struct clk_hw *hw)
 {
        struct clk_system *sys = to_clk_system(hw);
-       struct at91_pmc *pmc = sys->pmc;
+       unsigned int status;
 
-       if (!(pmc_read(pmc, AT91_PMC_SCSR) & (1 << sys->id)))
+       regmap_read(sys->regmap, AT91_PMC_SCSR, &status);
+
+       if (!(status & (1 << sys->id)))
                return 0;
 
        if (!is_pck(sys->id))
                return 1;
 
-       return !!(pmc_read(pmc, AT91_PMC_SR) & (1 << sys->id));
+       regmap_read(sys->regmap, AT91_PMC_SR, &status);
+
+       return status & (1 << sys->id) ? 1 : 0;
 }
 
 static const struct clk_ops system_ops = {
@@ -100,13 +89,12 @@ static const struct clk_ops system_ops = {
 };
 
 static struct clk * __init
-at91_clk_register_system(struct at91_pmc *pmc, const char *name,
-                        const char *parent_name, u8 id, int irq)
+at91_clk_register_system(struct regmap *regmap, const char *name,
+                        const char *parent_name, u8 id)
 {
        struct clk_system *sys;
        struct clk *clk = NULL;
        struct clk_init_data init;
-       int ret;
 
        if (!parent_name || id > SYSTEM_MAX_ID)
                return ERR_PTR(-EINVAL);
@@ -123,16 +111,7 @@ at91_clk_register_system(struct at91_pmc *pmc, const char *name,
 
        sys->id = id;
        sys->hw.init = &init;
-       sys->pmc = pmc;
-       sys->irq = irq;
-       if (irq) {
-               init_waitqueue_head(&sys->wait);
-               irq_set_status_flags(sys->irq, IRQ_NOAUTOEN);
-               ret = request_irq(sys->irq, clk_system_irq_handler,
-                               IRQF_TRIGGER_HIGH, name, sys);
-               if (ret)
-                       return ERR_PTR(ret);
-       }
+       sys->regmap = regmap;
 
        clk = clk_register(NULL, &sys->hw);
        if (IS_ERR(clk))
@@ -141,21 +120,24 @@ at91_clk_register_system(struct at91_pmc *pmc, const char *name,
        return clk;
 }
 
-static void __init
-of_at91_clk_sys_setup(struct device_node *np, struct at91_pmc *pmc)
+static void __init of_at91rm9200_clk_sys_setup(struct device_node *np)
 {
        int num;
-       int irq = 0;
        u32 id;
        struct clk *clk;
        const char *name;
        struct device_node *sysclknp;
        const char *parent_name;
+       struct regmap *regmap;
 
        num = of_get_child_count(np);
        if (num > (SYSTEM_MAX_ID + 1))
                return;
 
+       regmap = syscon_node_to_regmap(of_get_parent(np));
+       if (IS_ERR(regmap))
+               return;
+
        for_each_child_of_node(np, sysclknp) {
                if (of_property_read_u32(sysclknp, "reg", &id))
                        continue;
@@ -163,21 +145,14 @@ of_at91_clk_sys_setup(struct device_node *np, struct at91_pmc *pmc)
                if (of_property_read_string(np, "clock-output-names", &name))
                        name = sysclknp->name;
 
-               if (is_pck(id))
-                       irq = irq_of_parse_and_map(sysclknp, 0);
-
                parent_name = of_clk_get_parent_name(sysclknp, 0);
 
-               clk = at91_clk_register_system(pmc, name, parent_name, id, irq);
+               clk = at91_clk_register_system(regmap, name, parent_name, id);
                if (IS_ERR(clk))
                        continue;
 
                of_clk_add_provider(sysclknp, of_clk_src_simple_get, clk);
        }
 }
-
-void __init of_at91rm9200_clk_sys_setup(struct device_node *np,
-                                       struct at91_pmc *pmc)
-{
-       of_at91_clk_sys_setup(np, pmc);
-}
+CLK_OF_DECLARE(at91rm9200_clk_sys, "atmel,at91rm9200-clk-system",
+              of_at91rm9200_clk_sys_setup);