2 * Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
11 #include <linux/clk-provider.h>
12 #include <linux/clkdev.h>
13 #include <linux/clk/at91_pmc.h>
15 #include <linux/mfd/syscon.h>
16 #include <linux/regmap.h>
20 #define USB_SOURCE_MAX 2
22 #define SAM9X5_USB_DIV_SHIFT 8
23 #define SAM9X5_USB_MAX_DIV 0xf
25 #define RM9200_USB_DIV_SHIFT 28
26 #define RM9200_USB_DIV_TAB_SIZE 4
28 struct at91sam9x5_clk_usb
{
30 struct regmap
*regmap
;
33 #define to_at91sam9x5_clk_usb(hw) \
34 container_of(hw, struct at91sam9x5_clk_usb, hw)
36 struct at91rm9200_clk_usb
{
38 struct regmap
*regmap
;
42 #define to_at91rm9200_clk_usb(hw) \
43 container_of(hw, struct at91rm9200_clk_usb, hw)
45 static unsigned long at91sam9x5_clk_usb_recalc_rate(struct clk_hw
*hw
,
46 unsigned long parent_rate
)
48 struct at91sam9x5_clk_usb
*usb
= to_at91sam9x5_clk_usb(hw
);
52 regmap_read(usb
->regmap
, AT91_PMC_USB
, &usbr
);
53 usbdiv
= (usbr
& AT91_PMC_OHCIUSBDIV
) >> SAM9X5_USB_DIV_SHIFT
;
55 return DIV_ROUND_CLOSEST(parent_rate
, (usbdiv
+ 1));
58 static int at91sam9x5_clk_usb_determine_rate(struct clk_hw
*hw
,
59 struct clk_rate_request
*req
)
61 struct clk_hw
*parent
;
62 long best_rate
= -EINVAL
;
63 unsigned long tmp_rate
;
68 for (i
= 0; i
< clk_hw_get_num_parents(hw
); i
++) {
71 parent
= clk_hw_get_parent_by_index(hw
, i
);
75 for (div
= 1; div
< SAM9X5_USB_MAX_DIV
+ 2; div
++) {
76 unsigned long tmp_parent_rate
;
78 tmp_parent_rate
= req
->rate
* div
;
79 tmp_parent_rate
= clk_hw_round_rate(parent
,
81 tmp_rate
= DIV_ROUND_CLOSEST(tmp_parent_rate
, div
);
82 if (tmp_rate
< req
->rate
)
83 tmp_diff
= req
->rate
- tmp_rate
;
85 tmp_diff
= tmp_rate
- req
->rate
;
87 if (best_diff
< 0 || best_diff
> tmp_diff
) {
90 req
->best_parent_rate
= tmp_parent_rate
;
91 req
->best_parent_hw
= parent
;
94 if (!best_diff
|| tmp_rate
< req
->rate
)
105 req
->rate
= best_rate
;
109 static int at91sam9x5_clk_usb_set_parent(struct clk_hw
*hw
, u8 index
)
111 struct at91sam9x5_clk_usb
*usb
= to_at91sam9x5_clk_usb(hw
);
116 regmap_update_bits(usb
->regmap
, AT91_PMC_USB
, AT91_PMC_USBS
,
117 index
? AT91_PMC_USBS
: 0);
122 static u8
at91sam9x5_clk_usb_get_parent(struct clk_hw
*hw
)
124 struct at91sam9x5_clk_usb
*usb
= to_at91sam9x5_clk_usb(hw
);
127 regmap_read(usb
->regmap
, AT91_PMC_USB
, &usbr
);
129 return usbr
& AT91_PMC_USBS
;
132 static int at91sam9x5_clk_usb_set_rate(struct clk_hw
*hw
, unsigned long rate
,
133 unsigned long parent_rate
)
135 struct at91sam9x5_clk_usb
*usb
= to_at91sam9x5_clk_usb(hw
);
141 div
= DIV_ROUND_CLOSEST(parent_rate
, rate
);
142 if (div
> SAM9X5_USB_MAX_DIV
+ 1 || !div
)
145 regmap_update_bits(usb
->regmap
, AT91_PMC_USB
, AT91_PMC_OHCIUSBDIV
,
146 (div
- 1) << SAM9X5_USB_DIV_SHIFT
);
151 static const struct clk_ops at91sam9x5_usb_ops
= {
152 .recalc_rate
= at91sam9x5_clk_usb_recalc_rate
,
153 .determine_rate
= at91sam9x5_clk_usb_determine_rate
,
154 .get_parent
= at91sam9x5_clk_usb_get_parent
,
155 .set_parent
= at91sam9x5_clk_usb_set_parent
,
156 .set_rate
= at91sam9x5_clk_usb_set_rate
,
159 static int at91sam9n12_clk_usb_enable(struct clk_hw
*hw
)
161 struct at91sam9x5_clk_usb
*usb
= to_at91sam9x5_clk_usb(hw
);
163 regmap_update_bits(usb
->regmap
, AT91_PMC_USB
, AT91_PMC_USBS
,
169 static void at91sam9n12_clk_usb_disable(struct clk_hw
*hw
)
171 struct at91sam9x5_clk_usb
*usb
= to_at91sam9x5_clk_usb(hw
);
173 regmap_update_bits(usb
->regmap
, AT91_PMC_USB
, AT91_PMC_USBS
, 0);
176 static int at91sam9n12_clk_usb_is_enabled(struct clk_hw
*hw
)
178 struct at91sam9x5_clk_usb
*usb
= to_at91sam9x5_clk_usb(hw
);
181 regmap_read(usb
->regmap
, AT91_PMC_USB
, &usbr
);
183 return usbr
& AT91_PMC_USBS
;
186 static const struct clk_ops at91sam9n12_usb_ops
= {
187 .enable
= at91sam9n12_clk_usb_enable
,
188 .disable
= at91sam9n12_clk_usb_disable
,
189 .is_enabled
= at91sam9n12_clk_usb_is_enabled
,
190 .recalc_rate
= at91sam9x5_clk_usb_recalc_rate
,
191 .determine_rate
= at91sam9x5_clk_usb_determine_rate
,
192 .set_rate
= at91sam9x5_clk_usb_set_rate
,
195 static struct clk_hw
* __init
196 at91sam9x5_clk_register_usb(struct regmap
*regmap
, const char *name
,
197 const char **parent_names
, u8 num_parents
)
199 struct at91sam9x5_clk_usb
*usb
;
201 struct clk_init_data init
;
204 usb
= kzalloc(sizeof(*usb
), GFP_KERNEL
);
206 return ERR_PTR(-ENOMEM
);
209 init
.ops
= &at91sam9x5_usb_ops
;
210 init
.parent_names
= parent_names
;
211 init
.num_parents
= num_parents
;
212 init
.flags
= CLK_SET_RATE_GATE
| CLK_SET_PARENT_GATE
|
215 usb
->hw
.init
= &init
;
216 usb
->regmap
= regmap
;
219 ret
= clk_hw_register(NULL
, &usb
->hw
);
228 static struct clk_hw
* __init
229 at91sam9n12_clk_register_usb(struct regmap
*regmap
, const char *name
,
230 const char *parent_name
)
232 struct at91sam9x5_clk_usb
*usb
;
234 struct clk_init_data init
;
237 usb
= kzalloc(sizeof(*usb
), GFP_KERNEL
);
239 return ERR_PTR(-ENOMEM
);
242 init
.ops
= &at91sam9n12_usb_ops
;
243 init
.parent_names
= &parent_name
;
244 init
.num_parents
= 1;
245 init
.flags
= CLK_SET_RATE_GATE
| CLK_SET_RATE_PARENT
;
247 usb
->hw
.init
= &init
;
248 usb
->regmap
= regmap
;
251 ret
= clk_hw_register(NULL
, &usb
->hw
);
260 static unsigned long at91rm9200_clk_usb_recalc_rate(struct clk_hw
*hw
,
261 unsigned long parent_rate
)
263 struct at91rm9200_clk_usb
*usb
= to_at91rm9200_clk_usb(hw
);
267 regmap_read(usb
->regmap
, AT91_CKGR_PLLBR
, &pllbr
);
269 usbdiv
= (pllbr
& AT91_PMC_USBDIV
) >> RM9200_USB_DIV_SHIFT
;
270 if (usb
->divisors
[usbdiv
])
271 return parent_rate
/ usb
->divisors
[usbdiv
];
276 static long at91rm9200_clk_usb_round_rate(struct clk_hw
*hw
, unsigned long rate
,
277 unsigned long *parent_rate
)
279 struct at91rm9200_clk_usb
*usb
= to_at91rm9200_clk_usb(hw
);
280 struct clk_hw
*parent
= clk_hw_get_parent(hw
);
281 unsigned long bestrate
= 0;
283 unsigned long tmprate
;
287 for (i
= 0; i
< RM9200_USB_DIV_TAB_SIZE
; i
++) {
288 unsigned long tmp_parent_rate
;
290 if (!usb
->divisors
[i
])
293 tmp_parent_rate
= rate
* usb
->divisors
[i
];
294 tmp_parent_rate
= clk_hw_round_rate(parent
, tmp_parent_rate
);
295 tmprate
= DIV_ROUND_CLOSEST(tmp_parent_rate
, usb
->divisors
[i
]);
297 tmpdiff
= rate
- tmprate
;
299 tmpdiff
= tmprate
- rate
;
301 if (bestdiff
< 0 || bestdiff
> tmpdiff
) {
304 *parent_rate
= tmp_parent_rate
;
314 static int at91rm9200_clk_usb_set_rate(struct clk_hw
*hw
, unsigned long rate
,
315 unsigned long parent_rate
)
318 struct at91rm9200_clk_usb
*usb
= to_at91rm9200_clk_usb(hw
);
324 div
= DIV_ROUND_CLOSEST(parent_rate
, rate
);
326 for (i
= 0; i
< RM9200_USB_DIV_TAB_SIZE
; i
++) {
327 if (usb
->divisors
[i
] == div
) {
328 regmap_update_bits(usb
->regmap
, AT91_CKGR_PLLBR
,
330 i
<< RM9200_USB_DIV_SHIFT
);
339 static const struct clk_ops at91rm9200_usb_ops
= {
340 .recalc_rate
= at91rm9200_clk_usb_recalc_rate
,
341 .round_rate
= at91rm9200_clk_usb_round_rate
,
342 .set_rate
= at91rm9200_clk_usb_set_rate
,
345 static struct clk_hw
* __init
346 at91rm9200_clk_register_usb(struct regmap
*regmap
, const char *name
,
347 const char *parent_name
, const u32
*divisors
)
349 struct at91rm9200_clk_usb
*usb
;
351 struct clk_init_data init
;
354 usb
= kzalloc(sizeof(*usb
), GFP_KERNEL
);
356 return ERR_PTR(-ENOMEM
);
359 init
.ops
= &at91rm9200_usb_ops
;
360 init
.parent_names
= &parent_name
;
361 init
.num_parents
= 1;
362 init
.flags
= CLK_SET_RATE_PARENT
;
364 usb
->hw
.init
= &init
;
365 usb
->regmap
= regmap
;
366 memcpy(usb
->divisors
, divisors
, sizeof(usb
->divisors
));
369 ret
= clk_hw_register(NULL
, &usb
->hw
);
378 static void __init
of_at91sam9x5_clk_usb_setup(struct device_node
*np
)
381 unsigned int num_parents
;
382 const char *parent_names
[USB_SOURCE_MAX
];
383 const char *name
= np
->name
;
384 struct regmap
*regmap
;
386 num_parents
= of_clk_get_parent_count(np
);
387 if (num_parents
== 0 || num_parents
> USB_SOURCE_MAX
)
390 of_clk_parent_fill(np
, parent_names
, num_parents
);
392 of_property_read_string(np
, "clock-output-names", &name
);
394 regmap
= syscon_node_to_regmap(of_get_parent(np
));
398 hw
= at91sam9x5_clk_register_usb(regmap
, name
, parent_names
,
403 of_clk_add_hw_provider(np
, of_clk_hw_simple_get
, hw
);
405 CLK_OF_DECLARE(at91sam9x5_clk_usb
, "atmel,at91sam9x5-clk-usb",
406 of_at91sam9x5_clk_usb_setup
);
408 static void __init
of_at91sam9n12_clk_usb_setup(struct device_node
*np
)
411 const char *parent_name
;
412 const char *name
= np
->name
;
413 struct regmap
*regmap
;
415 parent_name
= of_clk_get_parent_name(np
, 0);
419 of_property_read_string(np
, "clock-output-names", &name
);
421 regmap
= syscon_node_to_regmap(of_get_parent(np
));
425 hw
= at91sam9n12_clk_register_usb(regmap
, name
, parent_name
);
429 of_clk_add_hw_provider(np
, of_clk_hw_simple_get
, hw
);
431 CLK_OF_DECLARE(at91sam9n12_clk_usb
, "atmel,at91sam9n12-clk-usb",
432 of_at91sam9n12_clk_usb_setup
);
434 static void __init
of_at91rm9200_clk_usb_setup(struct device_node
*np
)
437 const char *parent_name
;
438 const char *name
= np
->name
;
439 u32 divisors
[4] = {0, 0, 0, 0};
440 struct regmap
*regmap
;
442 parent_name
= of_clk_get_parent_name(np
, 0);
446 of_property_read_u32_array(np
, "atmel,clk-divisors", divisors
, 4);
450 of_property_read_string(np
, "clock-output-names", &name
);
452 regmap
= syscon_node_to_regmap(of_get_parent(np
));
455 hw
= at91rm9200_clk_register_usb(regmap
, name
, parent_name
, divisors
);
459 of_clk_add_hw_provider(np
, of_clk_hw_simple_get
, hw
);
461 CLK_OF_DECLARE(at91rm9200_clk_usb
, "atmel,at91rm9200-clk-usb",
462 of_at91rm9200_clk_usb_setup
);