2 * Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
11 #include <linux/clk-provider.h>
12 #include <linux/clkdev.h>
13 #include <linux/clk/at91_pmc.h>
14 #include <linux/interrupt.h>
15 #include <linux/irq.h>
17 #include <linux/of_address.h>
18 #include <linux/of_irq.h>
20 #include <linux/sched.h>
21 #include <linux/wait.h>
22 #include <linux/mfd/syscon.h>
23 #include <linux/regmap.h>
27 #define UTMI_FIXED_MUL 40
31 struct regmap *regmap;
33 wait_queue_head_t wait;
36 #define to_clk_utmi(hw) container_of(hw, struct clk_utmi, hw)
38 static irqreturn_t clk_utmi_irq_handler(int irq, void *dev_id)
40 struct clk_utmi *utmi = (struct clk_utmi *)dev_id;
43 disable_irq_nosync(utmi->irq);
48 static inline bool clk_utmi_ready(struct regmap *regmap)
52 regmap_read(regmap, AT91_PMC_SR, &status);
54 return status & AT91_PMC_LOCKU;
57 static int clk_utmi_prepare(struct clk_hw *hw)
59 struct clk_utmi *utmi = to_clk_utmi(hw);
60 unsigned int uckr = AT91_PMC_UPLLEN | AT91_PMC_UPLLCOUNT |
63 regmap_update_bits(utmi->regmap, AT91_CKGR_UCKR, uckr, uckr);
65 while (!clk_utmi_ready(utmi->regmap)) {
66 enable_irq(utmi->irq);
67 wait_event(utmi->wait,
68 clk_utmi_ready(utmi->regmap));
74 static int clk_utmi_is_prepared(struct clk_hw *hw)
76 struct clk_utmi *utmi = to_clk_utmi(hw);
78 return clk_utmi_ready(utmi->regmap);
81 static void clk_utmi_unprepare(struct clk_hw *hw)
83 struct clk_utmi *utmi = to_clk_utmi(hw);
85 regmap_update_bits(utmi->regmap, AT91_CKGR_UCKR, AT91_PMC_UPLLEN, 0);
88 static unsigned long clk_utmi_recalc_rate(struct clk_hw *hw,
89 unsigned long parent_rate)
91 /* UTMI clk is a fixed clk multiplier */
92 return parent_rate * UTMI_FIXED_MUL;
95 static const struct clk_ops utmi_ops = {
96 .prepare = clk_utmi_prepare,
97 .unprepare = clk_utmi_unprepare,
98 .is_prepared = clk_utmi_is_prepared,
99 .recalc_rate = clk_utmi_recalc_rate,
102 static struct clk * __init
103 at91_clk_register_utmi(struct regmap *regmap, unsigned int irq,
104 const char *name, const char *parent_name)
107 struct clk_utmi *utmi;
108 struct clk *clk = NULL;
109 struct clk_init_data init;
111 utmi = kzalloc(sizeof(*utmi), GFP_KERNEL);
113 return ERR_PTR(-ENOMEM);
116 init.ops = &utmi_ops;
117 init.parent_names = parent_name ? &parent_name : NULL;
118 init.num_parents = parent_name ? 1 : 0;
119 init.flags = CLK_SET_RATE_GATE;
121 utmi->hw.init = &init;
122 utmi->regmap = regmap;
124 init_waitqueue_head(&utmi->wait);
125 irq_set_status_flags(utmi->irq, IRQ_NOAUTOEN);
126 ret = request_irq(utmi->irq, clk_utmi_irq_handler,
127 IRQF_TRIGGER_HIGH, "clk-utmi", utmi);
133 clk = clk_register(NULL, &utmi->hw);
135 free_irq(utmi->irq, utmi);
142 static void __init of_at91sam9x5_clk_utmi_setup(struct device_node *np)
146 const char *parent_name;
147 const char *name = np->name;
148 struct regmap *regmap;
150 parent_name = of_clk_get_parent_name(np, 0);
152 of_property_read_string(np, "clock-output-names", &name);
154 irq = irq_of_parse_and_map(np, 0);
158 regmap = syscon_node_to_regmap(of_get_parent(np));
162 clk = at91_clk_register_utmi(regmap, irq, name, parent_name);
166 of_clk_add_provider(np, of_clk_src_simple_get, clk);
169 CLK_OF_DECLARE(at91sam9x5_clk_utmi, "atmel,at91sam9x5-clk-utmi",
170 of_at91sam9x5_clk_utmi_setup);