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