2 * Copyright (C) 2013 Emilio López <emilio@elopez.com.ar>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
8 * Adjustable factor-based clock implementation
11 #include <linux/clk-provider.h>
12 #include <linux/delay.h>
13 #include <linux/err.h>
15 #include <linux/of_address.h>
16 #include <linux/slab.h>
17 #include <linux/string.h>
19 #include "clk-factors.h"
22 * DOC: basic adjustable factor-based clock
24 * Traits of this clock:
25 * prepare - clk_prepare only ensures that parents are prepared
26 * enable - clk_enable only ensures that parents are enabled
27 * rate - rate is adjustable.
28 * clk->rate = (parent->rate * N * (K + 1) >> P) / (M + 1)
29 * parent - fixed parent. No clk_set_parent support
32 #define to_clk_factors(_hw) container_of(_hw, struct clk_factors, hw)
34 #define FACTORS_MAX_PARENTS 5
36 #define SETMASK(len, pos) (((1U << (len)) - 1) << (pos))
37 #define CLRMASK(len, pos) (~(SETMASK(len, pos)))
38 #define FACTOR_GET(bit, len, reg) (((reg) & SETMASK(len, bit)) >> (bit))
40 #define FACTOR_SET(bit, len, reg, val) \
41 (((reg) & CLRMASK(len, bit)) | (val << (bit)))
43 static unsigned long clk_factors_recalc_rate(struct clk_hw
*hw
,
44 unsigned long parent_rate
)
46 u8 n
= 1, k
= 0, p
= 0, m
= 0;
49 struct clk_factors
*factors
= to_clk_factors(hw
);
50 const struct clk_factors_config
*config
= factors
->config
;
52 /* Fetch the register value */
53 reg
= readl(factors
->reg
);
55 /* Get each individual factor if applicable */
56 if (config
->nwidth
!= SUNXI_FACTORS_NOT_APPLICABLE
)
57 n
= FACTOR_GET(config
->nshift
, config
->nwidth
, reg
);
58 if (config
->kwidth
!= SUNXI_FACTORS_NOT_APPLICABLE
)
59 k
= FACTOR_GET(config
->kshift
, config
->kwidth
, reg
);
60 if (config
->mwidth
!= SUNXI_FACTORS_NOT_APPLICABLE
)
61 m
= FACTOR_GET(config
->mshift
, config
->mwidth
, reg
);
62 if (config
->pwidth
!= SUNXI_FACTORS_NOT_APPLICABLE
)
63 p
= FACTOR_GET(config
->pshift
, config
->pwidth
, reg
);
65 if (factors
->recalc
) {
66 struct factors_request factors_req
= {
67 .parent_rate
= parent_rate
,
74 /* get mux details from mux clk structure */
76 factors_req
.parent_index
=
77 (reg
>> factors
->mux
->shift
) &
80 factors
->recalc(&factors_req
);
82 return factors_req
.rate
;
85 /* Calculate the rate */
86 rate
= (parent_rate
* (n
+ config
->n_start
) * (k
+ 1) >> p
) / (m
+ 1);
91 static int clk_factors_determine_rate(struct clk_hw
*hw
,
92 struct clk_rate_request
*req
)
94 struct clk_factors
*factors
= to_clk_factors(hw
);
95 struct clk_hw
*parent
, *best_parent
= NULL
;
97 unsigned long parent_rate
, best
= 0, child_rate
, best_child_rate
= 0;
99 /* find the parent that can help provide the fastest rate <= rate */
100 num_parents
= clk_hw_get_num_parents(hw
);
101 for (i
= 0; i
< num_parents
; i
++) {
102 struct factors_request factors_req
= {
106 parent
= clk_hw_get_parent_by_index(hw
, i
);
109 if (clk_hw_get_flags(hw
) & CLK_SET_RATE_PARENT
)
110 parent_rate
= clk_hw_round_rate(parent
, req
->rate
);
112 parent_rate
= clk_hw_get_rate(parent
);
114 factors_req
.parent_rate
= parent_rate
;
115 factors
->get_factors(&factors_req
);
116 child_rate
= factors_req
.rate
;
118 if (child_rate
<= req
->rate
&& child_rate
> best_child_rate
) {
119 best_parent
= parent
;
121 best_child_rate
= child_rate
;
128 req
->best_parent_hw
= best_parent
;
129 req
->best_parent_rate
= best
;
130 req
->rate
= best_child_rate
;
135 static int clk_factors_set_rate(struct clk_hw
*hw
, unsigned long rate
,
136 unsigned long parent_rate
)
138 struct factors_request req
= {
140 .parent_rate
= parent_rate
,
143 struct clk_factors
*factors
= to_clk_factors(hw
);
144 const struct clk_factors_config
*config
= factors
->config
;
145 unsigned long flags
= 0;
147 factors
->get_factors(&req
);
150 spin_lock_irqsave(factors
->lock
, flags
);
152 /* Fetch the register value */
153 reg
= readl(factors
->reg
);
155 /* Set up the new factors - macros do not do anything if width is 0 */
156 reg
= FACTOR_SET(config
->nshift
, config
->nwidth
, reg
, req
.n
);
157 reg
= FACTOR_SET(config
->kshift
, config
->kwidth
, reg
, req
.k
);
158 reg
= FACTOR_SET(config
->mshift
, config
->mwidth
, reg
, req
.m
);
159 reg
= FACTOR_SET(config
->pshift
, config
->pwidth
, reg
, req
.p
);
162 writel(reg
, factors
->reg
);
164 /* delay 500us so pll stabilizes */
165 __delay((rate
>> 20) * 500 / 2);
168 spin_unlock_irqrestore(factors
->lock
, flags
);
173 static const struct clk_ops clk_factors_ops
= {
174 .determine_rate
= clk_factors_determine_rate
,
175 .recalc_rate
= clk_factors_recalc_rate
,
176 .set_rate
= clk_factors_set_rate
,
179 static struct clk
*__sunxi_factors_register(struct device_node
*node
,
180 const struct factors_data
*data
,
181 spinlock_t
*lock
, void __iomem
*reg
,
185 struct clk_factors
*factors
;
186 struct clk_gate
*gate
= NULL
;
187 struct clk_mux
*mux
= NULL
;
188 struct clk_hw
*gate_hw
= NULL
;
189 struct clk_hw
*mux_hw
= NULL
;
190 const char *clk_name
= node
->name
;
191 const char *parents
[FACTORS_MAX_PARENTS
];
194 /* if we have a mux, we will have >1 parents */
195 i
= of_clk_parent_fill(node
, parents
, FACTORS_MAX_PARENTS
);
198 * some factor clocks, such as pll5 and pll6, may have multiple
199 * outputs, and have their name designated in factors_data
202 clk_name
= data
->name
;
204 of_property_read_string(node
, "clock-output-names", &clk_name
);
206 factors
= kzalloc(sizeof(struct clk_factors
), GFP_KERNEL
);
210 /* set up factors properties */
212 factors
->config
= data
->table
;
213 factors
->get_factors
= data
->getter
;
214 factors
->recalc
= data
->recalc
;
215 factors
->lock
= lock
;
217 /* Add a gate if this factor clock can be gated */
219 gate
= kzalloc(sizeof(struct clk_gate
), GFP_KERNEL
);
223 factors
->gate
= gate
;
225 /* set up gate properties */
227 gate
->bit_idx
= data
->enable
;
228 gate
->lock
= factors
->lock
;
232 /* Add a mux if this factor clock can be muxed */
234 mux
= kzalloc(sizeof(struct clk_mux
), GFP_KERNEL
);
240 /* set up gate properties */
242 mux
->shift
= data
->mux
;
243 mux
->mask
= data
->muxmask
;
244 mux
->lock
= factors
->lock
;
248 clk
= clk_register_composite(NULL
, clk_name
,
250 mux_hw
, &clk_mux_ops
,
251 &factors
->hw
, &clk_factors_ops
,
252 gate_hw
, &clk_gate_ops
, CLK_IS_CRITICAL
);
256 ret
= of_clk_add_provider(node
, of_clk_src_simple_get
, clk
);
263 /* TODO: The composite clock stuff will leak a bit here. */
275 struct clk
*sunxi_factors_register(struct device_node
*node
,
276 const struct factors_data
*data
,
280 return __sunxi_factors_register(node
, data
, lock
, reg
, 0);
283 struct clk
*sunxi_factors_register_critical(struct device_node
*node
,
284 const struct factors_data
*data
,
288 return __sunxi_factors_register(node
, data
, lock
, reg
, CLK_IS_CRITICAL
);
291 void sunxi_factors_unregister(struct device_node
*node
, struct clk
*clk
)
293 struct clk_hw
*hw
= __clk_get_hw(clk
);
294 struct clk_factors
*factors
;
299 factors
= to_clk_factors(hw
);
301 of_clk_del_provider(node
);
302 /* TODO: The composite clock stuff will leak a bit here. */
305 kfree(factors
->gate
);