0001
0002
0003
0004
0005
0006 #include <linux/clk-provider.h>
0007 #include <linux/clkdev.h>
0008 #include <linux/clk/at91_pmc.h>
0009 #include <linux/of.h>
0010 #include <linux/mfd/syscon.h>
0011 #include <linux/regmap.h>
0012
0013 #include "pmc.h"
0014
0015 #define SAM9X5_USB_DIV_SHIFT 8
0016 #define SAM9X5_USB_MAX_DIV 0xf
0017
0018 #define RM9200_USB_DIV_SHIFT 28
0019 #define RM9200_USB_DIV_TAB_SIZE 4
0020
0021 #define SAM9X5_USBS_MASK GENMASK(0, 0)
0022 #define SAM9X60_USBS_MASK GENMASK(1, 0)
0023
0024 struct at91sam9x5_clk_usb {
0025 struct clk_hw hw;
0026 struct regmap *regmap;
0027 struct at91_clk_pms pms;
0028 u32 usbs_mask;
0029 u8 num_parents;
0030 };
0031
0032 #define to_at91sam9x5_clk_usb(hw) \
0033 container_of(hw, struct at91sam9x5_clk_usb, hw)
0034
0035 struct at91rm9200_clk_usb {
0036 struct clk_hw hw;
0037 struct regmap *regmap;
0038 u32 divisors[4];
0039 };
0040
0041 #define to_at91rm9200_clk_usb(hw) \
0042 container_of(hw, struct at91rm9200_clk_usb, hw)
0043
0044 static unsigned long at91sam9x5_clk_usb_recalc_rate(struct clk_hw *hw,
0045 unsigned long parent_rate)
0046 {
0047 struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw);
0048 unsigned int usbr;
0049 u8 usbdiv;
0050
0051 regmap_read(usb->regmap, AT91_PMC_USB, &usbr);
0052 usbdiv = (usbr & AT91_PMC_OHCIUSBDIV) >> SAM9X5_USB_DIV_SHIFT;
0053
0054 return DIV_ROUND_CLOSEST(parent_rate, (usbdiv + 1));
0055 }
0056
0057 static int at91sam9x5_clk_usb_determine_rate(struct clk_hw *hw,
0058 struct clk_rate_request *req)
0059 {
0060 struct clk_hw *parent;
0061 long best_rate = -EINVAL;
0062 unsigned long tmp_rate;
0063 int best_diff = -1;
0064 int tmp_diff;
0065 int i;
0066
0067 for (i = 0; i < clk_hw_get_num_parents(hw); i++) {
0068 int div;
0069
0070 parent = clk_hw_get_parent_by_index(hw, i);
0071 if (!parent)
0072 continue;
0073
0074 for (div = 1; div < SAM9X5_USB_MAX_DIV + 2; div++) {
0075 unsigned long tmp_parent_rate;
0076
0077 tmp_parent_rate = req->rate * div;
0078 tmp_parent_rate = clk_hw_round_rate(parent,
0079 tmp_parent_rate);
0080 if (!tmp_parent_rate)
0081 continue;
0082
0083 tmp_rate = DIV_ROUND_CLOSEST(tmp_parent_rate, div);
0084 if (tmp_rate < req->rate)
0085 tmp_diff = req->rate - tmp_rate;
0086 else
0087 tmp_diff = tmp_rate - req->rate;
0088
0089 if (best_diff < 0 || best_diff > tmp_diff) {
0090 best_rate = tmp_rate;
0091 best_diff = tmp_diff;
0092 req->best_parent_rate = tmp_parent_rate;
0093 req->best_parent_hw = parent;
0094 }
0095
0096 if (!best_diff || tmp_rate < req->rate)
0097 break;
0098 }
0099
0100 if (!best_diff)
0101 break;
0102 }
0103
0104 if (best_rate < 0)
0105 return best_rate;
0106
0107 req->rate = best_rate;
0108 return 0;
0109 }
0110
0111 static int at91sam9x5_clk_usb_set_parent(struct clk_hw *hw, u8 index)
0112 {
0113 struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw);
0114
0115 if (index >= usb->num_parents)
0116 return -EINVAL;
0117
0118 regmap_update_bits(usb->regmap, AT91_PMC_USB, usb->usbs_mask, index);
0119
0120 return 0;
0121 }
0122
0123 static u8 at91sam9x5_clk_usb_get_parent(struct clk_hw *hw)
0124 {
0125 struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw);
0126 unsigned int usbr;
0127
0128 regmap_read(usb->regmap, AT91_PMC_USB, &usbr);
0129
0130 return usbr & usb->usbs_mask;
0131 }
0132
0133 static int at91sam9x5_clk_usb_set_rate(struct clk_hw *hw, unsigned long rate,
0134 unsigned long parent_rate)
0135 {
0136 struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw);
0137 unsigned long div;
0138
0139 if (!rate)
0140 return -EINVAL;
0141
0142 div = DIV_ROUND_CLOSEST(parent_rate, rate);
0143 if (div > SAM9X5_USB_MAX_DIV + 1 || !div)
0144 return -EINVAL;
0145
0146 regmap_update_bits(usb->regmap, AT91_PMC_USB, AT91_PMC_OHCIUSBDIV,
0147 (div - 1) << SAM9X5_USB_DIV_SHIFT);
0148
0149 return 0;
0150 }
0151
0152 static int at91sam9x5_usb_save_context(struct clk_hw *hw)
0153 {
0154 struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw);
0155 struct clk_hw *parent_hw = clk_hw_get_parent(hw);
0156
0157 usb->pms.parent = at91sam9x5_clk_usb_get_parent(hw);
0158 usb->pms.parent_rate = clk_hw_get_rate(parent_hw);
0159 usb->pms.rate = at91sam9x5_clk_usb_recalc_rate(hw, usb->pms.parent_rate);
0160
0161 return 0;
0162 }
0163
0164 static void at91sam9x5_usb_restore_context(struct clk_hw *hw)
0165 {
0166 struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw);
0167 int ret;
0168
0169 ret = at91sam9x5_clk_usb_set_parent(hw, usb->pms.parent);
0170 if (ret)
0171 return;
0172
0173 at91sam9x5_clk_usb_set_rate(hw, usb->pms.rate, usb->pms.parent_rate);
0174 }
0175
0176 static const struct clk_ops at91sam9x5_usb_ops = {
0177 .recalc_rate = at91sam9x5_clk_usb_recalc_rate,
0178 .determine_rate = at91sam9x5_clk_usb_determine_rate,
0179 .get_parent = at91sam9x5_clk_usb_get_parent,
0180 .set_parent = at91sam9x5_clk_usb_set_parent,
0181 .set_rate = at91sam9x5_clk_usb_set_rate,
0182 .save_context = at91sam9x5_usb_save_context,
0183 .restore_context = at91sam9x5_usb_restore_context,
0184 };
0185
0186 static int at91sam9n12_clk_usb_enable(struct clk_hw *hw)
0187 {
0188 struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw);
0189
0190 regmap_update_bits(usb->regmap, AT91_PMC_USB, AT91_PMC_USBS,
0191 AT91_PMC_USBS);
0192
0193 return 0;
0194 }
0195
0196 static void at91sam9n12_clk_usb_disable(struct clk_hw *hw)
0197 {
0198 struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw);
0199
0200 regmap_update_bits(usb->regmap, AT91_PMC_USB, AT91_PMC_USBS, 0);
0201 }
0202
0203 static int at91sam9n12_clk_usb_is_enabled(struct clk_hw *hw)
0204 {
0205 struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw);
0206 unsigned int usbr;
0207
0208 regmap_read(usb->regmap, AT91_PMC_USB, &usbr);
0209
0210 return usbr & AT91_PMC_USBS;
0211 }
0212
0213 static const struct clk_ops at91sam9n12_usb_ops = {
0214 .enable = at91sam9n12_clk_usb_enable,
0215 .disable = at91sam9n12_clk_usb_disable,
0216 .is_enabled = at91sam9n12_clk_usb_is_enabled,
0217 .recalc_rate = at91sam9x5_clk_usb_recalc_rate,
0218 .determine_rate = at91sam9x5_clk_usb_determine_rate,
0219 .set_rate = at91sam9x5_clk_usb_set_rate,
0220 };
0221
0222 static struct clk_hw * __init
0223 _at91sam9x5_clk_register_usb(struct regmap *regmap, const char *name,
0224 const char **parent_names, u8 num_parents,
0225 u32 usbs_mask)
0226 {
0227 struct at91sam9x5_clk_usb *usb;
0228 struct clk_hw *hw;
0229 struct clk_init_data init;
0230 int ret;
0231
0232 usb = kzalloc(sizeof(*usb), GFP_KERNEL);
0233 if (!usb)
0234 return ERR_PTR(-ENOMEM);
0235
0236 init.name = name;
0237 init.ops = &at91sam9x5_usb_ops;
0238 init.parent_names = parent_names;
0239 init.num_parents = num_parents;
0240 init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |
0241 CLK_SET_RATE_PARENT;
0242
0243 usb->hw.init = &init;
0244 usb->regmap = regmap;
0245 usb->usbs_mask = usbs_mask;
0246 usb->num_parents = num_parents;
0247
0248 hw = &usb->hw;
0249 ret = clk_hw_register(NULL, &usb->hw);
0250 if (ret) {
0251 kfree(usb);
0252 hw = ERR_PTR(ret);
0253 }
0254
0255 return hw;
0256 }
0257
0258 struct clk_hw * __init
0259 at91sam9x5_clk_register_usb(struct regmap *regmap, const char *name,
0260 const char **parent_names, u8 num_parents)
0261 {
0262 return _at91sam9x5_clk_register_usb(regmap, name, parent_names,
0263 num_parents, SAM9X5_USBS_MASK);
0264 }
0265
0266 struct clk_hw * __init
0267 sam9x60_clk_register_usb(struct regmap *regmap, const char *name,
0268 const char **parent_names, u8 num_parents)
0269 {
0270 return _at91sam9x5_clk_register_usb(regmap, name, parent_names,
0271 num_parents, SAM9X60_USBS_MASK);
0272 }
0273
0274 struct clk_hw * __init
0275 at91sam9n12_clk_register_usb(struct regmap *regmap, const char *name,
0276 const char *parent_name)
0277 {
0278 struct at91sam9x5_clk_usb *usb;
0279 struct clk_hw *hw;
0280 struct clk_init_data init;
0281 int ret;
0282
0283 usb = kzalloc(sizeof(*usb), GFP_KERNEL);
0284 if (!usb)
0285 return ERR_PTR(-ENOMEM);
0286
0287 init.name = name;
0288 init.ops = &at91sam9n12_usb_ops;
0289 init.parent_names = &parent_name;
0290 init.num_parents = 1;
0291 init.flags = CLK_SET_RATE_GATE | CLK_SET_RATE_PARENT;
0292
0293 usb->hw.init = &init;
0294 usb->regmap = regmap;
0295
0296 hw = &usb->hw;
0297 ret = clk_hw_register(NULL, &usb->hw);
0298 if (ret) {
0299 kfree(usb);
0300 hw = ERR_PTR(ret);
0301 }
0302
0303 return hw;
0304 }
0305
0306 static unsigned long at91rm9200_clk_usb_recalc_rate(struct clk_hw *hw,
0307 unsigned long parent_rate)
0308 {
0309 struct at91rm9200_clk_usb *usb = to_at91rm9200_clk_usb(hw);
0310 unsigned int pllbr;
0311 u8 usbdiv;
0312
0313 regmap_read(usb->regmap, AT91_CKGR_PLLBR, &pllbr);
0314
0315 usbdiv = (pllbr & AT91_PMC_USBDIV) >> RM9200_USB_DIV_SHIFT;
0316 if (usb->divisors[usbdiv])
0317 return parent_rate / usb->divisors[usbdiv];
0318
0319 return 0;
0320 }
0321
0322 static long at91rm9200_clk_usb_round_rate(struct clk_hw *hw, unsigned long rate,
0323 unsigned long *parent_rate)
0324 {
0325 struct at91rm9200_clk_usb *usb = to_at91rm9200_clk_usb(hw);
0326 struct clk_hw *parent = clk_hw_get_parent(hw);
0327 unsigned long bestrate = 0;
0328 int bestdiff = -1;
0329 unsigned long tmprate;
0330 int tmpdiff;
0331 int i = 0;
0332
0333 for (i = 0; i < RM9200_USB_DIV_TAB_SIZE; i++) {
0334 unsigned long tmp_parent_rate;
0335
0336 if (!usb->divisors[i])
0337 continue;
0338
0339 tmp_parent_rate = rate * usb->divisors[i];
0340 tmp_parent_rate = clk_hw_round_rate(parent, tmp_parent_rate);
0341 tmprate = DIV_ROUND_CLOSEST(tmp_parent_rate, usb->divisors[i]);
0342 if (tmprate < rate)
0343 tmpdiff = rate - tmprate;
0344 else
0345 tmpdiff = tmprate - rate;
0346
0347 if (bestdiff < 0 || bestdiff > tmpdiff) {
0348 bestrate = tmprate;
0349 bestdiff = tmpdiff;
0350 *parent_rate = tmp_parent_rate;
0351 }
0352
0353 if (!bestdiff)
0354 break;
0355 }
0356
0357 return bestrate;
0358 }
0359
0360 static int at91rm9200_clk_usb_set_rate(struct clk_hw *hw, unsigned long rate,
0361 unsigned long parent_rate)
0362 {
0363 int i;
0364 struct at91rm9200_clk_usb *usb = to_at91rm9200_clk_usb(hw);
0365 unsigned long div;
0366
0367 if (!rate)
0368 return -EINVAL;
0369
0370 div = DIV_ROUND_CLOSEST(parent_rate, rate);
0371
0372 for (i = 0; i < RM9200_USB_DIV_TAB_SIZE; i++) {
0373 if (usb->divisors[i] == div) {
0374 regmap_update_bits(usb->regmap, AT91_CKGR_PLLBR,
0375 AT91_PMC_USBDIV,
0376 i << RM9200_USB_DIV_SHIFT);
0377
0378 return 0;
0379 }
0380 }
0381
0382 return -EINVAL;
0383 }
0384
0385 static const struct clk_ops at91rm9200_usb_ops = {
0386 .recalc_rate = at91rm9200_clk_usb_recalc_rate,
0387 .round_rate = at91rm9200_clk_usb_round_rate,
0388 .set_rate = at91rm9200_clk_usb_set_rate,
0389 };
0390
0391 struct clk_hw * __init
0392 at91rm9200_clk_register_usb(struct regmap *regmap, const char *name,
0393 const char *parent_name, const u32 *divisors)
0394 {
0395 struct at91rm9200_clk_usb *usb;
0396 struct clk_hw *hw;
0397 struct clk_init_data init;
0398 int ret;
0399
0400 usb = kzalloc(sizeof(*usb), GFP_KERNEL);
0401 if (!usb)
0402 return ERR_PTR(-ENOMEM);
0403
0404 init.name = name;
0405 init.ops = &at91rm9200_usb_ops;
0406 init.parent_names = &parent_name;
0407 init.num_parents = 1;
0408 init.flags = CLK_SET_RATE_PARENT;
0409
0410 usb->hw.init = &init;
0411 usb->regmap = regmap;
0412 memcpy(usb->divisors, divisors, sizeof(usb->divisors));
0413
0414 hw = &usb->hw;
0415 ret = clk_hw_register(NULL, &usb->hw);
0416 if (ret) {
0417 kfree(usb);
0418 hw = ERR_PTR(ret);
0419 }
0420
0421 return hw;
0422 }