1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com>
6 #include <linux/clk-provider.h>
7 #include <linux/clkdev.h>
8 #include <linux/clk/at91_pmc.h>
10 #include <linux/mfd/syscon.h>
11 #include <linux/regmap.h>
17 #define PROG_STATUS_MASK(id) (1 << ((id) + 8))
18 #define PROG_PRES(layout, pckr) ((pckr >> layout->pres_shift) & layout->pres_mask)
19 #define PROG_MAX_RM9200_CSS 3
21 struct clk_programmable
{
23 struct regmap
*regmap
;
26 const struct clk_programmable_layout
*layout
;
29 #define to_clk_programmable(hw) container_of(hw, struct clk_programmable, hw)
31 static unsigned long clk_programmable_recalc_rate(struct clk_hw
*hw
,
32 unsigned long parent_rate
)
34 struct clk_programmable
*prog
= to_clk_programmable(hw
);
35 const struct clk_programmable_layout
*layout
= prog
->layout
;
39 regmap_read(prog
->regmap
, AT91_PMC_PCKR(prog
->id
), &pckr
);
41 if (layout
->is_pres_direct
)
42 rate
= parent_rate
/ (PROG_PRES(layout
, pckr
) + 1);
44 rate
= parent_rate
>> PROG_PRES(layout
, pckr
);
49 static int clk_programmable_determine_rate(struct clk_hw
*hw
,
50 struct clk_rate_request
*req
)
52 struct clk_programmable
*prog
= to_clk_programmable(hw
);
53 const struct clk_programmable_layout
*layout
= prog
->layout
;
54 struct clk_hw
*parent
;
55 long best_rate
= -EINVAL
;
56 unsigned long parent_rate
;
57 unsigned long tmp_rate
= 0;
61 for (i
= 0; i
< clk_hw_get_num_parents(hw
); i
++) {
62 parent
= clk_hw_get_parent_by_index(hw
, i
);
66 parent_rate
= clk_hw_get_rate(parent
);
67 if (layout
->is_pres_direct
) {
68 for (shift
= 0; shift
<= layout
->pres_mask
; shift
++) {
69 tmp_rate
= parent_rate
/ (shift
+ 1);
70 if (tmp_rate
<= req
->rate
)
74 for (shift
= 0; shift
< layout
->pres_mask
; shift
++) {
75 tmp_rate
= parent_rate
>> shift
;
76 if (tmp_rate
<= req
->rate
)
81 if (tmp_rate
> req
->rate
)
85 (req
->rate
- tmp_rate
) < (req
->rate
- best_rate
)) {
87 req
->best_parent_rate
= parent_rate
;
88 req
->best_parent_hw
= parent
;
98 req
->rate
= best_rate
;
102 static int clk_programmable_set_parent(struct clk_hw
*hw
, u8 index
)
104 struct clk_programmable
*prog
= to_clk_programmable(hw
);
105 const struct clk_programmable_layout
*layout
= prog
->layout
;
106 unsigned int mask
= layout
->css_mask
;
107 unsigned int pckr
= index
;
109 if (layout
->have_slck_mck
)
110 mask
|= AT91_PMC_CSSMCK_MCK
;
113 pckr
= clk_mux_index_to_val(prog
->mux_table
, 0, index
);
115 if (index
> layout
->css_mask
) {
116 if (index
> PROG_MAX_RM9200_CSS
&& !layout
->have_slck_mck
)
119 pckr
|= AT91_PMC_CSSMCK_MCK
;
122 regmap_update_bits(prog
->regmap
, AT91_PMC_PCKR(prog
->id
), mask
, pckr
);
127 static u8
clk_programmable_get_parent(struct clk_hw
*hw
)
129 struct clk_programmable
*prog
= to_clk_programmable(hw
);
130 const struct clk_programmable_layout
*layout
= prog
->layout
;
134 regmap_read(prog
->regmap
, AT91_PMC_PCKR(prog
->id
), &pckr
);
136 ret
= pckr
& layout
->css_mask
;
138 if (layout
->have_slck_mck
&& (pckr
& AT91_PMC_CSSMCK_MCK
) && !ret
)
139 ret
= PROG_MAX_RM9200_CSS
+ 1;
142 ret
= clk_mux_val_to_index(&prog
->hw
, prog
->mux_table
, 0, ret
);
147 static int clk_programmable_set_rate(struct clk_hw
*hw
, unsigned long rate
,
148 unsigned long parent_rate
)
150 struct clk_programmable
*prog
= to_clk_programmable(hw
);
151 const struct clk_programmable_layout
*layout
= prog
->layout
;
152 unsigned long div
= parent_rate
/ rate
;
158 if (layout
->is_pres_direct
) {
161 if (shift
> layout
->pres_mask
)
164 shift
= fls(div
) - 1;
166 if (div
!= (1 << shift
))
169 if (shift
>= layout
->pres_mask
)
173 regmap_update_bits(prog
->regmap
, AT91_PMC_PCKR(prog
->id
),
174 layout
->pres_mask
<< layout
->pres_shift
,
175 shift
<< layout
->pres_shift
);
180 static const struct clk_ops programmable_ops
= {
181 .recalc_rate
= clk_programmable_recalc_rate
,
182 .determine_rate
= clk_programmable_determine_rate
,
183 .get_parent
= clk_programmable_get_parent
,
184 .set_parent
= clk_programmable_set_parent
,
185 .set_rate
= clk_programmable_set_rate
,
188 struct clk_hw
* __init
189 at91_clk_register_programmable(struct regmap
*regmap
,
190 const char *name
, const char **parent_names
,
191 u8 num_parents
, u8 id
,
192 const struct clk_programmable_layout
*layout
,
195 struct clk_programmable
*prog
;
197 struct clk_init_data init
;
200 if (id
> PROG_ID_MAX
)
201 return ERR_PTR(-EINVAL
);
203 prog
= kzalloc(sizeof(*prog
), GFP_KERNEL
);
205 return ERR_PTR(-ENOMEM
);
208 init
.ops
= &programmable_ops
;
209 init
.parent_names
= parent_names
;
210 init
.num_parents
= num_parents
;
211 init
.flags
= CLK_SET_RATE_GATE
| CLK_SET_PARENT_GATE
;
214 prog
->layout
= layout
;
215 prog
->hw
.init
= &init
;
216 prog
->regmap
= regmap
;
217 prog
->mux_table
= mux_table
;
220 ret
= clk_hw_register(NULL
, &prog
->hw
);
225 pmc_register_pck(id
);
231 const struct clk_programmable_layout at91rm9200_programmable_layout
= {
239 const struct clk_programmable_layout at91sam9g45_programmable_layout
= {
247 const struct clk_programmable_layout at91sam9x5_programmable_layout
= {