1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2011 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de>
4 * Copyright (C) 2011 Richard Zhao, Linaro <richard.zhao@linaro.org>
5 * Copyright (C) 2011-2012 Mike Turquette, Linaro Ltd <mturquette@linaro.org>
7 * Simple multiplexer clock implementation
10 #include <linux/clk-provider.h>
11 #include <linux/device.h>
12 #include <linux/module.h>
13 #include <linux/slab.h>
15 #include <linux/err.h>
18 * DOC: basic adjustable multiplexer clock that cannot gate
20 * Traits of this clock:
21 * prepare - clk_prepare only ensures that parents are prepared
22 * enable - clk_enable only ensures that parents are enabled
23 * rate - rate is only affected by parent switching. No clk_set_rate support
24 * parent - parent is adjustable through clk_set_parent
27 static inline u32
clk_mux_readl(struct clk_mux
*mux
)
29 if (mux
->flags
& CLK_MUX_BIG_ENDIAN
)
30 return ioread32be(mux
->reg
);
32 return readl(mux
->reg
);
35 static inline void clk_mux_writel(struct clk_mux
*mux
, u32 val
)
37 if (mux
->flags
& CLK_MUX_BIG_ENDIAN
)
38 iowrite32be(val
, mux
->reg
);
40 writel(val
, mux
->reg
);
43 int clk_mux_val_to_index(struct clk_hw
*hw
, const u32
*table
, unsigned int flags
,
46 int num_parents
= clk_hw_get_num_parents(hw
);
51 for (i
= 0; i
< num_parents
; i
++)
57 if (val
&& (flags
& CLK_MUX_INDEX_BIT
))
60 if (val
&& (flags
& CLK_MUX_INDEX_ONE
))
63 if (val
>= num_parents
)
68 EXPORT_SYMBOL_GPL(clk_mux_val_to_index
);
70 unsigned int clk_mux_index_to_val(const u32
*table
, unsigned int flags
, u8 index
)
72 unsigned int val
= index
;
77 if (flags
& CLK_MUX_INDEX_BIT
)
80 if (flags
& CLK_MUX_INDEX_ONE
)
86 EXPORT_SYMBOL_GPL(clk_mux_index_to_val
);
88 static u8
clk_mux_get_parent(struct clk_hw
*hw
)
90 struct clk_mux
*mux
= to_clk_mux(hw
);
93 val
= clk_mux_readl(mux
) >> mux
->shift
;
96 return clk_mux_val_to_index(hw
, mux
->table
, mux
->flags
, val
);
99 static int clk_mux_set_parent(struct clk_hw
*hw
, u8 index
)
101 struct clk_mux
*mux
= to_clk_mux(hw
);
102 u32 val
= clk_mux_index_to_val(mux
->table
, mux
->flags
, index
);
103 unsigned long flags
= 0;
107 spin_lock_irqsave(mux
->lock
, flags
);
109 __acquire(mux
->lock
);
111 if (mux
->flags
& CLK_MUX_HIWORD_MASK
) {
112 reg
= mux
->mask
<< (mux
->shift
+ 16);
114 reg
= clk_mux_readl(mux
);
115 reg
&= ~(mux
->mask
<< mux
->shift
);
117 val
= val
<< mux
->shift
;
119 clk_mux_writel(mux
, reg
);
122 spin_unlock_irqrestore(mux
->lock
, flags
);
124 __release(mux
->lock
);
129 static int clk_mux_determine_rate(struct clk_hw
*hw
,
130 struct clk_rate_request
*req
)
132 struct clk_mux
*mux
= to_clk_mux(hw
);
134 return clk_mux_determine_rate_flags(hw
, req
, mux
->flags
);
137 const struct clk_ops clk_mux_ops
= {
138 .get_parent
= clk_mux_get_parent
,
139 .set_parent
= clk_mux_set_parent
,
140 .determine_rate
= clk_mux_determine_rate
,
142 EXPORT_SYMBOL_GPL(clk_mux_ops
);
144 const struct clk_ops clk_mux_ro_ops
= {
145 .get_parent
= clk_mux_get_parent
,
147 EXPORT_SYMBOL_GPL(clk_mux_ro_ops
);
149 struct clk_hw
*__clk_hw_register_mux(struct device
*dev
, struct device_node
*np
,
150 const char *name
, u8 num_parents
,
151 const char * const *parent_names
,
152 const struct clk_hw
**parent_hws
,
153 const struct clk_parent_data
*parent_data
,
154 unsigned long flags
, void __iomem
*reg
, u8 shift
, u32 mask
,
155 u8 clk_mux_flags
, const u32
*table
, spinlock_t
*lock
)
159 struct clk_init_data init
= {};
162 if (clk_mux_flags
& CLK_MUX_HIWORD_MASK
) {
163 u8 width
= fls(mask
) - ffs(mask
) + 1;
165 if (width
+ shift
> 16) {
166 pr_err("mux value exceeds LOWORD field\n");
167 return ERR_PTR(-EINVAL
);
171 /* allocate the mux */
172 mux
= kzalloc(sizeof(*mux
), GFP_KERNEL
);
174 return ERR_PTR(-ENOMEM
);
177 if (clk_mux_flags
& CLK_MUX_READ_ONLY
)
178 init
.ops
= &clk_mux_ro_ops
;
180 init
.ops
= &clk_mux_ops
;
182 init
.parent_names
= parent_names
;
183 init
.parent_data
= parent_data
;
184 init
.parent_hws
= parent_hws
;
185 init
.num_parents
= num_parents
;
187 /* struct clk_mux assignments */
191 mux
->flags
= clk_mux_flags
;
194 mux
->hw
.init
= &init
;
198 ret
= clk_hw_register(dev
, hw
);
200 ret
= of_clk_hw_register(np
, hw
);
208 EXPORT_SYMBOL_GPL(__clk_hw_register_mux
);
210 static void devm_clk_hw_release_mux(struct device
*dev
, void *res
)
212 clk_hw_unregister_mux(*(struct clk_hw
**)res
);
215 struct clk_hw
*__devm_clk_hw_register_mux(struct device
*dev
, struct device_node
*np
,
216 const char *name
, u8 num_parents
,
217 const char * const *parent_names
,
218 const struct clk_hw
**parent_hws
,
219 const struct clk_parent_data
*parent_data
,
220 unsigned long flags
, void __iomem
*reg
, u8 shift
, u32 mask
,
221 u8 clk_mux_flags
, const u32
*table
, spinlock_t
*lock
)
223 struct clk_hw
**ptr
, *hw
;
225 ptr
= devres_alloc(devm_clk_hw_release_mux
, sizeof(*ptr
), GFP_KERNEL
);
227 return ERR_PTR(-ENOMEM
);
229 hw
= __clk_hw_register_mux(dev
, np
, name
, num_parents
, parent_names
, parent_hws
,
230 parent_data
, flags
, reg
, shift
, mask
,
231 clk_mux_flags
, table
, lock
);
235 devres_add(dev
, ptr
);
242 EXPORT_SYMBOL_GPL(__devm_clk_hw_register_mux
);
244 struct clk
*clk_register_mux_table(struct device
*dev
, const char *name
,
245 const char * const *parent_names
, u8 num_parents
,
246 unsigned long flags
, void __iomem
*reg
, u8 shift
, u32 mask
,
247 u8 clk_mux_flags
, const u32
*table
, spinlock_t
*lock
)
251 hw
= clk_hw_register_mux_table(dev
, name
, parent_names
,
252 num_parents
, flags
, reg
, shift
, mask
,
253 clk_mux_flags
, table
, lock
);
258 EXPORT_SYMBOL_GPL(clk_register_mux_table
);
260 void clk_unregister_mux(struct clk
*clk
)
265 hw
= __clk_get_hw(clk
);
269 mux
= to_clk_mux(hw
);
274 EXPORT_SYMBOL_GPL(clk_unregister_mux
);
276 void clk_hw_unregister_mux(struct clk_hw
*hw
)
280 mux
= to_clk_mux(hw
);
282 clk_hw_unregister(hw
);
285 EXPORT_SYMBOL_GPL(clk_hw_unregister_mux
);