1 /* 2 * drivers/clk/at91/clk-slow.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/clk/at91_pmc.h> 16 #include <linux/delay.h> 17 #include <linux/of.h> 18 #include <linux/mfd/syscon.h> 19 #include <linux/regmap.h> 20 21 #include "pmc.h" 22 #include "sckc.h" 23 24 #define SLOW_CLOCK_FREQ 32768 25 #define SLOWCK_SW_CYCLES 5 26 #define SLOWCK_SW_TIME_USEC ((SLOWCK_SW_CYCLES * USEC_PER_SEC) / \ 27 SLOW_CLOCK_FREQ) 28 29 #define AT91_SCKC_CR 0x00 30 #define AT91_SCKC_RCEN (1 << 0) 31 #define AT91_SCKC_OSC32EN (1 << 1) 32 #define AT91_SCKC_OSC32BYP (1 << 2) 33 #define AT91_SCKC_OSCSEL (1 << 3) 34 35 struct clk_slow_osc { 36 struct clk_hw hw; 37 void __iomem *sckcr; 38 unsigned long startup_usec; 39 }; 40 41 #define to_clk_slow_osc(hw) container_of(hw, struct clk_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_sam9260_slow { 54 struct clk_hw hw; 55 struct regmap *regmap; 56 }; 57 58 #define to_clk_sam9260_slow(hw) container_of(hw, struct clk_sam9260_slow, hw) 59 60 struct clk_sam9x5_slow { 61 struct clk_hw hw; 62 void __iomem *sckcr; 63 u8 parent; 64 }; 65 66 #define to_clk_sam9x5_slow(hw) container_of(hw, struct clk_sam9x5_slow, hw) 67 68 static int clk_slow_osc_prepare(struct clk_hw *hw) 69 { 70 struct clk_slow_osc *osc = to_clk_slow_osc(hw); 71 void __iomem *sckcr = osc->sckcr; 72 u32 tmp = readl(sckcr); 73 74 if (tmp & AT91_SCKC_OSC32BYP) 75 return 0; 76 77 writel(tmp | AT91_SCKC_OSC32EN, sckcr); 78 79 usleep_range(osc->startup_usec, osc->startup_usec + 1); 80 81 return 0; 82 } 83 84 static void clk_slow_osc_unprepare(struct clk_hw *hw) 85 { 86 struct clk_slow_osc *osc = to_clk_slow_osc(hw); 87 void __iomem *sckcr = osc->sckcr; 88 u32 tmp = readl(sckcr); 89 90 if (tmp & AT91_SCKC_OSC32BYP) 91 return; 92 93 writel(tmp & ~AT91_SCKC_OSC32EN, sckcr); 94 } 95 96 static int clk_slow_osc_is_prepared(struct clk_hw *hw) 97 { 98 struct clk_slow_osc *osc = to_clk_slow_osc(hw); 99 void __iomem *sckcr = osc->sckcr; 100 u32 tmp = readl(sckcr); 101 102 if (tmp & AT91_SCKC_OSC32BYP) 103 return 1; 104 105 return !!(tmp & AT91_SCKC_OSC32EN); 106 } 107 108 static const struct clk_ops slow_osc_ops = { 109 .prepare = clk_slow_osc_prepare, 110 .unprepare = clk_slow_osc_unprepare, 111 .is_prepared = clk_slow_osc_is_prepared, 112 }; 113 114 static struct clk * __init 115 at91_clk_register_slow_osc(void __iomem *sckcr, 116 const char *name, 117 const char *parent_name, 118 unsigned long startup, 119 bool bypass) 120 { 121 struct clk_slow_osc *osc; 122 struct clk *clk = NULL; 123 struct clk_init_data init; 124 125 if (!sckcr || !name || !parent_name) 126 return ERR_PTR(-EINVAL); 127 128 osc = kzalloc(sizeof(*osc), GFP_KERNEL); 129 if (!osc) 130 return ERR_PTR(-ENOMEM); 131 132 init.name = name; 133 init.ops = &slow_osc_ops; 134 init.parent_names = &parent_name; 135 init.num_parents = 1; 136 init.flags = CLK_IGNORE_UNUSED; 137 138 osc->hw.init = &init; 139 osc->sckcr = sckcr; 140 osc->startup_usec = startup; 141 142 if (bypass) 143 writel((readl(sckcr) & ~AT91_SCKC_OSC32EN) | AT91_SCKC_OSC32BYP, 144 sckcr); 145 146 clk = clk_register(NULL, &osc->hw); 147 if (IS_ERR(clk)) 148 kfree(osc); 149 150 return clk; 151 } 152 153 void __init of_at91sam9x5_clk_slow_osc_setup(struct device_node *np, 154 void __iomem *sckcr) 155 { 156 struct clk *clk; 157 const char *parent_name; 158 const char *name = np->name; 159 u32 startup; 160 bool bypass; 161 162 parent_name = of_clk_get_parent_name(np, 0); 163 of_property_read_string(np, "clock-output-names", &name); 164 of_property_read_u32(np, "atmel,startup-time-usec", &startup); 165 bypass = of_property_read_bool(np, "atmel,osc-bypass"); 166 167 clk = at91_clk_register_slow_osc(sckcr, name, parent_name, startup, 168 bypass); 169 if (IS_ERR(clk)) 170 return; 171 172 of_clk_add_provider(np, of_clk_src_simple_get, clk); 173 } 174 175 static unsigned long clk_slow_rc_osc_recalc_rate(struct clk_hw *hw, 176 unsigned long parent_rate) 177 { 178 struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw); 179 180 return osc->frequency; 181 } 182 183 static unsigned long clk_slow_rc_osc_recalc_accuracy(struct clk_hw *hw, 184 unsigned long parent_acc) 185 { 186 struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw); 187 188 return osc->accuracy; 189 } 190 191 static int clk_slow_rc_osc_prepare(struct clk_hw *hw) 192 { 193 struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw); 194 void __iomem *sckcr = osc->sckcr; 195 196 writel(readl(sckcr) | AT91_SCKC_RCEN, sckcr); 197 198 usleep_range(osc->startup_usec, osc->startup_usec + 1); 199 200 return 0; 201 } 202 203 static void clk_slow_rc_osc_unprepare(struct clk_hw *hw) 204 { 205 struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw); 206 void __iomem *sckcr = osc->sckcr; 207 208 writel(readl(sckcr) & ~AT91_SCKC_RCEN, sckcr); 209 } 210 211 static int clk_slow_rc_osc_is_prepared(struct clk_hw *hw) 212 { 213 struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw); 214 215 return !!(readl(osc->sckcr) & AT91_SCKC_RCEN); 216 } 217 218 static const struct clk_ops slow_rc_osc_ops = { 219 .prepare = clk_slow_rc_osc_prepare, 220 .unprepare = clk_slow_rc_osc_unprepare, 221 .is_prepared = clk_slow_rc_osc_is_prepared, 222 .recalc_rate = clk_slow_rc_osc_recalc_rate, 223 .recalc_accuracy = clk_slow_rc_osc_recalc_accuracy, 224 }; 225 226 static struct clk * __init 227 at91_clk_register_slow_rc_osc(void __iomem *sckcr, 228 const char *name, 229 unsigned long frequency, 230 unsigned long accuracy, 231 unsigned long startup) 232 { 233 struct clk_slow_rc_osc *osc; 234 struct clk *clk = NULL; 235 struct clk_init_data init; 236 237 if (!sckcr || !name) 238 return ERR_PTR(-EINVAL); 239 240 osc = kzalloc(sizeof(*osc), GFP_KERNEL); 241 if (!osc) 242 return ERR_PTR(-ENOMEM); 243 244 init.name = name; 245 init.ops = &slow_rc_osc_ops; 246 init.parent_names = NULL; 247 init.num_parents = 0; 248 init.flags = CLK_IGNORE_UNUSED; 249 250 osc->hw.init = &init; 251 osc->sckcr = sckcr; 252 osc->frequency = frequency; 253 osc->accuracy = accuracy; 254 osc->startup_usec = startup; 255 256 clk = clk_register(NULL, &osc->hw); 257 if (IS_ERR(clk)) 258 kfree(osc); 259 260 return clk; 261 } 262 263 void __init of_at91sam9x5_clk_slow_rc_osc_setup(struct device_node *np, 264 void __iomem *sckcr) 265 { 266 struct clk *clk; 267 u32 frequency = 0; 268 u32 accuracy = 0; 269 u32 startup = 0; 270 const char *name = np->name; 271 272 of_property_read_string(np, "clock-output-names", &name); 273 of_property_read_u32(np, "clock-frequency", &frequency); 274 of_property_read_u32(np, "clock-accuracy", &accuracy); 275 of_property_read_u32(np, "atmel,startup-time-usec", &startup); 276 277 clk = at91_clk_register_slow_rc_osc(sckcr, name, frequency, accuracy, 278 startup); 279 if (IS_ERR(clk)) 280 return; 281 282 of_clk_add_provider(np, of_clk_src_simple_get, clk); 283 } 284 285 static int clk_sam9x5_slow_set_parent(struct clk_hw *hw, u8 index) 286 { 287 struct clk_sam9x5_slow *slowck = to_clk_sam9x5_slow(hw); 288 void __iomem *sckcr = slowck->sckcr; 289 u32 tmp; 290 291 if (index > 1) 292 return -EINVAL; 293 294 tmp = readl(sckcr); 295 296 if ((!index && !(tmp & AT91_SCKC_OSCSEL)) || 297 (index && (tmp & AT91_SCKC_OSCSEL))) 298 return 0; 299 300 if (index) 301 tmp |= AT91_SCKC_OSCSEL; 302 else 303 tmp &= ~AT91_SCKC_OSCSEL; 304 305 writel(tmp, sckcr); 306 307 usleep_range(SLOWCK_SW_TIME_USEC, SLOWCK_SW_TIME_USEC + 1); 308 309 return 0; 310 } 311 312 static u8 clk_sam9x5_slow_get_parent(struct clk_hw *hw) 313 { 314 struct clk_sam9x5_slow *slowck = to_clk_sam9x5_slow(hw); 315 316 return !!(readl(slowck->sckcr) & AT91_SCKC_OSCSEL); 317 } 318 319 static const struct clk_ops sam9x5_slow_ops = { 320 .set_parent = clk_sam9x5_slow_set_parent, 321 .get_parent = clk_sam9x5_slow_get_parent, 322 }; 323 324 static struct clk * __init 325 at91_clk_register_sam9x5_slow(void __iomem *sckcr, 326 const char *name, 327 const char **parent_names, 328 int num_parents) 329 { 330 struct clk_sam9x5_slow *slowck; 331 struct clk *clk = NULL; 332 struct clk_init_data init; 333 334 if (!sckcr || !name || !parent_names || !num_parents) 335 return ERR_PTR(-EINVAL); 336 337 slowck = kzalloc(sizeof(*slowck), GFP_KERNEL); 338 if (!slowck) 339 return ERR_PTR(-ENOMEM); 340 341 init.name = name; 342 init.ops = &sam9x5_slow_ops; 343 init.parent_names = parent_names; 344 init.num_parents = num_parents; 345 init.flags = 0; 346 347 slowck->hw.init = &init; 348 slowck->sckcr = sckcr; 349 slowck->parent = !!(readl(sckcr) & AT91_SCKC_OSCSEL); 350 351 clk = clk_register(NULL, &slowck->hw); 352 if (IS_ERR(clk)) 353 kfree(slowck); 354 355 return clk; 356 } 357 358 void __init of_at91sam9x5_clk_slow_setup(struct device_node *np, 359 void __iomem *sckcr) 360 { 361 struct clk *clk; 362 const char *parent_names[2]; 363 unsigned int num_parents; 364 const char *name = np->name; 365 366 num_parents = of_clk_get_parent_count(np); 367 if (num_parents == 0 || num_parents > 2) 368 return; 369 370 of_clk_parent_fill(np, parent_names, num_parents); 371 372 of_property_read_string(np, "clock-output-names", &name); 373 374 clk = at91_clk_register_sam9x5_slow(sckcr, name, parent_names, 375 num_parents); 376 if (IS_ERR(clk)) 377 return; 378 379 of_clk_add_provider(np, of_clk_src_simple_get, clk); 380 } 381 382 static u8 clk_sam9260_slow_get_parent(struct clk_hw *hw) 383 { 384 struct clk_sam9260_slow *slowck = to_clk_sam9260_slow(hw); 385 unsigned int status; 386 387 regmap_read(slowck->regmap, AT91_PMC_SR, &status); 388 389 return status & AT91_PMC_OSCSEL ? 1 : 0; 390 } 391 392 static const struct clk_ops sam9260_slow_ops = { 393 .get_parent = clk_sam9260_slow_get_parent, 394 }; 395 396 static struct clk * __init 397 at91_clk_register_sam9260_slow(struct regmap *regmap, 398 const char *name, 399 const char **parent_names, 400 int num_parents) 401 { 402 struct clk_sam9260_slow *slowck; 403 struct clk *clk = NULL; 404 struct clk_init_data init; 405 406 if (!name) 407 return ERR_PTR(-EINVAL); 408 409 if (!parent_names || !num_parents) 410 return ERR_PTR(-EINVAL); 411 412 slowck = kzalloc(sizeof(*slowck), GFP_KERNEL); 413 if (!slowck) 414 return ERR_PTR(-ENOMEM); 415 416 init.name = name; 417 init.ops = &sam9260_slow_ops; 418 init.parent_names = parent_names; 419 init.num_parents = num_parents; 420 init.flags = 0; 421 422 slowck->hw.init = &init; 423 slowck->regmap = regmap; 424 425 clk = clk_register(NULL, &slowck->hw); 426 if (IS_ERR(clk)) 427 kfree(slowck); 428 429 return clk; 430 } 431 432 static void __init of_at91sam9260_clk_slow_setup(struct device_node *np) 433 { 434 struct clk *clk; 435 const char *parent_names[2]; 436 unsigned int num_parents; 437 const char *name = np->name; 438 struct regmap *regmap; 439 440 num_parents = of_clk_get_parent_count(np); 441 if (num_parents != 2) 442 return; 443 444 of_clk_parent_fill(np, parent_names, num_parents); 445 regmap = syscon_node_to_regmap(of_get_parent(np)); 446 if (IS_ERR(regmap)) 447 return; 448 449 of_property_read_string(np, "clock-output-names", &name); 450 451 clk = at91_clk_register_sam9260_slow(regmap, name, parent_names, 452 num_parents); 453 if (IS_ERR(clk)) 454 return; 455 456 of_clk_add_provider(np, of_clk_src_simple_get, clk); 457 } 458 459 CLK_OF_DECLARE(at91sam9260_clk_slow, "atmel,at91sam9260-clk-slow", 460 of_at91sam9260_clk_slow_setup); 461