These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / clk / at91 / clk-main.c
index 59fa3cc..4bfc94d 100644 (file)
 #include <linux/clk/at91_pmc.h>
 #include <linux/delay.h>
 #include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/of_irq.h>
-#include <linux/io.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/sched.h>
-#include <linux/wait.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
 
 #include "pmc.h"
 
 
 struct clk_main_osc {
        struct clk_hw hw;
-       struct at91_pmc *pmc;
-       unsigned int irq;
-       wait_queue_head_t wait;
+       struct regmap *regmap;
 };
 
 #define to_clk_main_osc(hw) container_of(hw, struct clk_main_osc, hw)
 
 struct clk_main_rc_osc {
        struct clk_hw hw;
-       struct at91_pmc *pmc;
-       unsigned int irq;
-       wait_queue_head_t wait;
+       struct regmap *regmap;
        unsigned long frequency;
        unsigned long accuracy;
 };
@@ -54,51 +45,47 @@ struct clk_main_rc_osc {
 
 struct clk_rm9200_main {
        struct clk_hw hw;
-       struct at91_pmc *pmc;
+       struct regmap *regmap;
 };
 
 #define to_clk_rm9200_main(hw) container_of(hw, struct clk_rm9200_main, hw)
 
 struct clk_sam9x5_main {
        struct clk_hw hw;
-       struct at91_pmc *pmc;
-       unsigned int irq;
-       wait_queue_head_t wait;
+       struct regmap *regmap;
        u8 parent;
 };
 
 #define to_clk_sam9x5_main(hw) container_of(hw, struct clk_sam9x5_main, hw)
 
-static irqreturn_t clk_main_osc_irq_handler(int irq, void *dev_id)
+static inline bool clk_main_osc_ready(struct regmap *regmap)
 {
-       struct clk_main_osc *osc = dev_id;
+       unsigned int status;
 
-       wake_up(&osc->wait);
-       disable_irq_nosync(osc->irq);
+       regmap_read(regmap, AT91_PMC_SR, &status);
 
-       return IRQ_HANDLED;
+       return status & AT91_PMC_MOSCS;
 }
 
 static int clk_main_osc_prepare(struct clk_hw *hw)
 {
        struct clk_main_osc *osc = to_clk_main_osc(hw);
-       struct at91_pmc *pmc = osc->pmc;
+       struct regmap *regmap = osc->regmap;
        u32 tmp;
 
-       tmp = pmc_read(pmc, AT91_CKGR_MOR) & ~MOR_KEY_MASK;
+       regmap_read(regmap, AT91_CKGR_MOR, &tmp);
+       tmp &= ~MOR_KEY_MASK;
+
        if (tmp & AT91_PMC_OSCBYPASS)
                return 0;
 
        if (!(tmp & AT91_PMC_MOSCEN)) {
                tmp |= AT91_PMC_MOSCEN | AT91_PMC_KEY;
-               pmc_write(pmc, AT91_CKGR_MOR, tmp);
+               regmap_write(regmap, AT91_CKGR_MOR, tmp);
        }
 
-       while (!(pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCS)) {
-               enable_irq(osc->irq);
-               wait_event(osc->wait,
-                          pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCS);
-       }
+       while (!clk_main_osc_ready(regmap))
+               cpu_relax();
 
        return 0;
 }
@@ -106,9 +93,10 @@ static int clk_main_osc_prepare(struct clk_hw *hw)
 static void clk_main_osc_unprepare(struct clk_hw *hw)
 {
        struct clk_main_osc *osc = to_clk_main_osc(hw);
-       struct at91_pmc *pmc = osc->pmc;
-       u32 tmp = pmc_read(pmc, AT91_CKGR_MOR);
+       struct regmap *regmap = osc->regmap;
+       u32 tmp;
 
+       regmap_read(regmap, AT91_CKGR_MOR, &tmp);
        if (tmp & AT91_PMC_OSCBYPASS)
                return;
 
@@ -116,20 +104,22 @@ static void clk_main_osc_unprepare(struct clk_hw *hw)
                return;
 
        tmp &= ~(AT91_PMC_KEY | AT91_PMC_MOSCEN);
-       pmc_write(pmc, AT91_CKGR_MOR, tmp | AT91_PMC_KEY);
+       regmap_write(regmap, AT91_CKGR_MOR, tmp | AT91_PMC_KEY);
 }
 
 static int clk_main_osc_is_prepared(struct clk_hw *hw)
 {
        struct clk_main_osc *osc = to_clk_main_osc(hw);
-       struct at91_pmc *pmc = osc->pmc;
-       u32 tmp = pmc_read(pmc, AT91_CKGR_MOR);
+       struct regmap *regmap = osc->regmap;
+       u32 tmp, status;
 
+       regmap_read(regmap, AT91_CKGR_MOR, &tmp);
        if (tmp & AT91_PMC_OSCBYPASS)
                return 1;
 
-       return !!((pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCS) &&
-                 (pmc_read(pmc, AT91_CKGR_MOR) & AT91_PMC_MOSCEN));
+       regmap_read(regmap, AT91_PMC_SR, &status);
+
+       return (status & AT91_PMC_MOSCS) && (tmp & AT91_PMC_MOSCEN);
 }
 
 static const struct clk_ops main_osc_ops = {
@@ -139,18 +129,16 @@ static const struct clk_ops main_osc_ops = {
 };
 
 static struct clk * __init
-at91_clk_register_main_osc(struct at91_pmc *pmc,
-                          unsigned int irq,
+at91_clk_register_main_osc(struct regmap *regmap,
                           const char *name,
                           const char *parent_name,
                           bool bypass)
 {
-       int ret;
        struct clk_main_osc *osc;
        struct clk *clk = NULL;
        struct clk_init_data init;
 
-       if (!pmc || !irq || !name || !parent_name)
+       if (!name || !parent_name)
                return ERR_PTR(-EINVAL);
 
        osc = kzalloc(sizeof(*osc), GFP_KERNEL);
@@ -164,83 +152,70 @@ at91_clk_register_main_osc(struct at91_pmc *pmc,
        init.flags = CLK_IGNORE_UNUSED;
 
        osc->hw.init = &init;
-       osc->pmc = pmc;
-       osc->irq = irq;
-
-       init_waitqueue_head(&osc->wait);
-       irq_set_status_flags(osc->irq, IRQ_NOAUTOEN);
-       ret = request_irq(osc->irq, clk_main_osc_irq_handler,
-                         IRQF_TRIGGER_HIGH, name, osc);
-       if (ret)
-               return ERR_PTR(ret);
+       osc->regmap = regmap;
 
        if (bypass)
-               pmc_write(pmc, AT91_CKGR_MOR,
-                         (pmc_read(pmc, AT91_CKGR_MOR) &
-                          ~(MOR_KEY_MASK | AT91_PMC_MOSCEN)) |
-                         AT91_PMC_OSCBYPASS | AT91_PMC_KEY);
+               regmap_update_bits(regmap,
+                                  AT91_CKGR_MOR, MOR_KEY_MASK |
+                                  AT91_PMC_MOSCEN,
+                                  AT91_PMC_OSCBYPASS | AT91_PMC_KEY);
 
        clk = clk_register(NULL, &osc->hw);
-       if (IS_ERR(clk)) {
-               free_irq(irq, osc);
+       if (IS_ERR(clk))
                kfree(osc);
-       }
 
        return clk;
 }
 
-void __init of_at91rm9200_clk_main_osc_setup(struct device_node *np,
-                                            struct at91_pmc *pmc)
+static void __init of_at91rm9200_clk_main_osc_setup(struct device_node *np)
 {
        struct clk *clk;
-       unsigned int irq;
        const char *name = np->name;
        const char *parent_name;
+       struct regmap *regmap;
        bool bypass;
 
        of_property_read_string(np, "clock-output-names", &name);
        bypass = of_property_read_bool(np, "atmel,osc-bypass");
        parent_name = of_clk_get_parent_name(np, 0);
 
-       irq = irq_of_parse_and_map(np, 0);
-       if (!irq)
+       regmap = syscon_node_to_regmap(of_get_parent(np));
+       if (IS_ERR(regmap))
                return;
 
-       clk = at91_clk_register_main_osc(pmc, irq, name, parent_name, bypass);
+       clk = at91_clk_register_main_osc(regmap, name, parent_name, bypass);
        if (IS_ERR(clk))
                return;
 
        of_clk_add_provider(np, of_clk_src_simple_get, clk);
 }
+CLK_OF_DECLARE(at91rm9200_clk_main_osc, "atmel,at91rm9200-clk-main-osc",
+              of_at91rm9200_clk_main_osc_setup);
 
-static irqreturn_t clk_main_rc_osc_irq_handler(int irq, void *dev_id)
+static bool clk_main_rc_osc_ready(struct regmap *regmap)
 {
-       struct clk_main_rc_osc *osc = dev_id;
+       unsigned int status;
 
-       wake_up(&osc->wait);
-       disable_irq_nosync(osc->irq);
+       regmap_read(regmap, AT91_PMC_SR, &status);
 
-       return IRQ_HANDLED;
+       return status & AT91_PMC_MOSCRCS;
 }
 
 static int clk_main_rc_osc_prepare(struct clk_hw *hw)
 {
        struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw);
-       struct at91_pmc *pmc = osc->pmc;
-       u32 tmp;
+       struct regmap *regmap = osc->regmap;
+       unsigned int mor;
 
-       tmp = pmc_read(pmc, AT91_CKGR_MOR) & ~MOR_KEY_MASK;
+       regmap_read(regmap, AT91_CKGR_MOR, &mor);
 
-       if (!(tmp & AT91_PMC_MOSCRCEN)) {
-               tmp |= AT91_PMC_MOSCRCEN | AT91_PMC_KEY;
-               pmc_write(pmc, AT91_CKGR_MOR, tmp);
-       }
+       if (!(mor & AT91_PMC_MOSCRCEN))
+               regmap_update_bits(regmap, AT91_CKGR_MOR,
+                                  MOR_KEY_MASK | AT91_PMC_MOSCRCEN,
+                                  AT91_PMC_MOSCRCEN | AT91_PMC_KEY);
 
-       while (!(pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCRCS)) {
-               enable_irq(osc->irq);
-               wait_event(osc->wait,
-                          pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCRCS);
-       }
+       while (!clk_main_rc_osc_ready(regmap))
+               cpu_relax();
 
        return 0;
 }
@@ -248,23 +223,28 @@ static int clk_main_rc_osc_prepare(struct clk_hw *hw)
 static void clk_main_rc_osc_unprepare(struct clk_hw *hw)
 {
        struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw);
-       struct at91_pmc *pmc = osc->pmc;
-       u32 tmp = pmc_read(pmc, AT91_CKGR_MOR);
+       struct regmap *regmap = osc->regmap;
+       unsigned int mor;
 
-       if (!(tmp & AT91_PMC_MOSCRCEN))
+       regmap_read(regmap, AT91_CKGR_MOR, &mor);
+
+       if (!(mor & AT91_PMC_MOSCRCEN))
                return;
 
-       tmp &= ~(MOR_KEY_MASK | AT91_PMC_MOSCRCEN);
-       pmc_write(pmc, AT91_CKGR_MOR, tmp | AT91_PMC_KEY);
+       regmap_update_bits(regmap, AT91_CKGR_MOR,
+                          MOR_KEY_MASK | AT91_PMC_MOSCRCEN, AT91_PMC_KEY);
 }
 
 static int clk_main_rc_osc_is_prepared(struct clk_hw *hw)
 {
        struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw);
-       struct at91_pmc *pmc = osc->pmc;
+       struct regmap *regmap = osc->regmap;
+       unsigned int mor, status;
+
+       regmap_read(regmap, AT91_CKGR_MOR, &mor);
+       regmap_read(regmap, AT91_PMC_SR, &status);
 
-       return !!((pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCRCS) &&
-                 (pmc_read(pmc, AT91_CKGR_MOR) & AT91_PMC_MOSCRCEN));
+       return (mor & AT91_PMC_MOSCRCEN) && (status & AT91_PMC_MOSCRCS);
 }
 
 static unsigned long clk_main_rc_osc_recalc_rate(struct clk_hw *hw,
@@ -292,17 +272,15 @@ static const struct clk_ops main_rc_osc_ops = {
 };
 
 static struct clk * __init
-at91_clk_register_main_rc_osc(struct at91_pmc *pmc,
-                             unsigned int irq,
+at91_clk_register_main_rc_osc(struct regmap *regmap,
                              const char *name,
                              u32 frequency, u32 accuracy)
 {
-       int ret;
        struct clk_main_rc_osc *osc;
        struct clk *clk = NULL;
        struct clk_init_data init;
 
-       if (!pmc || !irq || !name || !frequency)
+       if (!name || !frequency)
                return ERR_PTR(-EINVAL);
 
        osc = kzalloc(sizeof(*osc), GFP_KERNEL);
@@ -316,63 +294,53 @@ at91_clk_register_main_rc_osc(struct at91_pmc *pmc,
        init.flags = CLK_IS_ROOT | CLK_IGNORE_UNUSED;
 
        osc->hw.init = &init;
-       osc->pmc = pmc;
-       osc->irq = irq;
+       osc->regmap = regmap;
        osc->frequency = frequency;
        osc->accuracy = accuracy;
 
-       init_waitqueue_head(&osc->wait);
-       irq_set_status_flags(osc->irq, IRQ_NOAUTOEN);
-       ret = request_irq(osc->irq, clk_main_rc_osc_irq_handler,
-                         IRQF_TRIGGER_HIGH, name, osc);
-       if (ret)
-               return ERR_PTR(ret);
-
        clk = clk_register(NULL, &osc->hw);
-       if (IS_ERR(clk)) {
-               free_irq(irq, osc);
+       if (IS_ERR(clk))
                kfree(osc);
-       }
 
        return clk;
 }
 
-void __init of_at91sam9x5_clk_main_rc_osc_setup(struct device_node *np,
-                                               struct at91_pmc *pmc)
+static void __init of_at91sam9x5_clk_main_rc_osc_setup(struct device_node *np)
 {
        struct clk *clk;
-       unsigned int irq;
        u32 frequency = 0;
        u32 accuracy = 0;
        const char *name = np->name;
+       struct regmap *regmap;
 
        of_property_read_string(np, "clock-output-names", &name);
        of_property_read_u32(np, "clock-frequency", &frequency);
        of_property_read_u32(np, "clock-accuracy", &accuracy);
 
-       irq = irq_of_parse_and_map(np, 0);
-       if (!irq)
+       regmap = syscon_node_to_regmap(of_get_parent(np));
+       if (IS_ERR(regmap))
                return;
 
-       clk = at91_clk_register_main_rc_osc(pmc, irq, name, frequency,
-                                           accuracy);
+       clk = at91_clk_register_main_rc_osc(regmap, name, frequency, accuracy);
        if (IS_ERR(clk))
                return;
 
        of_clk_add_provider(np, of_clk_src_simple_get, clk);
 }
+CLK_OF_DECLARE(at91sam9x5_clk_main_rc_osc, "atmel,at91sam9x5-clk-main-rc-osc",
+              of_at91sam9x5_clk_main_rc_osc_setup);
 
 
-static int clk_main_probe_frequency(struct at91_pmc *pmc)
+static int clk_main_probe_frequency(struct regmap *regmap)
 {
        unsigned long prep_time, timeout;
-       u32 tmp;
+       unsigned int mcfr;
 
        timeout = jiffies + usecs_to_jiffies(MAINFRDY_TIMEOUT);
        do {
                prep_time = jiffies;
-               tmp = pmc_read(pmc, AT91_CKGR_MCFR);
-               if (tmp & AT91_PMC_MAINRDY)
+               regmap_read(regmap, AT91_CKGR_MCFR, &mcfr);
+               if (mcfr & AT91_PMC_MAINRDY)
                        return 0;
                usleep_range(MAINF_LOOP_MIN_WAIT, MAINF_LOOP_MAX_WAIT);
        } while (time_before(prep_time, timeout));
@@ -380,34 +348,37 @@ static int clk_main_probe_frequency(struct at91_pmc *pmc)
        return -ETIMEDOUT;
 }
 
-static unsigned long clk_main_recalc_rate(struct at91_pmc *pmc,
+static unsigned long clk_main_recalc_rate(struct regmap *regmap,
                                          unsigned long parent_rate)
 {
-       u32 tmp;
+       unsigned int mcfr;
 
        if (parent_rate)
                return parent_rate;
 
        pr_warn("Main crystal frequency not set, using approximate value\n");
-       tmp = pmc_read(pmc, AT91_CKGR_MCFR);
-       if (!(tmp & AT91_PMC_MAINRDY))
+       regmap_read(regmap, AT91_CKGR_MCFR, &mcfr);
+       if (!(mcfr & AT91_PMC_MAINRDY))
                return 0;
 
-       return ((tmp & AT91_PMC_MAINF) * SLOW_CLOCK_FREQ) / MAINF_DIV;
+       return ((mcfr & AT91_PMC_MAINF) * SLOW_CLOCK_FREQ) / MAINF_DIV;
 }
 
 static int clk_rm9200_main_prepare(struct clk_hw *hw)
 {
        struct clk_rm9200_main *clkmain = to_clk_rm9200_main(hw);
 
-       return clk_main_probe_frequency(clkmain->pmc);
+       return clk_main_probe_frequency(clkmain->regmap);
 }
 
 static int clk_rm9200_main_is_prepared(struct clk_hw *hw)
 {
        struct clk_rm9200_main *clkmain = to_clk_rm9200_main(hw);
+       unsigned int status;
 
-       return !!(pmc_read(clkmain->pmc, AT91_CKGR_MCFR) & AT91_PMC_MAINRDY);
+       regmap_read(clkmain->regmap, AT91_CKGR_MCFR, &status);
+
+       return status & AT91_PMC_MAINRDY ? 1 : 0;
 }
 
 static unsigned long clk_rm9200_main_recalc_rate(struct clk_hw *hw,
@@ -415,7 +386,7 @@ static unsigned long clk_rm9200_main_recalc_rate(struct clk_hw *hw,
 {
        struct clk_rm9200_main *clkmain = to_clk_rm9200_main(hw);
 
-       return clk_main_recalc_rate(clkmain->pmc, parent_rate);
+       return clk_main_recalc_rate(clkmain->regmap, parent_rate);
 }
 
 static const struct clk_ops rm9200_main_ops = {
@@ -425,7 +396,7 @@ static const struct clk_ops rm9200_main_ops = {
 };
 
 static struct clk * __init
-at91_clk_register_rm9200_main(struct at91_pmc *pmc,
+at91_clk_register_rm9200_main(struct regmap *regmap,
                              const char *name,
                              const char *parent_name)
 {
@@ -433,7 +404,7 @@ at91_clk_register_rm9200_main(struct at91_pmc *pmc,
        struct clk *clk = NULL;
        struct clk_init_data init;
 
-       if (!pmc || !name)
+       if (!name)
                return ERR_PTR(-EINVAL);
 
        if (!parent_name)
@@ -450,7 +421,7 @@ at91_clk_register_rm9200_main(struct at91_pmc *pmc,
        init.flags = 0;
 
        clkmain->hw.init = &init;
-       clkmain->pmc = pmc;
+       clkmain->regmap = regmap;
 
        clk = clk_register(NULL, &clkmain->hw);
        if (IS_ERR(clk))
@@ -459,52 +430,54 @@ at91_clk_register_rm9200_main(struct at91_pmc *pmc,
        return clk;
 }
 
-void __init of_at91rm9200_clk_main_setup(struct device_node *np,
-                                        struct at91_pmc *pmc)
+static void __init of_at91rm9200_clk_main_setup(struct device_node *np)
 {
        struct clk *clk;
        const char *parent_name;
        const char *name = np->name;
+       struct regmap *regmap;
 
        parent_name = of_clk_get_parent_name(np, 0);
        of_property_read_string(np, "clock-output-names", &name);
 
-       clk = at91_clk_register_rm9200_main(pmc, name, parent_name);
+       regmap = syscon_node_to_regmap(of_get_parent(np));
+       if (IS_ERR(regmap))
+               return;
+
+       clk = at91_clk_register_rm9200_main(regmap, name, parent_name);
        if (IS_ERR(clk))
                return;
 
        of_clk_add_provider(np, of_clk_src_simple_get, clk);
 }
+CLK_OF_DECLARE(at91rm9200_clk_main, "atmel,at91rm9200-clk-main",
+              of_at91rm9200_clk_main_setup);
 
-static irqreturn_t clk_sam9x5_main_irq_handler(int irq, void *dev_id)
+static inline bool clk_sam9x5_main_ready(struct regmap *regmap)
 {
-       struct clk_sam9x5_main *clkmain = dev_id;
+       unsigned int status;
 
-       wake_up(&clkmain->wait);
-       disable_irq_nosync(clkmain->irq);
+       regmap_read(regmap, AT91_PMC_SR, &status);
 
-       return IRQ_HANDLED;
+       return status & AT91_PMC_MOSCSELS ? 1 : 0;
 }
 
 static int clk_sam9x5_main_prepare(struct clk_hw *hw)
 {
        struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw);
-       struct at91_pmc *pmc = clkmain->pmc;
+       struct regmap *regmap = clkmain->regmap;
 
-       while (!(pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCSELS)) {
-               enable_irq(clkmain->irq);
-               wait_event(clkmain->wait,
-                          pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCSELS);
-       }
+       while (!clk_sam9x5_main_ready(regmap))
+               cpu_relax();
 
-       return clk_main_probe_frequency(pmc);
+       return clk_main_probe_frequency(regmap);
 }
 
 static int clk_sam9x5_main_is_prepared(struct clk_hw *hw)
 {
        struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw);
 
-       return !!(pmc_read(clkmain->pmc, AT91_PMC_SR) & AT91_PMC_MOSCSELS);
+       return clk_sam9x5_main_ready(clkmain->regmap);
 }
 
 static unsigned long clk_sam9x5_main_recalc_rate(struct clk_hw *hw,
@@ -512,30 +485,28 @@ static unsigned long clk_sam9x5_main_recalc_rate(struct clk_hw *hw,
 {
        struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw);
 
-       return clk_main_recalc_rate(clkmain->pmc, parent_rate);
+       return clk_main_recalc_rate(clkmain->regmap, parent_rate);
 }
 
 static int clk_sam9x5_main_set_parent(struct clk_hw *hw, u8 index)
 {
        struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw);
-       struct at91_pmc *pmc = clkmain->pmc;
-       u32 tmp;
+       struct regmap *regmap = clkmain->regmap;
+       unsigned int tmp;
 
        if (index > 1)
                return -EINVAL;
 
-       tmp = pmc_read(pmc, AT91_CKGR_MOR) & ~MOR_KEY_MASK;
+       regmap_read(regmap, AT91_CKGR_MOR, &tmp);
+       tmp &= ~MOR_KEY_MASK;
 
        if (index && !(tmp & AT91_PMC_MOSCSEL))
-               pmc_write(pmc, AT91_CKGR_MOR, tmp | AT91_PMC_MOSCSEL);
+               regmap_write(regmap, AT91_CKGR_MOR, tmp | AT91_PMC_MOSCSEL);
        else if (!index && (tmp & AT91_PMC_MOSCSEL))
-               pmc_write(pmc, AT91_CKGR_MOR, tmp & ~AT91_PMC_MOSCSEL);
+               regmap_write(regmap, AT91_CKGR_MOR, tmp & ~AT91_PMC_MOSCSEL);
 
-       while (!(pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCSELS)) {
-               enable_irq(clkmain->irq);
-               wait_event(clkmain->wait,
-                          pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCSELS);
-       }
+       while (!clk_sam9x5_main_ready(regmap))
+               cpu_relax();
 
        return 0;
 }
@@ -543,8 +514,11 @@ static int clk_sam9x5_main_set_parent(struct clk_hw *hw, u8 index)
 static u8 clk_sam9x5_main_get_parent(struct clk_hw *hw)
 {
        struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw);
+       unsigned int status;
 
-       return !!(pmc_read(clkmain->pmc, AT91_CKGR_MOR) & AT91_PMC_MOSCEN);
+       regmap_read(clkmain->regmap, AT91_CKGR_MOR, &status);
+
+       return status & AT91_PMC_MOSCEN ? 1 : 0;
 }
 
 static const struct clk_ops sam9x5_main_ops = {
@@ -556,18 +530,17 @@ static const struct clk_ops sam9x5_main_ops = {
 };
 
 static struct clk * __init
-at91_clk_register_sam9x5_main(struct at91_pmc *pmc,
-                             unsigned int irq,
+at91_clk_register_sam9x5_main(struct regmap *regmap,
                              const char *name,
                              const char **parent_names,
                              int num_parents)
 {
-       int ret;
        struct clk_sam9x5_main *clkmain;
        struct clk *clk = NULL;
        struct clk_init_data init;
+       unsigned int status;
 
-       if (!pmc || !irq || !name)
+       if (!name)
                return ERR_PTR(-EINVAL);
 
        if (!parent_names || !num_parents)
@@ -584,56 +557,42 @@ at91_clk_register_sam9x5_main(struct at91_pmc *pmc,
        init.flags = CLK_SET_PARENT_GATE;
 
        clkmain->hw.init = &init;
-       clkmain->pmc = pmc;
-       clkmain->irq = irq;
-       clkmain->parent = !!(pmc_read(clkmain->pmc, AT91_CKGR_MOR) &
-                            AT91_PMC_MOSCEN);
-       init_waitqueue_head(&clkmain->wait);
-       irq_set_status_flags(clkmain->irq, IRQ_NOAUTOEN);
-       ret = request_irq(clkmain->irq, clk_sam9x5_main_irq_handler,
-                         IRQF_TRIGGER_HIGH, name, clkmain);
-       if (ret)
-               return ERR_PTR(ret);
+       clkmain->regmap = regmap;
+       regmap_read(clkmain->regmap, AT91_CKGR_MOR, &status);
+       clkmain->parent = status & AT91_PMC_MOSCEN ? 1 : 0;
 
        clk = clk_register(NULL, &clkmain->hw);
-       if (IS_ERR(clk)) {
-               free_irq(clkmain->irq, clkmain);
+       if (IS_ERR(clk))
                kfree(clkmain);
-       }
 
        return clk;
 }
 
-void __init of_at91sam9x5_clk_main_setup(struct device_node *np,
-                                        struct at91_pmc *pmc)
+static void __init of_at91sam9x5_clk_main_setup(struct device_node *np)
 {
        struct clk *clk;
        const char *parent_names[2];
        int num_parents;
-       unsigned int irq;
        const char *name = np->name;
-       int i;
+       struct regmap *regmap;
 
-       num_parents = of_count_phandle_with_args(np, "clocks", "#clock-cells");
+       num_parents = of_clk_get_parent_count(np);
        if (num_parents <= 0 || num_parents > 2)
                return;
 
-       for (i = 0; i < num_parents; ++i) {
-               parent_names[i] = of_clk_get_parent_name(np, i);
-               if (!parent_names[i])
-                       return;
-       }
+       of_clk_parent_fill(np, parent_names, num_parents);
+       regmap = syscon_node_to_regmap(of_get_parent(np));
+       if (IS_ERR(regmap))
+               return;
 
        of_property_read_string(np, "clock-output-names", &name);
 
-       irq = irq_of_parse_and_map(np, 0);
-       if (!irq)
-               return;
-
-       clk = at91_clk_register_sam9x5_main(pmc, irq, name, parent_names,
+       clk = at91_clk_register_sam9x5_main(regmap, name, parent_names,
                                            num_parents);
        if (IS_ERR(clk))
                return;
 
        of_clk_add_provider(np, of_clk_src_simple_get, clk);
 }
+CLK_OF_DECLARE(at91sam9x5_clk_main, "atmel,at91sam9x5-clk-main",
+              of_at91sam9x5_clk_main_setup);