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/module.h>
16 #include <linux/of_address.h>
17 #include <linux/slab.h>
18 #include <linux/string.h>
20 #include "clk-factors.h"
23 * DOC: basic adjustable factor-based clock
25 * Traits of this clock:
26 * prepare - clk_prepare only ensures that parents are prepared
27 * enable - clk_enable only ensures that parents are enabled
28 * rate - rate is adjustable.
29 * clk->rate = (parent->rate * N * (K + 1) >> P) / (M + 1)
30 * parent - fixed parent. No clk_set_parent support
33 #define to_clk_factors(_hw) container_of(_hw, struct clk_factors, hw)
35 #define FACTORS_MAX_PARENTS 5
37 #define SETMASK(len, pos) (((1U << (len)) - 1) << (pos))
38 #define CLRMASK(len, pos) (~(SETMASK(len, pos)))
39 #define FACTOR_GET(bit, len, reg) (((reg) & SETMASK(len, bit)) >> (bit))
41 #define FACTOR_SET(bit, len, reg, val) \
42 (((reg) & CLRMASK(len, bit)) | (val << (bit)))
44 static unsigned long clk_factors_recalc_rate(struct clk_hw
*hw
,
45 unsigned long parent_rate
)
47 u8 n
= 1, k
= 0, p
= 0, m
= 0;
50 struct clk_factors
*factors
= to_clk_factors(hw
);
51 struct clk_factors_config
*config
= factors
->config
;
53 /* Fetch the register value */
54 reg
= readl(factors
->reg
);
56 /* Get each individual factor if applicable */
57 if (config
->nwidth
!= SUNXI_FACTORS_NOT_APPLICABLE
)
58 n
= FACTOR_GET(config
->nshift
, config
->nwidth
, reg
);
59 if (config
->kwidth
!= SUNXI_FACTORS_NOT_APPLICABLE
)
60 k
= FACTOR_GET(config
->kshift
, config
->kwidth
, reg
);
61 if (config
->mwidth
!= SUNXI_FACTORS_NOT_APPLICABLE
)
62 m
= FACTOR_GET(config
->mshift
, config
->mwidth
, reg
);
63 if (config
->pwidth
!= SUNXI_FACTORS_NOT_APPLICABLE
)
64 p
= FACTOR_GET(config
->pshift
, config
->pwidth
, reg
);
66 /* Calculate the rate */
67 rate
= (parent_rate
* (n
+ config
->n_start
) * (k
+ 1) >> p
) / (m
+ 1);
72 static long clk_factors_round_rate(struct clk_hw
*hw
, unsigned long rate
,
73 unsigned long *parent_rate
)
75 struct clk_factors
*factors
= to_clk_factors(hw
);
76 factors
->get_factors((u32
*)&rate
, (u32
)*parent_rate
,
77 NULL
, NULL
, NULL
, NULL
);
82 static int clk_factors_determine_rate(struct clk_hw
*hw
,
83 struct clk_rate_request
*req
)
85 struct clk_hw
*parent
, *best_parent
= NULL
;
87 unsigned long parent_rate
, best
= 0, child_rate
, best_child_rate
= 0;
89 /* find the parent that can help provide the fastest rate <= rate */
90 num_parents
= clk_hw_get_num_parents(hw
);
91 for (i
= 0; i
< num_parents
; i
++) {
92 parent
= clk_hw_get_parent_by_index(hw
, i
);
95 if (clk_hw_get_flags(hw
) & CLK_SET_RATE_PARENT
)
96 parent_rate
= clk_hw_round_rate(parent
, req
->rate
);
98 parent_rate
= clk_hw_get_rate(parent
);
100 child_rate
= clk_factors_round_rate(hw
, req
->rate
,
103 if (child_rate
<= req
->rate
&& child_rate
> best_child_rate
) {
104 best_parent
= parent
;
106 best_child_rate
= child_rate
;
113 req
->best_parent_hw
= best_parent
;
114 req
->best_parent_rate
= best
;
115 req
->rate
= best_child_rate
;
120 static int clk_factors_set_rate(struct clk_hw
*hw
, unsigned long rate
,
121 unsigned long parent_rate
)
123 u8 n
= 0, k
= 0, m
= 0, p
= 0;
125 struct clk_factors
*factors
= to_clk_factors(hw
);
126 struct clk_factors_config
*config
= factors
->config
;
127 unsigned long flags
= 0;
129 factors
->get_factors((u32
*)&rate
, (u32
)parent_rate
, &n
, &k
, &m
, &p
);
132 spin_lock_irqsave(factors
->lock
, flags
);
134 /* Fetch the register value */
135 reg
= readl(factors
->reg
);
137 /* Set up the new factors - macros do not do anything if width is 0 */
138 reg
= FACTOR_SET(config
->nshift
, config
->nwidth
, reg
, n
);
139 reg
= FACTOR_SET(config
->kshift
, config
->kwidth
, reg
, k
);
140 reg
= FACTOR_SET(config
->mshift
, config
->mwidth
, reg
, m
);
141 reg
= FACTOR_SET(config
->pshift
, config
->pwidth
, reg
, p
);
144 writel(reg
, factors
->reg
);
146 /* delay 500us so pll stabilizes */
147 __delay((rate
>> 20) * 500 / 2);
150 spin_unlock_irqrestore(factors
->lock
, flags
);
155 static const struct clk_ops clk_factors_ops
= {
156 .determine_rate
= clk_factors_determine_rate
,
157 .recalc_rate
= clk_factors_recalc_rate
,
158 .round_rate
= clk_factors_round_rate
,
159 .set_rate
= clk_factors_set_rate
,
162 struct clk
*sunxi_factors_register(struct device_node
*node
,
163 const struct factors_data
*data
,
168 struct clk_factors
*factors
;
169 struct clk_gate
*gate
= NULL
;
170 struct clk_mux
*mux
= NULL
;
171 struct clk_hw
*gate_hw
= NULL
;
172 struct clk_hw
*mux_hw
= NULL
;
173 const char *clk_name
= node
->name
;
174 const char *parents
[FACTORS_MAX_PARENTS
];
177 /* if we have a mux, we will have >1 parents */
178 i
= of_clk_parent_fill(node
, parents
, FACTORS_MAX_PARENTS
);
181 * some factor clocks, such as pll5 and pll6, may have multiple
182 * outputs, and have their name designated in factors_data
185 clk_name
= data
->name
;
187 of_property_read_string(node
, "clock-output-names", &clk_name
);
189 factors
= kzalloc(sizeof(struct clk_factors
), GFP_KERNEL
);
193 /* set up factors properties */
195 factors
->config
= data
->table
;
196 factors
->get_factors
= data
->getter
;
197 factors
->lock
= lock
;
199 /* Add a gate if this factor clock can be gated */
201 gate
= kzalloc(sizeof(struct clk_gate
), GFP_KERNEL
);
207 /* set up gate properties */
209 gate
->bit_idx
= data
->enable
;
210 gate
->lock
= factors
->lock
;
214 /* Add a mux if this factor clock can be muxed */
216 mux
= kzalloc(sizeof(struct clk_mux
), GFP_KERNEL
);
223 /* set up gate properties */
225 mux
->shift
= data
->mux
;
226 mux
->mask
= data
->muxmask
;
227 mux
->lock
= factors
->lock
;
231 clk
= clk_register_composite(NULL
, clk_name
,
233 mux_hw
, &clk_mux_ops
,
234 &factors
->hw
, &clk_factors_ops
,
235 gate_hw
, &clk_gate_ops
, 0);
238 of_clk_add_provider(node
, of_clk_src_simple_get
, clk
);
239 clk_register_clkdev(clk
, clk_name
, NULL
);