1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * drivers/clk/at91/sckc.c 4 * 5 * Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com> 6 */ 7 8 #include <linux/clk-provider.h> 9 #include <linux/clkdev.h> 10 #include <linux/delay.h> 11 #include <linux/of.h> 12 #include <linux/of_address.h> 13 #include <linux/io.h> 14 15 #define SLOW_CLOCK_FREQ 32768 16 #define SLOWCK_SW_CYCLES 5 17 #define SLOWCK_SW_TIME_USEC ((SLOWCK_SW_CYCLES * USEC_PER_SEC) / \ 18 SLOW_CLOCK_FREQ) 19 20 #define AT91_SCKC_CR 0x00 21 #define AT91_SCKC_RCEN (1 << 0) 22 #define AT91_SCKC_OSC32EN (1 << 1) 23 #define AT91_SCKC_OSC32BYP (1 << 2) 24 #define AT91_SCKC_OSCSEL (1 << 3) 25 26 struct clk_slow_osc { 27 struct clk_hw hw; 28 void __iomem *sckcr; 29 unsigned long startup_usec; 30 }; 31 32 #define to_clk_slow_osc(hw) container_of(hw, struct clk_slow_osc, hw) 33 34 struct clk_sama5d4_slow_osc { 35 struct clk_hw hw; 36 void __iomem *sckcr; 37 unsigned long startup_usec; 38 bool prepared; 39 }; 40 41 #define to_clk_sama5d4_slow_osc(hw) container_of(hw, struct clk_sama5d4_slow_osc, hw) 42 43 struct clk_slow_rc_osc { 44 struct clk_hw hw; 45 void __iomem *sckcr; 46 unsigned long frequency; 47 unsigned long accuracy; 48 unsigned long startup_usec; 49 }; 50 51 #define to_clk_slow_rc_osc(hw) container_of(hw, struct clk_slow_rc_osc, hw) 52 53 struct clk_sam9x5_slow { 54 struct clk_hw hw; 55 void __iomem *sckcr; 56 u8 parent; 57 }; 58 59 #define to_clk_sam9x5_slow(hw) container_of(hw, struct clk_sam9x5_slow, hw) 60 61 static int clk_slow_osc_prepare(struct clk_hw *hw) 62 { 63 struct clk_slow_osc *osc = to_clk_slow_osc(hw); 64 void __iomem *sckcr = osc->sckcr; 65 u32 tmp = readl(sckcr); 66 67 if (tmp & (AT91_SCKC_OSC32BYP | AT91_SCKC_OSC32EN)) 68 return 0; 69 70 writel(tmp | AT91_SCKC_OSC32EN, sckcr); 71 72 usleep_range(osc->startup_usec, osc->startup_usec + 1); 73 74 return 0; 75 } 76 77 static void clk_slow_osc_unprepare(struct clk_hw *hw) 78 { 79 struct clk_slow_osc *osc = to_clk_slow_osc(hw); 80 void __iomem *sckcr = osc->sckcr; 81 u32 tmp = readl(sckcr); 82 83 if (tmp & AT91_SCKC_OSC32BYP) 84 return; 85 86 writel(tmp & ~AT91_SCKC_OSC32EN, sckcr); 87 } 88 89 static int clk_slow_osc_is_prepared(struct clk_hw *hw) 90 { 91 struct clk_slow_osc *osc = to_clk_slow_osc(hw); 92 void __iomem *sckcr = osc->sckcr; 93 u32 tmp = readl(sckcr); 94 95 if (tmp & AT91_SCKC_OSC32BYP) 96 return 1; 97 98 return !!(tmp & AT91_SCKC_OSC32EN); 99 } 100 101 static const struct clk_ops slow_osc_ops = { 102 .prepare = clk_slow_osc_prepare, 103 .unprepare = clk_slow_osc_unprepare, 104 .is_prepared = clk_slow_osc_is_prepared, 105 }; 106 107 static struct clk_hw * __init 108 at91_clk_register_slow_osc(void __iomem *sckcr, 109 const char *name, 110 const char *parent_name, 111 unsigned long startup, 112 bool bypass) 113 { 114 struct clk_slow_osc *osc; 115 struct clk_hw *hw; 116 struct clk_init_data init; 117 int ret; 118 119 if (!sckcr || !name || !parent_name) 120 return ERR_PTR(-EINVAL); 121 122 osc = kzalloc(sizeof(*osc), GFP_KERNEL); 123 if (!osc) 124 return ERR_PTR(-ENOMEM); 125 126 init.name = name; 127 init.ops = &slow_osc_ops; 128 init.parent_names = &parent_name; 129 init.num_parents = 1; 130 init.flags = CLK_IGNORE_UNUSED; 131 132 osc->hw.init = &init; 133 osc->sckcr = sckcr; 134 osc->startup_usec = startup; 135 136 if (bypass) 137 writel((readl(sckcr) & ~AT91_SCKC_OSC32EN) | AT91_SCKC_OSC32BYP, 138 sckcr); 139 140 hw = &osc->hw; 141 ret = clk_hw_register(NULL, &osc->hw); 142 if (ret) { 143 kfree(osc); 144 hw = ERR_PTR(ret); 145 } 146 147 return hw; 148 } 149 150 static unsigned long clk_slow_rc_osc_recalc_rate(struct clk_hw *hw, 151 unsigned long parent_rate) 152 { 153 struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw); 154 155 return osc->frequency; 156 } 157 158 static unsigned long clk_slow_rc_osc_recalc_accuracy(struct clk_hw *hw, 159 unsigned long parent_acc) 160 { 161 struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw); 162 163 return osc->accuracy; 164 } 165 166 static int clk_slow_rc_osc_prepare(struct clk_hw *hw) 167 { 168 struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw); 169 void __iomem *sckcr = osc->sckcr; 170 171 writel(readl(sckcr) | AT91_SCKC_RCEN, sckcr); 172 173 usleep_range(osc->startup_usec, osc->startup_usec + 1); 174 175 return 0; 176 } 177 178 static void clk_slow_rc_osc_unprepare(struct clk_hw *hw) 179 { 180 struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw); 181 void __iomem *sckcr = osc->sckcr; 182 183 writel(readl(sckcr) & ~AT91_SCKC_RCEN, sckcr); 184 } 185 186 static int clk_slow_rc_osc_is_prepared(struct clk_hw *hw) 187 { 188 struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw); 189 190 return !!(readl(osc->sckcr) & AT91_SCKC_RCEN); 191 } 192 193 static const struct clk_ops slow_rc_osc_ops = { 194 .prepare = clk_slow_rc_osc_prepare, 195 .unprepare = clk_slow_rc_osc_unprepare, 196 .is_prepared = clk_slow_rc_osc_is_prepared, 197 .recalc_rate = clk_slow_rc_osc_recalc_rate, 198 .recalc_accuracy = clk_slow_rc_osc_recalc_accuracy, 199 }; 200 201 static struct clk_hw * __init 202 at91_clk_register_slow_rc_osc(void __iomem *sckcr, 203 const char *name, 204 unsigned long frequency, 205 unsigned long accuracy, 206 unsigned long startup) 207 { 208 struct clk_slow_rc_osc *osc; 209 struct clk_hw *hw; 210 struct clk_init_data init; 211 int ret; 212 213 if (!sckcr || !name) 214 return ERR_PTR(-EINVAL); 215 216 osc = kzalloc(sizeof(*osc), GFP_KERNEL); 217 if (!osc) 218 return ERR_PTR(-ENOMEM); 219 220 init.name = name; 221 init.ops = &slow_rc_osc_ops; 222 init.parent_names = NULL; 223 init.num_parents = 0; 224 init.flags = CLK_IGNORE_UNUSED; 225 226 osc->hw.init = &init; 227 osc->sckcr = sckcr; 228 osc->frequency = frequency; 229 osc->accuracy = accuracy; 230 osc->startup_usec = startup; 231 232 hw = &osc->hw; 233 ret = clk_hw_register(NULL, &osc->hw); 234 if (ret) { 235 kfree(osc); 236 hw = ERR_PTR(ret); 237 } 238 239 return hw; 240 } 241 242 static int clk_sam9x5_slow_set_parent(struct clk_hw *hw, u8 index) 243 { 244 struct clk_sam9x5_slow *slowck = to_clk_sam9x5_slow(hw); 245 void __iomem *sckcr = slowck->sckcr; 246 u32 tmp; 247 248 if (index > 1) 249 return -EINVAL; 250 251 tmp = readl(sckcr); 252 253 if ((!index && !(tmp & AT91_SCKC_OSCSEL)) || 254 (index && (tmp & AT91_SCKC_OSCSEL))) 255 return 0; 256 257 if (index) 258 tmp |= AT91_SCKC_OSCSEL; 259 else 260 tmp &= ~AT91_SCKC_OSCSEL; 261 262 writel(tmp, sckcr); 263 264 usleep_range(SLOWCK_SW_TIME_USEC, SLOWCK_SW_TIME_USEC + 1); 265 266 return 0; 267 } 268 269 static u8 clk_sam9x5_slow_get_parent(struct clk_hw *hw) 270 { 271 struct clk_sam9x5_slow *slowck = to_clk_sam9x5_slow(hw); 272 273 return !!(readl(slowck->sckcr) & AT91_SCKC_OSCSEL); 274 } 275 276 static const struct clk_ops sam9x5_slow_ops = { 277 .set_parent = clk_sam9x5_slow_set_parent, 278 .get_parent = clk_sam9x5_slow_get_parent, 279 }; 280 281 static struct clk_hw * __init 282 at91_clk_register_sam9x5_slow(void __iomem *sckcr, 283 const char *name, 284 const char **parent_names, 285 int num_parents) 286 { 287 struct clk_sam9x5_slow *slowck; 288 struct clk_hw *hw; 289 struct clk_init_data init; 290 int ret; 291 292 if (!sckcr || !name || !parent_names || !num_parents) 293 return ERR_PTR(-EINVAL); 294 295 slowck = kzalloc(sizeof(*slowck), GFP_KERNEL); 296 if (!slowck) 297 return ERR_PTR(-ENOMEM); 298 299 init.name = name; 300 init.ops = &sam9x5_slow_ops; 301 init.parent_names = parent_names; 302 init.num_parents = num_parents; 303 init.flags = 0; 304 305 slowck->hw.init = &init; 306 slowck->sckcr = sckcr; 307 slowck->parent = !!(readl(sckcr) & AT91_SCKC_OSCSEL); 308 309 hw = &slowck->hw; 310 ret = clk_hw_register(NULL, &slowck->hw); 311 if (ret) { 312 kfree(slowck); 313 hw = ERR_PTR(ret); 314 } 315 316 return hw; 317 } 318 319 static void __init at91sam9x5_sckc_register(struct device_node *np, 320 unsigned int rc_osc_startup_us) 321 { 322 const char *parent_names[2] = { "slow_rc_osc", "slow_osc" }; 323 void __iomem *regbase = of_iomap(np, 0); 324 struct device_node *child = NULL; 325 const char *xtal_name; 326 struct clk_hw *hw; 327 bool bypass; 328 329 if (!regbase) 330 return; 331 332 hw = at91_clk_register_slow_rc_osc(regbase, parent_names[0], 32768, 333 50000000, rc_osc_startup_us); 334 if (IS_ERR(hw)) 335 return; 336 337 xtal_name = of_clk_get_parent_name(np, 0); 338 if (!xtal_name) { 339 /* DT backward compatibility */ 340 child = of_get_compatible_child(np, "atmel,at91sam9x5-clk-slow-osc"); 341 if (!child) 342 return; 343 344 xtal_name = of_clk_get_parent_name(child, 0); 345 bypass = of_property_read_bool(child, "atmel,osc-bypass"); 346 347 child = of_get_compatible_child(np, "atmel,at91sam9x5-clk-slow"); 348 } else { 349 bypass = of_property_read_bool(np, "atmel,osc-bypass"); 350 } 351 352 if (!xtal_name) 353 return; 354 355 hw = at91_clk_register_slow_osc(regbase, parent_names[1], xtal_name, 356 1200000, bypass); 357 if (IS_ERR(hw)) 358 return; 359 360 hw = at91_clk_register_sam9x5_slow(regbase, "slowck", parent_names, 2); 361 if (IS_ERR(hw)) 362 return; 363 364 of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw); 365 366 /* DT backward compatibility */ 367 if (child) 368 of_clk_add_hw_provider(child, of_clk_hw_simple_get, hw); 369 } 370 371 static void __init of_at91sam9x5_sckc_setup(struct device_node *np) 372 { 373 at91sam9x5_sckc_register(np, 75); 374 } 375 CLK_OF_DECLARE(at91sam9x5_clk_sckc, "atmel,at91sam9x5-sckc", 376 of_at91sam9x5_sckc_setup); 377 378 static void __init of_sama5d3_sckc_setup(struct device_node *np) 379 { 380 at91sam9x5_sckc_register(np, 500); 381 } 382 CLK_OF_DECLARE(sama5d3_clk_sckc, "atmel,sama5d3-sckc", 383 of_sama5d3_sckc_setup); 384 385 static int clk_sama5d4_slow_osc_prepare(struct clk_hw *hw) 386 { 387 struct clk_sama5d4_slow_osc *osc = to_clk_sama5d4_slow_osc(hw); 388 389 if (osc->prepared) 390 return 0; 391 392 /* 393 * Assume that if it has already been selected (for example by the 394 * bootloader), enough time has aready passed. 395 */ 396 if ((readl(osc->sckcr) & AT91_SCKC_OSCSEL)) { 397 osc->prepared = true; 398 return 0; 399 } 400 401 usleep_range(osc->startup_usec, osc->startup_usec + 1); 402 osc->prepared = true; 403 404 return 0; 405 } 406 407 static int clk_sama5d4_slow_osc_is_prepared(struct clk_hw *hw) 408 { 409 struct clk_sama5d4_slow_osc *osc = to_clk_sama5d4_slow_osc(hw); 410 411 return osc->prepared; 412 } 413 414 static const struct clk_ops sama5d4_slow_osc_ops = { 415 .prepare = clk_sama5d4_slow_osc_prepare, 416 .is_prepared = clk_sama5d4_slow_osc_is_prepared, 417 }; 418 419 static void __init of_sama5d4_sckc_setup(struct device_node *np) 420 { 421 void __iomem *regbase = of_iomap(np, 0); 422 struct clk_hw *hw; 423 struct clk_sama5d4_slow_osc *osc; 424 struct clk_init_data init; 425 const char *xtal_name; 426 const char *parent_names[2] = { "slow_rc_osc", "slow_osc" }; 427 bool bypass; 428 int ret; 429 430 if (!regbase) 431 return; 432 433 hw = clk_hw_register_fixed_rate_with_accuracy(NULL, parent_names[0], 434 NULL, 0, 32768, 435 250000000); 436 if (IS_ERR(hw)) 437 return; 438 439 xtal_name = of_clk_get_parent_name(np, 0); 440 441 bypass = of_property_read_bool(np, "atmel,osc-bypass"); 442 443 osc = kzalloc(sizeof(*osc), GFP_KERNEL); 444 if (!osc) 445 return; 446 447 init.name = parent_names[1]; 448 init.ops = &sama5d4_slow_osc_ops; 449 init.parent_names = &xtal_name; 450 init.num_parents = 1; 451 init.flags = CLK_IGNORE_UNUSED; 452 453 osc->hw.init = &init; 454 osc->sckcr = regbase; 455 osc->startup_usec = 1200000; 456 457 if (bypass) 458 writel((readl(regbase) | AT91_SCKC_OSC32BYP), regbase); 459 460 hw = &osc->hw; 461 ret = clk_hw_register(NULL, &osc->hw); 462 if (ret) { 463 kfree(osc); 464 return; 465 } 466 467 hw = at91_clk_register_sam9x5_slow(regbase, "slowck", parent_names, 2); 468 if (IS_ERR(hw)) 469 return; 470 471 of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw); 472 } 473 CLK_OF_DECLARE(sama5d4_clk_sckc, "atmel,sama5d4-sckc", 474 of_sama5d4_sckc_setup); 475