1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com> 4 */ 5 6 #include <linux/clk-provider.h> 7 #include <linux/clkdev.h> 8 #include <linux/clk/at91_pmc.h> 9 #include <linux/of.h> 10 #include <linux/mfd/syscon.h> 11 #include <linux/regmap.h> 12 13 #include "pmc.h" 14 15 #define SAM9X5_USB_DIV_SHIFT 8 16 #define SAM9X5_USB_MAX_DIV 0xf 17 18 #define RM9200_USB_DIV_SHIFT 28 19 #define RM9200_USB_DIV_TAB_SIZE 4 20 21 #define SAM9X5_USBS_MASK GENMASK(0, 0) 22 #define SAM9X60_USBS_MASK GENMASK(1, 0) 23 24 struct at91sam9x5_clk_usb { 25 struct clk_hw hw; 26 struct regmap *regmap; 27 u32 usbs_mask; 28 u8 num_parents; 29 }; 30 31 #define to_at91sam9x5_clk_usb(hw) \ 32 container_of(hw, struct at91sam9x5_clk_usb, hw) 33 34 struct at91rm9200_clk_usb { 35 struct clk_hw hw; 36 struct regmap *regmap; 37 u32 divisors[4]; 38 }; 39 40 #define to_at91rm9200_clk_usb(hw) \ 41 container_of(hw, struct at91rm9200_clk_usb, hw) 42 43 static unsigned long at91sam9x5_clk_usb_recalc_rate(struct clk_hw *hw, 44 unsigned long parent_rate) 45 { 46 struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw); 47 unsigned int usbr; 48 u8 usbdiv; 49 50 regmap_read(usb->regmap, AT91_PMC_USB, &usbr); 51 usbdiv = (usbr & AT91_PMC_OHCIUSBDIV) >> SAM9X5_USB_DIV_SHIFT; 52 53 return DIV_ROUND_CLOSEST(parent_rate, (usbdiv + 1)); 54 } 55 56 static int at91sam9x5_clk_usb_determine_rate(struct clk_hw *hw, 57 struct clk_rate_request *req) 58 { 59 struct clk_hw *parent; 60 long best_rate = -EINVAL; 61 unsigned long tmp_rate; 62 int best_diff = -1; 63 int tmp_diff; 64 int i; 65 66 for (i = 0; i < clk_hw_get_num_parents(hw); i++) { 67 int div; 68 69 parent = clk_hw_get_parent_by_index(hw, i); 70 if (!parent) 71 continue; 72 73 for (div = 1; div < SAM9X5_USB_MAX_DIV + 2; div++) { 74 unsigned long tmp_parent_rate; 75 76 tmp_parent_rate = req->rate * div; 77 tmp_parent_rate = clk_hw_round_rate(parent, 78 tmp_parent_rate); 79 if (!tmp_parent_rate) 80 continue; 81 82 tmp_rate = DIV_ROUND_CLOSEST(tmp_parent_rate, div); 83 if (tmp_rate < req->rate) 84 tmp_diff = req->rate - tmp_rate; 85 else 86 tmp_diff = tmp_rate - req->rate; 87 88 if (best_diff < 0 || best_diff > tmp_diff) { 89 best_rate = tmp_rate; 90 best_diff = tmp_diff; 91 req->best_parent_rate = tmp_parent_rate; 92 req->best_parent_hw = parent; 93 } 94 95 if (!best_diff || tmp_rate < req->rate) 96 break; 97 } 98 99 if (!best_diff) 100 break; 101 } 102 103 if (best_rate < 0) 104 return best_rate; 105 106 req->rate = best_rate; 107 return 0; 108 } 109 110 static int at91sam9x5_clk_usb_set_parent(struct clk_hw *hw, u8 index) 111 { 112 struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw); 113 114 if (index >= usb->num_parents) 115 return -EINVAL; 116 117 regmap_update_bits(usb->regmap, AT91_PMC_USB, usb->usbs_mask, index); 118 119 return 0; 120 } 121 122 static u8 at91sam9x5_clk_usb_get_parent(struct clk_hw *hw) 123 { 124 struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw); 125 unsigned int usbr; 126 127 regmap_read(usb->regmap, AT91_PMC_USB, &usbr); 128 129 return usbr & usb->usbs_mask; 130 } 131 132 static int at91sam9x5_clk_usb_set_rate(struct clk_hw *hw, unsigned long rate, 133 unsigned long parent_rate) 134 { 135 struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw); 136 unsigned long div; 137 138 if (!rate) 139 return -EINVAL; 140 141 div = DIV_ROUND_CLOSEST(parent_rate, rate); 142 if (div > SAM9X5_USB_MAX_DIV + 1 || !div) 143 return -EINVAL; 144 145 regmap_update_bits(usb->regmap, AT91_PMC_USB, AT91_PMC_OHCIUSBDIV, 146 (div - 1) << SAM9X5_USB_DIV_SHIFT); 147 148 return 0; 149 } 150 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, 157 }; 158 159 static int at91sam9n12_clk_usb_enable(struct clk_hw *hw) 160 { 161 struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw); 162 163 regmap_update_bits(usb->regmap, AT91_PMC_USB, AT91_PMC_USBS, 164 AT91_PMC_USBS); 165 166 return 0; 167 } 168 169 static void at91sam9n12_clk_usb_disable(struct clk_hw *hw) 170 { 171 struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw); 172 173 regmap_update_bits(usb->regmap, AT91_PMC_USB, AT91_PMC_USBS, 0); 174 } 175 176 static int at91sam9n12_clk_usb_is_enabled(struct clk_hw *hw) 177 { 178 struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw); 179 unsigned int usbr; 180 181 regmap_read(usb->regmap, AT91_PMC_USB, &usbr); 182 183 return usbr & AT91_PMC_USBS; 184 } 185 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, 193 }; 194 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, 198 u32 usbs_mask) 199 { 200 struct at91sam9x5_clk_usb *usb; 201 struct clk_hw *hw; 202 struct clk_init_data init; 203 int ret; 204 205 usb = kzalloc(sizeof(*usb), GFP_KERNEL); 206 if (!usb) 207 return ERR_PTR(-ENOMEM); 208 209 init.name = name; 210 init.ops = &at91sam9x5_usb_ops; 211 init.parent_names = parent_names; 212 init.num_parents = num_parents; 213 init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE | 214 CLK_SET_RATE_PARENT; 215 216 usb->hw.init = &init; 217 usb->regmap = regmap; 218 usb->usbs_mask = usbs_mask; 219 usb->num_parents = num_parents; 220 221 hw = &usb->hw; 222 ret = clk_hw_register(NULL, &usb->hw); 223 if (ret) { 224 kfree(usb); 225 hw = ERR_PTR(ret); 226 } 227 228 return hw; 229 } 230 231 struct clk_hw * __init 232 at91sam9x5_clk_register_usb(struct regmap *regmap, const char *name, 233 const char **parent_names, u8 num_parents) 234 { 235 return _at91sam9x5_clk_register_usb(regmap, name, parent_names, 236 num_parents, SAM9X5_USBS_MASK); 237 } 238 239 struct clk_hw * __init 240 sam9x60_clk_register_usb(struct regmap *regmap, const char *name, 241 const char **parent_names, u8 num_parents) 242 { 243 return _at91sam9x5_clk_register_usb(regmap, name, parent_names, 244 num_parents, SAM9X60_USBS_MASK); 245 } 246 247 struct clk_hw * __init 248 at91sam9n12_clk_register_usb(struct regmap *regmap, const char *name, 249 const char *parent_name) 250 { 251 struct at91sam9x5_clk_usb *usb; 252 struct clk_hw *hw; 253 struct clk_init_data init; 254 int ret; 255 256 usb = kzalloc(sizeof(*usb), GFP_KERNEL); 257 if (!usb) 258 return ERR_PTR(-ENOMEM); 259 260 init.name = name; 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; 265 266 usb->hw.init = &init; 267 usb->regmap = regmap; 268 269 hw = &usb->hw; 270 ret = clk_hw_register(NULL, &usb->hw); 271 if (ret) { 272 kfree(usb); 273 hw = ERR_PTR(ret); 274 } 275 276 return hw; 277 } 278 279 static unsigned long at91rm9200_clk_usb_recalc_rate(struct clk_hw *hw, 280 unsigned long parent_rate) 281 { 282 struct at91rm9200_clk_usb *usb = to_at91rm9200_clk_usb(hw); 283 unsigned int pllbr; 284 u8 usbdiv; 285 286 regmap_read(usb->regmap, AT91_CKGR_PLLBR, &pllbr); 287 288 usbdiv = (pllbr & AT91_PMC_USBDIV) >> RM9200_USB_DIV_SHIFT; 289 if (usb->divisors[usbdiv]) 290 return parent_rate / usb->divisors[usbdiv]; 291 292 return 0; 293 } 294 295 static long at91rm9200_clk_usb_round_rate(struct clk_hw *hw, unsigned long rate, 296 unsigned long *parent_rate) 297 { 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; 301 int bestdiff = -1; 302 unsigned long tmprate; 303 int tmpdiff; 304 int i = 0; 305 306 for (i = 0; i < RM9200_USB_DIV_TAB_SIZE; i++) { 307 unsigned long tmp_parent_rate; 308 309 if (!usb->divisors[i]) 310 continue; 311 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]); 315 if (tmprate < rate) 316 tmpdiff = rate - tmprate; 317 else 318 tmpdiff = tmprate - rate; 319 320 if (bestdiff < 0 || bestdiff > tmpdiff) { 321 bestrate = tmprate; 322 bestdiff = tmpdiff; 323 *parent_rate = tmp_parent_rate; 324 } 325 326 if (!bestdiff) 327 break; 328 } 329 330 return bestrate; 331 } 332 333 static int at91rm9200_clk_usb_set_rate(struct clk_hw *hw, unsigned long rate, 334 unsigned long parent_rate) 335 { 336 int i; 337 struct at91rm9200_clk_usb *usb = to_at91rm9200_clk_usb(hw); 338 unsigned long div; 339 340 if (!rate) 341 return -EINVAL; 342 343 div = DIV_ROUND_CLOSEST(parent_rate, rate); 344 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, 348 AT91_PMC_USBDIV, 349 i << RM9200_USB_DIV_SHIFT); 350 351 return 0; 352 } 353 } 354 355 return -EINVAL; 356 } 357 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, 362 }; 363 364 struct clk_hw * __init 365 at91rm9200_clk_register_usb(struct regmap *regmap, const char *name, 366 const char *parent_name, const u32 *divisors) 367 { 368 struct at91rm9200_clk_usb *usb; 369 struct clk_hw *hw; 370 struct clk_init_data init; 371 int ret; 372 373 usb = kzalloc(sizeof(*usb), GFP_KERNEL); 374 if (!usb) 375 return ERR_PTR(-ENOMEM); 376 377 init.name = name; 378 init.ops = &at91rm9200_usb_ops; 379 init.parent_names = &parent_name; 380 init.num_parents = 1; 381 init.flags = CLK_SET_RATE_PARENT; 382 383 usb->hw.init = &init; 384 usb->regmap = regmap; 385 memcpy(usb->divisors, divisors, sizeof(usb->divisors)); 386 387 hw = &usb->hw; 388 ret = clk_hw_register(NULL, &usb->hw); 389 if (ret) { 390 kfree(usb); 391 hw = ERR_PTR(ret); 392 } 393 394 return hw; 395 } 396