ARM: s3c64xx: bring back notes from removed debug-macro.S
[linux-2.6-microblaze.git] / drivers / clk / at91 / clk-utmi.c
index f1ef4e1..df9f3fc 100644 (file)
@@ -120,9 +120,11 @@ static const struct clk_ops utmi_ops = {
        .recalc_rate = clk_utmi_recalc_rate,
 };
 
-struct clk_hw * __init
-at91_clk_register_utmi(struct regmap *regmap_pmc, struct regmap *regmap_sfr,
-                      const char *name, const char *parent_name)
+static struct clk_hw * __init
+at91_clk_register_utmi_internal(struct regmap *regmap_pmc,
+                               struct regmap *regmap_sfr,
+                               const char *name, const char *parent_name,
+                               const struct clk_ops *ops, unsigned long flags)
 {
        struct clk_utmi *utmi;
        struct clk_hw *hw;
@@ -134,10 +136,10 @@ at91_clk_register_utmi(struct regmap *regmap_pmc, struct regmap *regmap_sfr,
                return ERR_PTR(-ENOMEM);
 
        init.name = name;
-       init.ops = &utmi_ops;
+       init.ops = ops;
        init.parent_names = parent_name ? &parent_name : NULL;
        init.num_parents = parent_name ? 1 : 0;
-       init.flags = CLK_SET_RATE_GATE;
+       init.flags = flags;
 
        utmi->hw.init = &init;
        utmi->regmap_pmc = regmap_pmc;
@@ -152,3 +154,94 @@ at91_clk_register_utmi(struct regmap *regmap_pmc, struct regmap *regmap_sfr,
 
        return hw;
 }
+
+struct clk_hw * __init
+at91_clk_register_utmi(struct regmap *regmap_pmc, struct regmap *regmap_sfr,
+                      const char *name, const char *parent_name)
+{
+       return at91_clk_register_utmi_internal(regmap_pmc, regmap_sfr, name,
+                       parent_name, &utmi_ops, CLK_SET_RATE_GATE);
+}
+
+static int clk_utmi_sama7g5_prepare(struct clk_hw *hw)
+{
+       struct clk_utmi *utmi = to_clk_utmi(hw);
+       struct clk_hw *hw_parent;
+       unsigned long parent_rate;
+       unsigned int val;
+
+       hw_parent = clk_hw_get_parent(hw);
+       parent_rate = clk_hw_get_rate(hw_parent);
+
+       switch (parent_rate) {
+       case 16000000:
+               val = 0;
+               break;
+       case 20000000:
+               val = 2;
+               break;
+       case 24000000:
+               val = 3;
+               break;
+       case 32000000:
+               val = 5;
+               break;
+       default:
+               pr_err("UTMICK: unsupported main_xtal rate\n");
+               return -EINVAL;
+       }
+
+       regmap_write(utmi->regmap_pmc, AT91_PMC_XTALF, val);
+
+       return 0;
+
+}
+
+static int clk_utmi_sama7g5_is_prepared(struct clk_hw *hw)
+{
+       struct clk_utmi *utmi = to_clk_utmi(hw);
+       struct clk_hw *hw_parent;
+       unsigned long parent_rate;
+       unsigned int val;
+
+       hw_parent = clk_hw_get_parent(hw);
+       parent_rate = clk_hw_get_rate(hw_parent);
+
+       regmap_read(utmi->regmap_pmc, AT91_PMC_XTALF, &val);
+       switch (val & 0x7) {
+       case 0:
+               if (parent_rate == 16000000)
+                       return 1;
+               break;
+       case 2:
+               if (parent_rate == 20000000)
+                       return 1;
+               break;
+       case 3:
+               if (parent_rate == 24000000)
+                       return 1;
+               break;
+       case 5:
+               if (parent_rate == 32000000)
+                       return 1;
+               break;
+       default:
+               break;
+       }
+
+       return 0;
+}
+
+static const struct clk_ops sama7g5_utmi_ops = {
+       .prepare = clk_utmi_sama7g5_prepare,
+       .is_prepared = clk_utmi_sama7g5_is_prepared,
+       .recalc_rate = clk_utmi_recalc_rate,
+};
+
+struct clk_hw * __init
+at91_clk_sama7g5_register_utmi(struct regmap *regmap_pmc, const char *name,
+                              const char *parent_name)
+{
+       return at91_clk_register_utmi_internal(regmap_pmc, NULL, name,
+                       parent_name, &sama7g5_utmi_ops, 0);
+}