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 SAM9X5_USB_DIV_SHIFT 8
21 #define SAM9X5_USB_MAX_DIV 0xf
23 #define RM9200_USB_DIV_SHIFT 28
24 #define RM9200_USB_DIV_TAB_SIZE 4
26 #define SAM9X5_USBS_MASK GENMASK(0, 0)
27 #define SAM9X60_USBS_MASK GENMASK(1, 0)
29 struct at91sam9x5_clk_usb {
31 struct regmap *regmap;
35 #define to_at91sam9x5_clk_usb(hw) \
36 container_of(hw, struct at91sam9x5_clk_usb, hw)
38 struct at91rm9200_clk_usb {
40 struct regmap *regmap;
44 #define to_at91rm9200_clk_usb(hw) \
45 container_of(hw, struct at91rm9200_clk_usb, hw)
47 static unsigned long at91sam9x5_clk_usb_recalc_rate(struct clk_hw *hw,
48 unsigned long parent_rate)
50 struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw);
54 regmap_read(usb->regmap, AT91_PMC_USB, &usbr);
55 usbdiv = (usbr & AT91_PMC_OHCIUSBDIV) >> SAM9X5_USB_DIV_SHIFT;
57 return DIV_ROUND_CLOSEST(parent_rate, (usbdiv + 1));
60 static int at91sam9x5_clk_usb_determine_rate(struct clk_hw *hw,
61 struct clk_rate_request *req)
63 struct clk_hw *parent;
64 long best_rate = -EINVAL;
65 unsigned long tmp_rate;
70 for (i = 0; i < clk_hw_get_num_parents(hw); i++) {
73 parent = clk_hw_get_parent_by_index(hw, i);
77 for (div = 1; div < SAM9X5_USB_MAX_DIV + 2; div++) {
78 unsigned long tmp_parent_rate;
80 tmp_parent_rate = req->rate * div;
81 tmp_parent_rate = clk_hw_round_rate(parent,
83 tmp_rate = DIV_ROUND_CLOSEST(tmp_parent_rate, div);
84 if (tmp_rate < req->rate)
85 tmp_diff = req->rate - tmp_rate;
87 tmp_diff = tmp_rate - req->rate;
89 if (best_diff < 0 || best_diff > tmp_diff) {
92 req->best_parent_rate = tmp_parent_rate;
93 req->best_parent_hw = parent;
96 if (!best_diff || tmp_rate < req->rate)
107 req->rate = best_rate;
111 static int at91sam9x5_clk_usb_set_parent(struct clk_hw *hw, u8 index)
113 struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw);
118 regmap_update_bits(usb->regmap, AT91_PMC_USB, usb->usbs_mask, index);
123 static u8 at91sam9x5_clk_usb_get_parent(struct clk_hw *hw)
125 struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw);
128 regmap_read(usb->regmap, AT91_PMC_USB, &usbr);
130 return usbr & usb->usbs_mask;
133 static int at91sam9x5_clk_usb_set_rate(struct clk_hw *hw, unsigned long rate,
134 unsigned long parent_rate)
136 struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw);
142 div = DIV_ROUND_CLOSEST(parent_rate, rate);
143 if (div > SAM9X5_USB_MAX_DIV + 1 || !div)
146 regmap_update_bits(usb->regmap, AT91_PMC_USB, AT91_PMC_OHCIUSBDIV,
147 (div - 1) << SAM9X5_USB_DIV_SHIFT);
152 static const struct clk_ops at91sam9x5_usb_ops = {
153 .recalc_rate = at91sam9x5_clk_usb_recalc_rate,
154 .determine_rate = at91sam9x5_clk_usb_determine_rate,
155 .get_parent = at91sam9x5_clk_usb_get_parent,
156 .set_parent = at91sam9x5_clk_usb_set_parent,
157 .set_rate = at91sam9x5_clk_usb_set_rate,
160 static int at91sam9n12_clk_usb_enable(struct clk_hw *hw)
162 struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw);
164 regmap_update_bits(usb->regmap, AT91_PMC_USB, AT91_PMC_USBS,
170 static void at91sam9n12_clk_usb_disable(struct clk_hw *hw)
172 struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw);
174 regmap_update_bits(usb->regmap, AT91_PMC_USB, AT91_PMC_USBS, 0);
177 static int at91sam9n12_clk_usb_is_enabled(struct clk_hw *hw)
179 struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw);
182 regmap_read(usb->regmap, AT91_PMC_USB, &usbr);
184 return usbr & AT91_PMC_USBS;
187 static const struct clk_ops at91sam9n12_usb_ops = {
188 .enable = at91sam9n12_clk_usb_enable,
189 .disable = at91sam9n12_clk_usb_disable,
190 .is_enabled = at91sam9n12_clk_usb_is_enabled,
191 .recalc_rate = at91sam9x5_clk_usb_recalc_rate,
192 .determine_rate = at91sam9x5_clk_usb_determine_rate,
193 .set_rate = at91sam9x5_clk_usb_set_rate,
196 static struct clk_hw * __init
197 _at91sam9x5_clk_register_usb(struct regmap *regmap, const char *name,
198 const char **parent_names, u8 num_parents,
201 struct at91sam9x5_clk_usb *usb;
203 struct clk_init_data init;
206 usb = kzalloc(sizeof(*usb), GFP_KERNEL);
208 return ERR_PTR(-ENOMEM);
211 init.ops = &at91sam9x5_usb_ops;
212 init.parent_names = parent_names;
213 init.num_parents = num_parents;
214 init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |
217 usb->hw.init = &init;
218 usb->regmap = regmap;
219 usb->usbs_mask = SAM9X5_USBS_MASK;
222 ret = clk_hw_register(NULL, &usb->hw);
231 struct clk_hw * __init
232 at91sam9x5_clk_register_usb(struct regmap *regmap, const char *name,
233 const char **parent_names, u8 num_parents)
235 return _at91sam9x5_clk_register_usb(regmap, name, parent_names,
236 num_parents, SAM9X5_USBS_MASK);
239 struct clk_hw * __init
240 sam9x60_clk_register_usb(struct regmap *regmap, const char *name,
241 const char **parent_names, u8 num_parents)
243 return _at91sam9x5_clk_register_usb(regmap, name, parent_names,
244 num_parents, SAM9X60_USBS_MASK);
247 struct clk_hw * __init
248 at91sam9n12_clk_register_usb(struct regmap *regmap, const char *name,
249 const char *parent_name)
251 struct at91sam9x5_clk_usb *usb;
253 struct clk_init_data init;
256 usb = kzalloc(sizeof(*usb), GFP_KERNEL);
258 return ERR_PTR(-ENOMEM);
261 init.ops = &at91sam9n12_usb_ops;
262 init.parent_names = &parent_name;
263 init.num_parents = 1;
264 init.flags = CLK_SET_RATE_GATE | CLK_SET_RATE_PARENT;
266 usb->hw.init = &init;
267 usb->regmap = regmap;
270 ret = clk_hw_register(NULL, &usb->hw);
279 static unsigned long at91rm9200_clk_usb_recalc_rate(struct clk_hw *hw,
280 unsigned long parent_rate)
282 struct at91rm9200_clk_usb *usb = to_at91rm9200_clk_usb(hw);
286 regmap_read(usb->regmap, AT91_CKGR_PLLBR, &pllbr);
288 usbdiv = (pllbr & AT91_PMC_USBDIV) >> RM9200_USB_DIV_SHIFT;
289 if (usb->divisors[usbdiv])
290 return parent_rate / usb->divisors[usbdiv];
295 static long at91rm9200_clk_usb_round_rate(struct clk_hw *hw, unsigned long rate,
296 unsigned long *parent_rate)
298 struct at91rm9200_clk_usb *usb = to_at91rm9200_clk_usb(hw);
299 struct clk_hw *parent = clk_hw_get_parent(hw);
300 unsigned long bestrate = 0;
302 unsigned long tmprate;
306 for (i = 0; i < RM9200_USB_DIV_TAB_SIZE; i++) {
307 unsigned long tmp_parent_rate;
309 if (!usb->divisors[i])
312 tmp_parent_rate = rate * usb->divisors[i];
313 tmp_parent_rate = clk_hw_round_rate(parent, tmp_parent_rate);
314 tmprate = DIV_ROUND_CLOSEST(tmp_parent_rate, usb->divisors[i]);
316 tmpdiff = rate - tmprate;
318 tmpdiff = tmprate - rate;
320 if (bestdiff < 0 || bestdiff > tmpdiff) {
323 *parent_rate = tmp_parent_rate;
333 static int at91rm9200_clk_usb_set_rate(struct clk_hw *hw, unsigned long rate,
334 unsigned long parent_rate)
337 struct at91rm9200_clk_usb *usb = to_at91rm9200_clk_usb(hw);
343 div = DIV_ROUND_CLOSEST(parent_rate, rate);
345 for (i = 0; i < RM9200_USB_DIV_TAB_SIZE; i++) {
346 if (usb->divisors[i] == div) {
347 regmap_update_bits(usb->regmap, AT91_CKGR_PLLBR,
349 i << RM9200_USB_DIV_SHIFT);
358 static const struct clk_ops at91rm9200_usb_ops = {
359 .recalc_rate = at91rm9200_clk_usb_recalc_rate,
360 .round_rate = at91rm9200_clk_usb_round_rate,
361 .set_rate = at91rm9200_clk_usb_set_rate,
364 struct clk_hw * __init
365 at91rm9200_clk_register_usb(struct regmap *regmap, const char *name,
366 const char *parent_name, const u32 *divisors)
368 struct at91rm9200_clk_usb *usb;
370 struct clk_init_data init;
373 usb = kzalloc(sizeof(*usb), GFP_KERNEL);
375 return ERR_PTR(-ENOMEM);
378 init.ops = &at91rm9200_usb_ops;
379 init.parent_names = &parent_name;
380 init.num_parents = 1;
381 init.flags = CLK_SET_RATE_PARENT;
383 usb->hw.init = &init;
384 usb->regmap = regmap;
385 memcpy(usb->divisors, divisors, sizeof(usb->divisors));
388 ret = clk_hw_register(NULL, &usb->hw);