aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMike Turquette <mturquette@linaro.org>2012-03-16 02:11:20 -0400
committerArnd Bergmann <arnd@arndb.de>2012-03-16 16:35:02 -0400
commit9d9f78ed9af0e465d2fd15550471956e7f559b9f (patch)
tree8a65fc0844a35c928162f65b671a8a5786ea03ee
parentb2476490ef11134b65544d8f062cff96c53e941b (diff)
clk: basic clock hardware types
Many platforms support simple gateable clocks, fixed-rate clocks, adjustable divider clocks and multi-parent multiplexer clocks. This patch introduces basic clock types for the above-mentioned hardware which share some common characteristics. Based on original work by Jeremy Kerr and contribution by Jamie Iles. Dividers and multiplexor clocks originally contributed by Richard Zhao & Sascha Hauer. Signed-off-by: Mike Turquette <mturquette@linaro.org> Signed-off-by: Mike Turquette <mturquette@ti.com> Reviewed-by: Andrew Lunn <andrew@lunn.ch> Tested-by: Andrew Lunn <andrew@lunn.ch> Reviewed-by: Rob Herring <rob.herring@calxeda.com> Cc: Russell King <linux@arm.linux.org.uk> Cc: Jeremy Kerr <jeremy.kerr@canonical.com> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Arnd Bergman <arnd.bergmann@linaro.org> Cc: Paul Walmsley <paul@pwsan.com> Cc: Shawn Guo <shawn.guo@freescale.com> Cc: Sascha Hauer <s.hauer@pengutronix.de> Cc: Jamie Iles <jamie@jamieiles.com> Cc: Richard Zhao <richard.zhao@linaro.org> Cc: Saravana Kannan <skannan@codeaurora.org> Cc: Magnus Damm <magnus.damm@gmail.com> Cc: Mark Brown <broonie@opensource.wolfsonmicro.com> Cc: Linus Walleij <linus.walleij@stericsson.com> Cc: Stephen Boyd <sboyd@codeaurora.org> Cc: Amit Kucheria <amit.kucheria@linaro.org> Cc: Deepak Saxena <dsaxena@linaro.org> Cc: Grant Likely <grant.likely@secretlab.ca> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
-rw-r--r--drivers/clk/Makefile3
-rw-r--r--drivers/clk/clk-divider.c200
-rw-r--r--drivers/clk/clk-fixed-rate.c82
-rw-r--r--drivers/clk/clk-gate.c150
-rw-r--r--drivers/clk/clk-mux.c116
-rw-r--r--include/linux/clk-private.h124
-rw-r--r--include/linux/clk-provider.h127
7 files changed, 801 insertions, 1 deletions
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index ff362c4fb4c3..1f736bc11c4b 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -1,3 +1,4 @@
1 1
2obj-$(CONFIG_CLKDEV_LOOKUP) += clkdev.o 2obj-$(CONFIG_CLKDEV_LOOKUP) += clkdev.o
3obj-$(CONFIG_COMMON_CLK) += clk.o 3obj-$(CONFIG_COMMON_CLK) += clk.o clk-fixed-rate.o clk-gate.o \
4 clk-mux.o clk-divider.o
diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
new file mode 100644
index 000000000000..d5ac6a75ea57
--- /dev/null
+++ b/drivers/clk/clk-divider.c
@@ -0,0 +1,200 @@
1/*
2 * Copyright (C) 2011 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de>
3 * Copyright (C) 2011 Richard Zhao, Linaro <richard.zhao@linaro.org>
4 * Copyright (C) 2011-2012 Mike Turquette, Linaro Ltd <mturquette@linaro.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * Adjustable divider clock implementation
11 */
12
13#include <linux/clk-provider.h>
14#include <linux/module.h>
15#include <linux/slab.h>
16#include <linux/io.h>
17#include <linux/err.h>
18#include <linux/string.h>
19
20/*
21 * DOC: basic adjustable divider clock that cannot gate
22 *
23 * Traits of this clock:
24 * prepare - clk_prepare only ensures that parents are prepared
25 * enable - clk_enable only ensures that parents are enabled
26 * rate - rate is adjustable. clk->rate = parent->rate / divisor
27 * parent - fixed parent. No clk_set_parent support
28 */
29
30#define to_clk_divider(_hw) container_of(_hw, struct clk_divider, hw)
31
32#define div_mask(d) ((1 << (d->width)) - 1)
33
34static unsigned long clk_divider_recalc_rate(struct clk_hw *hw,
35 unsigned long parent_rate)
36{
37 struct clk_divider *divider = to_clk_divider(hw);
38 unsigned int div;
39
40 div = readl(divider->reg) >> divider->shift;
41 div &= div_mask(divider);
42
43 if (!(divider->flags & CLK_DIVIDER_ONE_BASED))
44 div++;
45
46 return parent_rate / div;
47}
48EXPORT_SYMBOL_GPL(clk_divider_recalc_rate);
49
50/*
51 * The reverse of DIV_ROUND_UP: The maximum number which
52 * divided by m is r
53 */
54#define MULT_ROUND_UP(r, m) ((r) * (m) + (m) - 1)
55
56static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate,
57 unsigned long *best_parent_rate)
58{
59 struct clk_divider *divider = to_clk_divider(hw);
60 int i, bestdiv = 0;
61 unsigned long parent_rate, best = 0, now, maxdiv;
62
63 if (!rate)
64 rate = 1;
65
66 maxdiv = (1 << divider->width);
67
68 if (divider->flags & CLK_DIVIDER_ONE_BASED)
69 maxdiv--;
70
71 if (!best_parent_rate) {
72 parent_rate = __clk_get_rate(__clk_get_parent(hw->clk));
73 bestdiv = DIV_ROUND_UP(parent_rate, rate);
74 bestdiv = bestdiv == 0 ? 1 : bestdiv;
75 bestdiv = bestdiv > maxdiv ? maxdiv : bestdiv;
76 return bestdiv;
77 }
78
79 /*
80 * The maximum divider we can use without overflowing
81 * unsigned long in rate * i below
82 */
83 maxdiv = min(ULONG_MAX / rate, maxdiv);
84
85 for (i = 1; i <= maxdiv; i++) {
86 parent_rate = __clk_round_rate(__clk_get_parent(hw->clk),
87 MULT_ROUND_UP(rate, i));
88 now = parent_rate / i;
89 if (now <= rate && now > best) {
90 bestdiv = i;
91 best = now;
92 *best_parent_rate = parent_rate;
93 }
94 }
95
96 if (!bestdiv) {
97 bestdiv = (1 << divider->width);
98 if (divider->flags & CLK_DIVIDER_ONE_BASED)
99 bestdiv--;
100 *best_parent_rate = __clk_round_rate(__clk_get_parent(hw->clk), 1);
101 }
102
103 return bestdiv;
104}
105
106static long clk_divider_round_rate(struct clk_hw *hw, unsigned long rate,
107 unsigned long *prate)
108{
109 int div;
110 div = clk_divider_bestdiv(hw, rate, prate);
111
112 if (prate)
113 return *prate / div;
114 else {
115 unsigned long r;
116 r = __clk_get_rate(__clk_get_parent(hw->clk));
117 return r / div;
118 }
119}
120EXPORT_SYMBOL_GPL(clk_divider_round_rate);
121
122static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate)
123{
124 struct clk_divider *divider = to_clk_divider(hw);
125 unsigned int div;
126 unsigned long flags = 0;
127 u32 val;
128
129 div = __clk_get_rate(__clk_get_parent(hw->clk)) / rate;
130
131 if (!(divider->flags & CLK_DIVIDER_ONE_BASED))
132 div--;
133
134 if (div > div_mask(divider))
135 div = div_mask(divider);
136
137 if (divider->lock)
138 spin_lock_irqsave(divider->lock, flags);
139
140 val = readl(divider->reg);
141 val &= ~(div_mask(divider) << divider->shift);
142 val |= div << divider->shift;
143 writel(val, divider->reg);
144
145 if (divider->lock)
146 spin_unlock_irqrestore(divider->lock, flags);
147
148 return 0;
149}
150EXPORT_SYMBOL_GPL(clk_divider_set_rate);
151
152struct clk_ops clk_divider_ops = {
153 .recalc_rate = clk_divider_recalc_rate,
154 .round_rate = clk_divider_round_rate,
155 .set_rate = clk_divider_set_rate,
156};
157EXPORT_SYMBOL_GPL(clk_divider_ops);
158
159struct clk *clk_register_divider(struct device *dev, const char *name,
160 const char *parent_name, unsigned long flags,
161 void __iomem *reg, u8 shift, u8 width,
162 u8 clk_divider_flags, spinlock_t *lock)
163{
164 struct clk_divider *div;
165 struct clk *clk;
166
167 div = kzalloc(sizeof(struct clk_divider), GFP_KERNEL);
168
169 if (!div) {
170 pr_err("%s: could not allocate divider clk\n", __func__);
171 return NULL;
172 }
173
174 /* struct clk_divider assignments */
175 div->reg = reg;
176 div->shift = shift;
177 div->width = width;
178 div->flags = clk_divider_flags;
179 div->lock = lock;
180
181 if (parent_name) {
182 div->parent[0] = kstrdup(parent_name, GFP_KERNEL);
183 if (!div->parent[0])
184 goto out;
185 }
186
187 clk = clk_register(dev, name,
188 &clk_divider_ops, &div->hw,
189 div->parent,
190 (parent_name ? 1 : 0),
191 flags);
192 if (clk)
193 return clk;
194
195out:
196 kfree(div->parent[0]);
197 kfree(div);
198
199 return NULL;
200}
diff --git a/drivers/clk/clk-fixed-rate.c b/drivers/clk/clk-fixed-rate.c
new file mode 100644
index 000000000000..90c79fb5d1bd
--- /dev/null
+++ b/drivers/clk/clk-fixed-rate.c
@@ -0,0 +1,82 @@
1/*
2 * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
3 * Copyright (C) 2011-2012 Mike Turquette, Linaro Ltd <mturquette@linaro.org>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 *
9 * Fixed rate clock implementation
10 */
11
12#include <linux/clk-provider.h>
13#include <linux/module.h>
14#include <linux/slab.h>
15#include <linux/io.h>
16#include <linux/err.h>
17
18/*
19 * DOC: basic fixed-rate clock that cannot gate
20 *
21 * Traits of this clock:
22 * prepare - clk_(un)prepare only ensures parents are prepared
23 * enable - clk_enable only ensures parents are enabled
24 * rate - rate is always a fixed value. No clk_set_rate support
25 * parent - fixed parent. No clk_set_parent support
26 */
27
28#define to_clk_fixed_rate(_hw) container_of(_hw, struct clk_fixed_rate, hw)
29
30static unsigned long clk_fixed_rate_recalc_rate(struct clk_hw *hw,
31 unsigned long parent_rate)
32{
33 return to_clk_fixed_rate(hw)->fixed_rate;
34}
35EXPORT_SYMBOL_GPL(clk_fixed_rate_recalc_rate);
36
37struct clk_ops clk_fixed_rate_ops = {
38 .recalc_rate = clk_fixed_rate_recalc_rate,
39};
40EXPORT_SYMBOL_GPL(clk_fixed_rate_ops);
41
42struct clk *clk_register_fixed_rate(struct device *dev, const char *name,
43 const char *parent_name, unsigned long flags,
44 unsigned long fixed_rate)
45{
46 struct clk_fixed_rate *fixed;
47 char **parent_names = NULL;
48 u8 len;
49
50 fixed = kzalloc(sizeof(struct clk_fixed_rate), GFP_KERNEL);
51
52 if (!fixed) {
53 pr_err("%s: could not allocate fixed clk\n", __func__);
54 return ERR_PTR(-ENOMEM);
55 }
56
57 /* struct clk_fixed_rate assignments */
58 fixed->fixed_rate = fixed_rate;
59
60 if (parent_name) {
61 parent_names = kmalloc(sizeof(char *), GFP_KERNEL);
62
63 if (! parent_names)
64 goto out;
65
66 len = sizeof(char) * strlen(parent_name);
67
68 parent_names[0] = kmalloc(len, GFP_KERNEL);
69
70 if (!parent_names[0])
71 goto out;
72
73 strncpy(parent_names[0], parent_name, len);
74 }
75
76out:
77 return clk_register(dev, name,
78 &clk_fixed_rate_ops, &fixed->hw,
79 parent_names,
80 (parent_name ? 1 : 0),
81 flags);
82}
diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c
new file mode 100644
index 000000000000..b5902e2ef2fd
--- /dev/null
+++ b/drivers/clk/clk-gate.c
@@ -0,0 +1,150 @@
1/*
2 * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
3 * Copyright (C) 2011-2012 Mike Turquette, Linaro Ltd <mturquette@linaro.org>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 *
9 * Gated clock implementation
10 */
11
12#include <linux/clk-provider.h>
13#include <linux/module.h>
14#include <linux/slab.h>
15#include <linux/io.h>
16#include <linux/err.h>
17#include <linux/string.h>
18
19/**
20 * DOC: basic gatable clock which can gate and ungate it's ouput
21 *
22 * Traits of this clock:
23 * prepare - clk_(un)prepare only ensures parent is (un)prepared
24 * enable - clk_enable and clk_disable are functional & control gating
25 * rate - inherits rate from parent. No clk_set_rate support
26 * parent - fixed parent. No clk_set_parent support
27 */
28
29#define to_clk_gate(_hw) container_of(_hw, struct clk_gate, hw)
30
31static void clk_gate_set_bit(struct clk_gate *gate)
32{
33 u32 reg;
34 unsigned long flags = 0;
35
36 if (gate->lock)
37 spin_lock_irqsave(gate->lock, flags);
38
39 reg = readl(gate->reg);
40 reg |= BIT(gate->bit_idx);
41 writel(reg, gate->reg);
42
43 if (gate->lock)
44 spin_unlock_irqrestore(gate->lock, flags);
45}
46
47static void clk_gate_clear_bit(struct clk_gate *gate)
48{
49 u32 reg;
50 unsigned long flags = 0;
51
52 if (gate->lock)
53 spin_lock_irqsave(gate->lock, flags);
54
55 reg = readl(gate->reg);
56 reg &= ~BIT(gate->bit_idx);
57 writel(reg, gate->reg);
58
59 if (gate->lock)
60 spin_unlock_irqrestore(gate->lock, flags);
61}
62
63static int clk_gate_enable(struct clk_hw *hw)
64{
65 struct clk_gate *gate = to_clk_gate(hw);
66
67 if (gate->flags & CLK_GATE_SET_TO_DISABLE)
68 clk_gate_clear_bit(gate);
69 else
70 clk_gate_set_bit(gate);
71
72 return 0;
73}
74EXPORT_SYMBOL_GPL(clk_gate_enable);
75
76static void clk_gate_disable(struct clk_hw *hw)
77{
78 struct clk_gate *gate = to_clk_gate(hw);
79
80 if (gate->flags & CLK_GATE_SET_TO_DISABLE)
81 clk_gate_set_bit(gate);
82 else
83 clk_gate_clear_bit(gate);
84}
85EXPORT_SYMBOL_GPL(clk_gate_disable);
86
87static int clk_gate_is_enabled(struct clk_hw *hw)
88{
89 u32 reg;
90 struct clk_gate *gate = to_clk_gate(hw);
91
92 reg = readl(gate->reg);
93
94 /* if a set bit disables this clk, flip it before masking */
95 if (gate->flags & CLK_GATE_SET_TO_DISABLE)
96 reg ^= BIT(gate->bit_idx);
97
98 reg &= BIT(gate->bit_idx);
99
100 return reg ? 1 : 0;
101}
102EXPORT_SYMBOL_GPL(clk_gate_is_enabled);
103
104struct clk_ops clk_gate_ops = {
105 .enable = clk_gate_enable,
106 .disable = clk_gate_disable,
107 .is_enabled = clk_gate_is_enabled,
108};
109EXPORT_SYMBOL_GPL(clk_gate_ops);
110
111struct clk *clk_register_gate(struct device *dev, const char *name,
112 const char *parent_name, unsigned long flags,
113 void __iomem *reg, u8 bit_idx,
114 u8 clk_gate_flags, spinlock_t *lock)
115{
116 struct clk_gate *gate;
117 struct clk *clk;
118
119 gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL);
120
121 if (!gate) {
122 pr_err("%s: could not allocate gated clk\n", __func__);
123 return NULL;
124 }
125
126 /* struct clk_gate assignments */
127 gate->reg = reg;
128 gate->bit_idx = bit_idx;
129 gate->flags = clk_gate_flags;
130 gate->lock = lock;
131
132 if (parent_name) {
133 gate->parent[0] = kstrdup(parent_name, GFP_KERNEL);
134 if (!gate->parent[0])
135 goto out;
136 }
137
138 clk = clk_register(dev, name,
139 &clk_gate_ops, &gate->hw,
140 gate->parent,
141 (parent_name ? 1 : 0),
142 flags);
143 if (clk)
144 return clk;
145out:
146 kfree(gate->parent[0]);
147 kfree(gate);
148
149 return NULL;
150}
diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c
new file mode 100644
index 000000000000..c71ad1f41a97
--- /dev/null
+++ b/drivers/clk/clk-mux.c
@@ -0,0 +1,116 @@
1/*
2 * Copyright (C) 2011 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de>
3 * Copyright (C) 2011 Richard Zhao, Linaro <richard.zhao@linaro.org>
4 * Copyright (C) 2011-2012 Mike Turquette, Linaro Ltd <mturquette@linaro.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * Simple multiplexer clock implementation
11 */
12
13#include <linux/clk.h>
14#include <linux/clk-provider.h>
15#include <linux/module.h>
16#include <linux/slab.h>
17#include <linux/io.h>
18#include <linux/err.h>
19
20/*
21 * DOC: basic adjustable multiplexer clock that cannot gate
22 *
23 * Traits of this clock:
24 * prepare - clk_prepare only ensures that parents are prepared
25 * enable - clk_enable only ensures that parents are enabled
26 * rate - rate is only affected by parent switching. No clk_set_rate support
27 * parent - parent is adjustable through clk_set_parent
28 */
29
30#define to_clk_mux(_hw) container_of(_hw, struct clk_mux, hw)
31
32static u8 clk_mux_get_parent(struct clk_hw *hw)
33{
34 struct clk_mux *mux = to_clk_mux(hw);
35 u32 val;
36
37 /*
38 * FIXME need a mux-specific flag to determine if val is bitwise or numeric
39 * e.g. sys_clkin_ck's clksel field is 3 bits wide, but ranges from 0x1
40 * to 0x7 (index starts at one)
41 * OTOH, pmd_trace_clk_mux_ck uses a separate bit for each clock, so
42 * val = 0x4 really means "bit 2, index starts at bit 0"
43 */
44 val = readl(mux->reg) >> mux->shift;
45 val &= (1 << mux->width) - 1;
46
47 if (val && (mux->flags & CLK_MUX_INDEX_BIT))
48 val = ffs(val) - 1;
49
50 if (val && (mux->flags & CLK_MUX_INDEX_ONE))
51 val--;
52
53 if (val >= __clk_get_num_parents(hw->clk))
54 return -EINVAL;
55
56 return val;
57}
58EXPORT_SYMBOL_GPL(clk_mux_get_parent);
59
60static int clk_mux_set_parent(struct clk_hw *hw, u8 index)
61{
62 struct clk_mux *mux = to_clk_mux(hw);
63 u32 val;
64 unsigned long flags = 0;
65
66 if (mux->flags & CLK_MUX_INDEX_BIT)
67 index = (1 << ffs(index));
68
69 if (mux->flags & CLK_MUX_INDEX_ONE)
70 index++;
71
72 if (mux->lock)
73 spin_lock_irqsave(mux->lock, flags);
74
75 val = readl(mux->reg);
76 val &= ~(((1 << mux->width) - 1) << mux->shift);
77 val |= index << mux->shift;
78 writel(val, mux->reg);
79
80 if (mux->lock)
81 spin_unlock_irqrestore(mux->lock, flags);
82
83 return 0;
84}
85EXPORT_SYMBOL_GPL(clk_mux_set_parent);
86
87struct clk_ops clk_mux_ops = {
88 .get_parent = clk_mux_get_parent,
89 .set_parent = clk_mux_set_parent,
90};
91EXPORT_SYMBOL_GPL(clk_mux_ops);
92
93struct clk *clk_register_mux(struct device *dev, const char *name,
94 char **parent_names, u8 num_parents, unsigned long flags,
95 void __iomem *reg, u8 shift, u8 width,
96 u8 clk_mux_flags, spinlock_t *lock)
97{
98 struct clk_mux *mux;
99
100 mux = kmalloc(sizeof(struct clk_mux), GFP_KERNEL);
101
102 if (!mux) {
103 pr_err("%s: could not allocate mux clk\n", __func__);
104 return ERR_PTR(-ENOMEM);
105 }
106
107 /* struct clk_mux assignments */
108 mux->reg = reg;
109 mux->shift = shift;
110 mux->width = width;
111 mux->flags = clk_mux_flags;
112 mux->lock = lock;
113
114 return clk_register(dev, name, &clk_mux_ops, &mux->hw,
115 parent_names, num_parents, flags);
116}
diff --git a/include/linux/clk-private.h b/include/linux/clk-private.h
index e2cce6fa6046..5e4312b6f5cc 100644
--- a/include/linux/clk-private.h
+++ b/include/linux/clk-private.h
@@ -46,6 +46,130 @@ struct clk {
46#endif 46#endif
47}; 47};
48 48
49/*
50 * DOC: Basic clock implementations common to many platforms
51 *
52 * Each basic clock hardware type is comprised of a structure describing the
53 * clock hardware, implementations of the relevant callbacks in struct clk_ops,
54 * unique flags for that hardware type, a registration function and an
55 * alternative macro for static initialization
56 */
57
58extern struct clk_ops clk_fixed_rate_ops;
59
60#define DEFINE_CLK_FIXED_RATE(_name, _flags, _rate, \
61 _fixed_rate_flags) \
62 static struct clk _name; \
63 static char *_name##_parent_names[] = {}; \
64 static struct clk_fixed_rate _name##_hw = { \
65 .hw = { \
66 .clk = &_name, \
67 }, \
68 .fixed_rate = _rate, \
69 .flags = _fixed_rate_flags, \
70 }; \
71 static struct clk _name = { \
72 .name = #_name, \
73 .ops = &clk_fixed_rate_ops, \
74 .hw = &_name##_hw.hw, \
75 .parent_names = _name##_parent_names, \
76 .num_parents = \
77 ARRAY_SIZE(_name##_parent_names), \
78 .flags = _flags, \
79 };
80
81extern struct clk_ops clk_gate_ops;
82
83#define DEFINE_CLK_GATE(_name, _parent_name, _parent_ptr, \
84 _flags, _reg, _bit_idx, \
85 _gate_flags, _lock) \
86 static struct clk _name; \
87 static char *_name##_parent_names[] = { \
88 _parent_name, \
89 }; \
90 static struct clk *_name##_parents[] = { \
91 _parent_ptr, \
92 }; \
93 static struct clk_gate _name##_hw = { \
94 .hw = { \
95 .clk = &_name, \
96 }, \
97 .reg = _reg, \
98 .bit_idx = _bit_idx, \
99 .flags = _gate_flags, \
100 .lock = _lock, \
101 }; \
102 static struct clk _name = { \
103 .name = #_name, \
104 .ops = &clk_gate_ops, \
105 .hw = &_name##_hw.hw, \
106 .parent_names = _name##_parent_names, \
107 .num_parents = \
108 ARRAY_SIZE(_name##_parent_names), \
109 .parents = _name##_parents, \
110 .flags = _flags, \
111 };
112
113extern struct clk_ops clk_divider_ops;
114
115#define DEFINE_CLK_DIVIDER(_name, _parent_name, _parent_ptr, \
116 _flags, _reg, _shift, _width, \
117 _divider_flags, _lock) \
118 static struct clk _name; \
119 static char *_name##_parent_names[] = { \
120 _parent_name, \
121 }; \
122 static struct clk *_name##_parents[] = { \
123 _parent_ptr, \
124 }; \
125 static struct clk_divider _name##_hw = { \
126 .hw = { \
127 .clk = &_name, \
128 }, \
129 .reg = _reg, \
130 .shift = _shift, \
131 .width = _width, \
132 .flags = _divider_flags, \
133 .lock = _lock, \
134 }; \
135 static struct clk _name = { \
136 .name = #_name, \
137 .ops = &clk_divider_ops, \
138 .hw = &_name##_hw.hw, \
139 .parent_names = _name##_parent_names, \
140 .num_parents = \
141 ARRAY_SIZE(_name##_parent_names), \
142 .parents = _name##_parents, \
143 .flags = _flags, \
144 };
145
146extern struct clk_ops clk_mux_ops;
147
148#define DEFINE_CLK_MUX(_name, _parent_names, _parents, _flags, \
149 _reg, _shift, _width, \
150 _mux_flags, _lock) \
151 static struct clk _name; \
152 static struct clk_mux _name##_hw = { \
153 .hw = { \
154 .clk = &_name, \
155 }, \
156 .reg = _reg, \
157 .shift = _shift, \
158 .width = _width, \
159 .flags = _mux_flags, \
160 .lock = _lock, \
161 }; \
162 static struct clk _name = { \
163 .name = #_name, \
164 .ops = &clk_mux_ops, \
165 .hw = &_name##_hw.hw, \
166 .parent_names = _parent_names, \
167 .num_parents = \
168 ARRAY_SIZE(_parent_names), \
169 .parents = _parents, \
170 .flags = _flags, \
171 };
172
49/** 173/**
50 * __clk_init - initialize the data structures in a struct clk 174 * __clk_init - initialize the data structures in a struct clk
51 * @dev: device initializing this clk, placeholder for now 175 * @dev: device initializing this clk, placeholder for now
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index b18b0e7888a8..5508897ad376 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -129,6 +129,133 @@ struct clk_ops {
129 void (*init)(struct clk_hw *hw); 129 void (*init)(struct clk_hw *hw);
130}; 130};
131 131
132/*
133 * DOC: Basic clock implementations common to many platforms
134 *
135 * Each basic clock hardware type is comprised of a structure describing the
136 * clock hardware, implementations of the relevant callbacks in struct clk_ops,
137 * unique flags for that hardware type, a registration function and an
138 * alternative macro for static initialization
139 */
140
141/**
142 * struct clk_fixed_rate - fixed-rate clock
143 * @hw: handle between common and hardware-specific interfaces
144 * @fixed_rate: constant frequency of clock
145 */
146struct clk_fixed_rate {
147 struct clk_hw hw;
148 unsigned long fixed_rate;
149 u8 flags;
150};
151
152struct clk *clk_register_fixed_rate(struct device *dev, const char *name,
153 const char *parent_name, unsigned long flags,
154 unsigned long fixed_rate);
155
156/**
157 * struct clk_gate - gating clock
158 *
159 * @hw: handle between common and hardware-specific interfaces
160 * @reg: register controlling gate
161 * @bit_idx: single bit controlling gate
162 * @flags: hardware-specific flags
163 * @lock: register lock
164 *
165 * Clock which can gate its output. Implements .enable & .disable
166 *
167 * Flags:
168 * CLK_GATE_SET_DISABLE - by default this clock sets the bit at bit_idx to
169 * enable the clock. Setting this flag does the opposite: setting the bit
170 * disable the clock and clearing it enables the clock
171 */
172struct clk_gate {
173 struct clk_hw hw;
174 void __iomem *reg;
175 u8 bit_idx;
176 u8 flags;
177 spinlock_t *lock;
178 char *parent[1];
179};
180
181#define CLK_GATE_SET_TO_DISABLE BIT(0)
182
183struct clk *clk_register_gate(struct device *dev, const char *name,
184 const char *parent_name, unsigned long flags,
185 void __iomem *reg, u8 bit_idx,
186 u8 clk_gate_flags, spinlock_t *lock);
187
188/**
189 * struct clk_divider - adjustable divider clock
190 *
191 * @hw: handle between common and hardware-specific interfaces
192 * @reg: register containing the divider
193 * @shift: shift to the divider bit field
194 * @width: width of the divider bit field
195 * @lock: register lock
196 *
197 * Clock with an adjustable divider affecting its output frequency. Implements
198 * .recalc_rate, .set_rate and .round_rate
199 *
200 * Flags:
201 * CLK_DIVIDER_ONE_BASED - by default the divisor is the value read from the
202 * register plus one. If CLK_DIVIDER_ONE_BASED is set then the divider is
203 * the raw value read from the register, with the value of zero considered
204 * invalid
205 * CLK_DIVIDER_POWER_OF_TWO - clock divisor is 2 raised to the value read from
206 * the hardware register
207 */
208struct clk_divider {
209 struct clk_hw hw;
210 void __iomem *reg;
211 u8 shift;
212 u8 width;
213 u8 flags;
214 spinlock_t *lock;
215 char *parent[1];
216};
217
218#define CLK_DIVIDER_ONE_BASED BIT(0)
219#define CLK_DIVIDER_POWER_OF_TWO BIT(1)
220
221struct clk *clk_register_divider(struct device *dev, const char *name,
222 const char *parent_name, unsigned long flags,
223 void __iomem *reg, u8 shift, u8 width,
224 u8 clk_divider_flags, spinlock_t *lock);
225
226/**
227 * struct clk_mux - multiplexer clock
228 *
229 * @hw: handle between common and hardware-specific interfaces
230 * @reg: register controlling multiplexer
231 * @shift: shift to multiplexer bit field
232 * @width: width of mutliplexer bit field
233 * @num_clks: number of parent clocks
234 * @lock: register lock
235 *
236 * Clock with multiple selectable parents. Implements .get_parent, .set_parent
237 * and .recalc_rate
238 *
239 * Flags:
240 * CLK_MUX_INDEX_ONE - register index starts at 1, not 0
241 * CLK_MUX_INDEX_BITWISE - register index is a single bit (power of two)
242 */
243struct clk_mux {
244 struct clk_hw hw;
245 void __iomem *reg;
246 u8 shift;
247 u8 width;
248 u8 flags;
249 spinlock_t *lock;
250};
251
252#define CLK_MUX_INDEX_ONE BIT(0)
253#define CLK_MUX_INDEX_BIT BIT(1)
254
255struct clk *clk_register_mux(struct device *dev, const char *name,
256 char **parent_names, u8 num_parents, unsigned long flags,
257 void __iomem *reg, u8 shift, u8 width,
258 u8 clk_mux_flags, spinlock_t *lock);
132 259
133/** 260/**
134 * clk_register - allocate a new clock, register it and return an opaque cookie 261 * clk_register - allocate a new clock, register it and return an opaque cookie