2 * r8a7790 Common Clock Framework support
4 * Copyright (C) 2013 Renesas Solutions Corp.
6 * Contact: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; version 2 of the License.
13 #include <linux/clk-provider.h>
14 #include <linux/init.h>
16 #include <linux/kernel.h>
18 #include <linux/of_address.h>
19 #include <linux/slab.h>
23 #define CPG_DIV6_CKSTP BIT(8)
24 #define CPG_DIV6_DIV(d) ((d) & 0x3f)
25 #define CPG_DIV6_DIV_MASK 0x3f
28 * struct div6_clock - CPG 6 bit divider clock
29 * @hw: handle between common and hardware-specific interfaces
30 * @reg: IO-remapped register
31 * @div: divisor value (1-64)
42 #define to_div6_clock(_hw) container_of(_hw, struct div6_clock, hw)
44 static int cpg_div6_clock_enable(struct clk_hw
*hw
)
46 struct div6_clock
*clock
= to_div6_clock(hw
);
49 val
= (clk_readl(clock
->reg
) & ~(CPG_DIV6_DIV_MASK
| CPG_DIV6_CKSTP
))
50 | CPG_DIV6_DIV(clock
->div
- 1);
51 clk_writel(val
, clock
->reg
);
56 static void cpg_div6_clock_disable(struct clk_hw
*hw
)
58 struct div6_clock
*clock
= to_div6_clock(hw
);
61 val
= clk_readl(clock
->reg
);
62 val
|= CPG_DIV6_CKSTP
;
64 * DIV6 clocks require the divisor field to be non-zero when stopping
65 * the clock. However, some clocks (e.g. ZB on sh73a0) fail to be
66 * re-enabled later if the divisor field is changed when stopping the
69 if (!(val
& CPG_DIV6_DIV_MASK
))
70 val
|= CPG_DIV6_DIV_MASK
;
71 clk_writel(val
, clock
->reg
);
74 static int cpg_div6_clock_is_enabled(struct clk_hw
*hw
)
76 struct div6_clock
*clock
= to_div6_clock(hw
);
78 return !(clk_readl(clock
->reg
) & CPG_DIV6_CKSTP
);
81 static unsigned long cpg_div6_clock_recalc_rate(struct clk_hw
*hw
,
82 unsigned long parent_rate
)
84 struct div6_clock
*clock
= to_div6_clock(hw
);
86 return parent_rate
/ clock
->div
;
89 static unsigned int cpg_div6_clock_calc_div(unsigned long rate
,
90 unsigned long parent_rate
)
97 div
= DIV_ROUND_CLOSEST(parent_rate
, rate
);
98 return clamp_t(unsigned int, div
, 1, 64);
101 static long cpg_div6_clock_round_rate(struct clk_hw
*hw
, unsigned long rate
,
102 unsigned long *parent_rate
)
104 unsigned int div
= cpg_div6_clock_calc_div(rate
, *parent_rate
);
106 return *parent_rate
/ div
;
109 static int cpg_div6_clock_set_rate(struct clk_hw
*hw
, unsigned long rate
,
110 unsigned long parent_rate
)
112 struct div6_clock
*clock
= to_div6_clock(hw
);
113 unsigned int div
= cpg_div6_clock_calc_div(rate
, parent_rate
);
118 val
= clk_readl(clock
->reg
) & ~CPG_DIV6_DIV_MASK
;
119 /* Only program the new divisor if the clock isn't stopped. */
120 if (!(val
& CPG_DIV6_CKSTP
))
121 clk_writel(val
| CPG_DIV6_DIV(clock
->div
- 1), clock
->reg
);
126 static u8
cpg_div6_clock_get_parent(struct clk_hw
*hw
)
128 struct div6_clock
*clock
= to_div6_clock(hw
);
132 if (clock
->src_width
== 0)
135 hw_index
= (clk_readl(clock
->reg
) >> clock
->src_shift
) &
136 (BIT(clock
->src_width
) - 1);
137 for (i
= 0; i
< clk_hw_get_num_parents(hw
); i
++) {
138 if (clock
->parents
[i
] == hw_index
)
142 pr_err("%s: %s DIV6 clock set to invalid parent %u\n",
143 __func__
, clk_hw_get_name(hw
), hw_index
);
147 static int cpg_div6_clock_set_parent(struct clk_hw
*hw
, u8 index
)
149 struct div6_clock
*clock
= to_div6_clock(hw
);
153 if (index
>= clk_hw_get_num_parents(hw
))
156 mask
= ~((BIT(clock
->src_width
) - 1) << clock
->src_shift
);
157 hw_index
= clock
->parents
[index
];
159 clk_writel((clk_readl(clock
->reg
) & mask
) |
160 (hw_index
<< clock
->src_shift
), clock
->reg
);
165 static const struct clk_ops cpg_div6_clock_ops
= {
166 .enable
= cpg_div6_clock_enable
,
167 .disable
= cpg_div6_clock_disable
,
168 .is_enabled
= cpg_div6_clock_is_enabled
,
169 .get_parent
= cpg_div6_clock_get_parent
,
170 .set_parent
= cpg_div6_clock_set_parent
,
171 .recalc_rate
= cpg_div6_clock_recalc_rate
,
172 .round_rate
= cpg_div6_clock_round_rate
,
173 .set_rate
= cpg_div6_clock_set_rate
,
178 * cpg_div6_register - Register a DIV6 clock
179 * @name: Name of the DIV6 clock
180 * @num_parents: Number of parent clocks of the DIV6 clock (1, 4, or 8)
181 * @parent_names: Array containing the names of the parent clocks
182 * @reg: Mapped register used to control the DIV6 clock
184 struct clk
* __init
cpg_div6_register(const char *name
,
185 unsigned int num_parents
,
186 const char **parent_names
,
189 unsigned int valid_parents
;
190 struct clk_init_data init
;
191 struct div6_clock
*clock
;
195 clock
= kzalloc(sizeof(*clock
), GFP_KERNEL
);
197 return ERR_PTR(-ENOMEM
);
199 clock
->parents
= kmalloc_array(num_parents
, sizeof(*clock
->parents
),
201 if (!clock
->parents
) {
202 clk
= ERR_PTR(-ENOMEM
);
209 * Read the divisor. Disabling the clock overwrites the divisor, so we
210 * need to cache its value for the enable operation.
212 clock
->div
= (clk_readl(clock
->reg
) & CPG_DIV6_DIV_MASK
) + 1;
214 switch (num_parents
) {
216 /* fixed parent clock */
217 clock
->src_shift
= clock
->src_width
= 0;
220 /* clock with EXSRC bits 6-7 */
221 clock
->src_shift
= 6;
222 clock
->src_width
= 2;
225 /* VCLK with EXSRC bits 12-14 */
226 clock
->src_shift
= 12;
227 clock
->src_width
= 3;
230 pr_err("%s: invalid number of parents for DIV6 clock %s\n",
232 clk
= ERR_PTR(-EINVAL
);
236 /* Filter out invalid parents */
237 for (i
= 0, valid_parents
= 0; i
< num_parents
; i
++) {
238 if (parent_names
[i
]) {
239 parent_names
[valid_parents
] = parent_names
[i
];
240 clock
->parents
[valid_parents
] = i
;
245 /* Register the clock. */
247 init
.ops
= &cpg_div6_clock_ops
;
248 init
.flags
= CLK_IS_BASIC
;
249 init
.parent_names
= parent_names
;
250 init
.num_parents
= valid_parents
;
252 clock
->hw
.init
= &init
;
254 clk
= clk_register(NULL
, &clock
->hw
);
261 kfree(clock
->parents
);
267 static void __init
cpg_div6_clock_init(struct device_node
*np
)
269 unsigned int num_parents
;
270 const char **parent_names
;
271 const char *clk_name
= np
->name
;
276 num_parents
= of_clk_get_parent_count(np
);
277 if (num_parents
< 1) {
278 pr_err("%s: no parent found for %s DIV6 clock\n",
283 parent_names
= kmalloc_array(num_parents
, sizeof(*parent_names
),
288 reg
= of_iomap(np
, 0);
290 pr_err("%s: failed to map %s DIV6 clock register\n",
295 /* Parse the DT properties. */
296 of_property_read_string(np
, "clock-output-names", &clk_name
);
298 for (i
= 0; i
< num_parents
; i
++)
299 parent_names
[i
] = of_clk_get_parent_name(np
, i
);
301 clk
= cpg_div6_register(clk_name
, num_parents
, parent_names
, reg
);
303 pr_err("%s: failed to register %s DIV6 clock (%ld)\n",
304 __func__
, np
->name
, PTR_ERR(clk
));
308 of_clk_add_provider(np
, of_clk_src_simple_get
, clk
);
318 CLK_OF_DECLARE(cpg_div6_clk
, "renesas,cpg-div6-clock", cpg_div6_clock_init
);