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