1/* 2 * Clock tree for CSR SiRFprimaII 3 * 4 * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. 5 * 6 * Licensed under GPLv2 or later. 7 */ 8 9#include <linux/module.h> 10#include <linux/bitops.h> 11#include <linux/err.h> 12#include <linux/errno.h> 13#include <linux/io.h> 14#include <linux/clkdev.h> 15#include <linux/clk.h> 16#include <linux/spinlock.h> 17#include <linux/of.h> 18#include <linux/of_address.h> 19#include <asm/mach/map.h> 20#include <mach/map.h> 21 22#define SIRFSOC_CLKC_CLK_EN0 0x0000 23#define SIRFSOC_CLKC_CLK_EN1 0x0004 24#define SIRFSOC_CLKC_REF_CFG 0x0014 25#define SIRFSOC_CLKC_CPU_CFG 0x0018 26#define SIRFSOC_CLKC_MEM_CFG 0x001c 27#define SIRFSOC_CLKC_SYS_CFG 0x0020 28#define SIRFSOC_CLKC_IO_CFG 0x0024 29#define SIRFSOC_CLKC_DSP_CFG 0x0028 30#define SIRFSOC_CLKC_GFX_CFG 0x002c 31#define SIRFSOC_CLKC_MM_CFG 0x0030 32#define SIRFSOC_LKC_LCD_CFG 0x0034 33#define SIRFSOC_CLKC_MMC_CFG 0x0038 34#define SIRFSOC_CLKC_PLL1_CFG0 0x0040 35#define SIRFSOC_CLKC_PLL2_CFG0 0x0044 36#define SIRFSOC_CLKC_PLL3_CFG0 0x0048 37#define SIRFSOC_CLKC_PLL1_CFG1 0x004c 38#define SIRFSOC_CLKC_PLL2_CFG1 0x0050 39#define SIRFSOC_CLKC_PLL3_CFG1 0x0054 40#define SIRFSOC_CLKC_PLL1_CFG2 0x0058 41#define SIRFSOC_CLKC_PLL2_CFG2 0x005c 42#define SIRFSOC_CLKC_PLL3_CFG2 0x0060 43 44#define SIRFSOC_CLOCK_VA_BASE SIRFSOC_VA(0x005000) 45 46#define KHZ 1000 47#define MHZ (KHZ * KHZ) 48 49struct clk_ops { 50 unsigned long (*get_rate)(struct clk *clk); 51 long (*round_rate)(struct clk *clk, unsigned long rate); 52 int (*set_rate)(struct clk *clk, unsigned long rate); 53 int (*enable)(struct clk *clk); 54 int (*disable)(struct clk *clk); 55 struct clk *(*get_parent)(struct clk *clk); 56 int (*set_parent)(struct clk *clk, struct clk *parent); 57}; 58 59struct clk { 60 struct clk *parent; /* parent clk */ 61 unsigned long rate; /* clock rate in Hz */ 62 signed char usage; /* clock enable count */ 63 signed char enable_bit; /* enable bit: 0 ~ 63 */ 64 unsigned short regofs; /* register offset */ 65 struct clk_ops *ops; /* clock operation */ 66}; 67 68static DEFINE_SPINLOCK(clocks_lock); 69 70static inline unsigned long clkc_readl(unsigned reg) 71{ 72 return readl(SIRFSOC_CLOCK_VA_BASE + reg); 73} 74 75static inline void clkc_writel(u32 val, unsigned reg) 76{ 77 writel(val, SIRFSOC_CLOCK_VA_BASE + reg); 78} 79 80/* 81 * osc_rtc - real time oscillator - 32.768KHz 82 * osc_sys - high speed oscillator - 26MHz 83 */ 84 85static struct clk clk_rtc = { 86 .rate = 32768, 87}; 88 89static struct clk clk_osc = { 90 .rate = 26 * MHZ, 91}; 92 93/* 94 * std pll 95 */ 96static unsigned long std_pll_get_rate(struct clk *clk) 97{ 98 unsigned long fin = clk_get_rate(clk->parent); 99 u32 regcfg2 = clk->regofs + SIRFSOC_CLKC_PLL1_CFG2 - 100 SIRFSOC_CLKC_PLL1_CFG0; 101 102 if (clkc_readl(regcfg2) & BIT(2)) { 103 /* pll bypass mode */ 104 clk->rate = fin; 105 } else { 106 /* fout = fin * nf / nr / od */ 107 u32 cfg0 = clkc_readl(clk->regofs); 108 u32 nf = (cfg0 & (BIT(13) - 1)) + 1; 109 u32 nr = ((cfg0 >> 13) & (BIT(6) - 1)) + 1; 110 u32 od = ((cfg0 >> 19) & (BIT(4) - 1)) + 1; 111 WARN_ON(fin % MHZ); 112 clk->rate = fin / MHZ * nf / nr / od * MHZ; 113 } 114 115 return clk->rate; 116} 117 118static int std_pll_set_rate(struct clk *clk, unsigned long rate) 119{ 120 unsigned long fin, nf, nr, od, reg; 121 122 /* 123 * fout = fin * nf / (nr * od); 124 * set od = 1, nr = fin/MHz, so fout = nf * MHz 125 */ 126 127 nf = rate / MHZ; 128 if (unlikely((rate % MHZ) || nf > BIT(13) || nf < 1)) 129 return -EINVAL; 130 131 fin = clk_get_rate(clk->parent); 132 BUG_ON(fin < MHZ); 133 134 nr = fin / MHZ; 135 BUG_ON((fin % MHZ) || nr > BIT(6)); 136 137 od = 1; 138 139 reg = (nf - 1) | ((nr - 1) << 13) | ((od - 1) << 19); 140 clkc_writel(reg, clk->regofs); 141 142 reg = clk->regofs + SIRFSOC_CLKC_PLL1_CFG1 - SIRFSOC_CLKC_PLL1_CFG0; 143 clkc_writel((nf >> 1) - 1, reg); 144 145 reg = clk->regofs + SIRFSOC_CLKC_PLL1_CFG2 - SIRFSOC_CLKC_PLL1_CFG0; 146 while (!(clkc_readl(reg) & BIT(6))) 147 cpu_relax(); 148 149 clk->rate = 0; /* set to zero will force recalculation */ 150 return 0; 151} 152 153static struct clk_ops std_pll_ops = { 154 .get_rate = std_pll_get_rate, 155 .set_rate = std_pll_set_rate, 156}; 157 158static struct clk clk_pll1 = { 159 .parent = &clk_osc, 160 .regofs = SIRFSOC_CLKC_PLL1_CFG0, 161 .ops = &std_pll_ops, 162}; 163 164static struct clk clk_pll2 = { 165 .parent = &clk_osc, 166 .regofs = SIRFSOC_CLKC_PLL2_CFG0, 167 .ops = &std_pll_ops, 168}; 169 170static struct clk clk_pll3 = { 171 .parent = &clk_osc, 172 .regofs = SIRFSOC_CLKC_PLL3_CFG0, 173 .ops = &std_pll_ops, 174}; 175 176/* 177 * clock domains - cpu, mem, sys/io 178 */ 179 180static struct clk clk_mem; 181 182static struct clk *dmn_get_parent(struct clk *clk) 183{ 184 struct clk *clks[] = { 185 &clk_osc, &clk_rtc, &clk_pll1, &clk_pll2, &clk_pll3 186 }; 187 u32 cfg = clkc_readl(clk->regofs); 188 WARN_ON((cfg & (BIT(3) - 1)) > 4); 189 return clks[cfg & (BIT(3) - 1)]; 190} 191 192static int dmn_set_parent(struct clk *clk, struct clk *parent) 193{ 194 const struct clk *clks[] = { 195 &clk_osc, &clk_rtc, &clk_pll1, &clk_pll2, &clk_pll3 196 }; 197 u32 cfg = clkc_readl(clk->regofs); 198 int i; 199 for (i = 0; i < ARRAY_SIZE(clks); i++) { 200 if (clks[i] == parent) { 201 cfg &= ~(BIT(3) - 1); 202 clkc_writel(cfg | i, clk->regofs); 203 /* BIT(3) - switching status: 1 - busy, 0 - done */ 204 while (clkc_readl(clk->regofs) & BIT(3)) 205 cpu_relax(); 206 return 0; 207 } 208 } 209 return -EINVAL; 210} 211 212static unsigned long dmn_get_rate(struct clk *clk) 213{ 214 unsigned long fin = clk_get_rate(clk->parent); 215 u32 cfg = clkc_readl(clk->regofs); 216 if (cfg & BIT(24)) { 217 /* fcd bypass mode */ 218 clk->rate = fin; 219 } else { 220 /* 221 * wait count: bit[19:16], hold count: bit[23:20] 222 */ 223 u32 wait = (cfg >> 16) & (BIT(4) - 1); 224 u32 hold = (cfg >> 20) & (BIT(4) - 1); 225 226 clk->rate = fin / (wait + hold + 2); 227 } 228 229 return clk->rate; 230} 231 232static int dmn_set_rate(struct clk *clk, unsigned long rate) 233{ 234 unsigned long fin; 235 unsigned ratio, wait, hold, reg; 236 unsigned bits = (clk == &clk_mem) ? 3 : 4; 237 238 fin = clk_get_rate(clk->parent); 239 ratio = fin / rate; 240 241 if (unlikely(ratio < 2 || ratio > BIT(bits + 1))) 242 return -EINVAL; 243 244 WARN_ON(fin % rate); 245 246 wait = (ratio >> 1) - 1; 247 hold = ratio - wait - 2; 248 249 reg = clkc_readl(clk->regofs); 250 reg &= ~(((BIT(bits) - 1) << 16) | ((BIT(bits) - 1) << 20)); 251 reg |= (wait << 16) | (hold << 20) | BIT(25); 252 clkc_writel(reg, clk->regofs); 253 254 /* waiting FCD been effective */ 255 while (clkc_readl(clk->regofs) & BIT(25)) 256 cpu_relax(); 257 258 clk->rate = 0; /* set to zero will force recalculation */ 259 260 return 0; 261} 262 263/* 264 * cpu clock has no FCD register in Prima2, can only change pll 265 */ 266static int cpu_set_rate(struct clk *clk, unsigned long rate) 267{ 268 int ret1, ret2; 269 struct clk *cur_parent, *tmp_parent; 270 271 cur_parent = dmn_get_parent(clk); 272 BUG_ON(cur_parent == NULL || cur_parent->usage > 1); 273 274 /* switch to tmp pll before setting parent clock's rate */ 275 tmp_parent = cur_parent == &clk_pll1 ? &clk_pll2 : &clk_pll1; 276 ret1 = dmn_set_parent(clk, tmp_parent); 277 BUG_ON(ret1); 278 279 ret2 = clk_set_rate(cur_parent, rate); 280 281 ret1 = dmn_set_parent(clk, cur_parent); 282 283 clk->rate = 0; /* set to zero will force recalculation */ 284 285 return ret2 ? ret2 : ret1; 286} 287 288static struct clk_ops cpu_ops = { 289 .get_parent = dmn_get_parent, 290 .set_parent = dmn_set_parent, 291 .set_rate = cpu_set_rate, 292}; 293 294static struct clk clk_cpu = { 295 .parent = &clk_pll1, 296 .regofs = SIRFSOC_CLKC_CPU_CFG, 297 .ops = &cpu_ops, 298}; 299 300 301static struct clk_ops msi_ops = { 302 .set_rate = dmn_set_rate, 303 .get_rate = dmn_get_rate, 304 .set_parent = dmn_set_parent, 305 .get_parent = dmn_get_parent, 306}; 307 308static struct clk clk_mem = { 309 .parent = &clk_pll2, 310 .regofs = SIRFSOC_CLKC_MEM_CFG, 311 .ops = &msi_ops, 312}; 313 314static struct clk clk_sys = { 315 .parent = &clk_pll3, 316 .regofs = SIRFSOC_CLKC_SYS_CFG, 317 .ops = &msi_ops, 318}; 319 320static struct clk clk_io = { 321 .parent = &clk_pll3, 322 .regofs = SIRFSOC_CLKC_IO_CFG, 323 .ops = &msi_ops, 324}; 325 326/* 327 * on-chip clock sets 328 */ 329static struct clk_lookup onchip_clks[] = { 330 { 331 .dev_id = "rtc", 332 .clk = &clk_rtc, 333 }, { 334 .dev_id = "osc", 335 .clk = &clk_osc, 336 }, { 337 .dev_id = "pll1", 338 .clk = &clk_pll1, 339 }, { 340 .dev_id = "pll2", 341 .clk = &clk_pll2, 342 }, { 343 .dev_id = "pll3", 344 .clk = &clk_pll3, 345 }, { 346 .dev_id = "cpu", 347 .clk = &clk_cpu, 348 }, { 349 .dev_id = "mem", 350 .clk = &clk_mem, 351 }, { 352 .dev_id = "sys", 353 .clk = &clk_sys, 354 }, { 355 .dev_id = "io", 356 .clk = &clk_io, 357 }, 358}; 359 360int clk_enable(struct clk *clk) 361{ 362 unsigned long flags; 363 364 if (unlikely(IS_ERR_OR_NULL(clk))) 365 return -EINVAL; 366 367 if (clk->parent) 368 clk_enable(clk->parent); 369 370 spin_lock_irqsave(&clocks_lock, flags); 371 if (!clk->usage++ && clk->ops && clk->ops->enable) 372 clk->ops->enable(clk); 373 spin_unlock_irqrestore(&clocks_lock, flags); 374 return 0; 375} 376EXPORT_SYMBOL(clk_enable); 377 378void clk_disable(struct clk *clk) 379{ 380 unsigned long flags; 381 382 if (unlikely(IS_ERR_OR_NULL(clk))) 383 return; 384 385 WARN_ON(!clk->usage); 386 387 spin_lock_irqsave(&clocks_lock, flags); 388 if (--clk->usage == 0 && clk->ops && clk->ops->disable) 389 clk->ops->disable(clk); 390 spin_unlock_irqrestore(&clocks_lock, flags); 391 392 if (clk->parent) 393 clk_disable(clk->parent); 394} 395EXPORT_SYMBOL(clk_disable); 396 397unsigned long clk_get_rate(struct clk *clk) 398{ 399 if (unlikely(IS_ERR_OR_NULL(clk))) 400 return 0; 401 402 if (clk->rate) 403 return clk->rate; 404 405 if (clk->ops && clk->ops->get_rate) 406 return clk->ops->get_rate(clk); 407 408 return clk_get_rate(clk->parent); 409} 410EXPORT_SYMBOL(clk_get_rate); 411 412long clk_round_rate(struct clk *clk, unsigned long rate) 413{ 414 if (unlikely(IS_ERR_OR_NULL(clk))) 415 return 0; 416 417 if (clk->ops && clk->ops->round_rate) 418 return clk->ops->round_rate(clk, rate); 419 420 return 0; 421} 422EXPORT_SYMBOL(clk_round_rate); 423 424int clk_set_rate(struct clk *clk, unsigned long rate) 425{ 426 if (unlikely(IS_ERR_OR_NULL(clk))) 427 return -EINVAL; 428 429 if (!clk->ops || !clk->ops->set_rate) 430 return -EINVAL; 431 432 return clk->ops->set_rate(clk, rate); 433} 434EXPORT_SYMBOL(clk_set_rate); 435 436int clk_set_parent(struct clk *clk, struct clk *parent) 437{ 438 int ret; 439 unsigned long flags; 440 441 if (unlikely(IS_ERR_OR_NULL(clk))) 442 return -EINVAL; 443 444 if (!clk->ops || !clk->ops->set_parent) 445 return -EINVAL; 446 447 spin_lock_irqsave(&clocks_lock, flags); 448 ret = clk->ops->set_parent(clk, parent); 449 if (!ret) { 450 parent->usage += clk->usage; 451 clk->parent->usage -= clk->usage; 452 BUG_ON(clk->parent->usage < 0); 453 clk->parent = parent; 454 } 455 spin_unlock_irqrestore(&clocks_lock, flags); 456 return ret; 457} 458EXPORT_SYMBOL(clk_set_parent); 459 460struct clk *clk_get_parent(struct clk *clk) 461{ 462 unsigned long flags; 463 464 if (unlikely(IS_ERR_OR_NULL(clk))) 465 return NULL; 466 467 if (!clk->ops || !clk->ops->get_parent) 468 return clk->parent; 469 470 spin_lock_irqsave(&clocks_lock, flags); 471 clk->parent = clk->ops->get_parent(clk); 472 spin_unlock_irqrestore(&clocks_lock, flags); 473 return clk->parent; 474} 475EXPORT_SYMBOL(clk_get_parent); 476 477static void __init sirfsoc_clk_init(void) 478{ 479 clkdev_add_table(onchip_clks, ARRAY_SIZE(onchip_clks)); 480} 481 482static struct of_device_id clkc_ids[] = { 483 { .compatible = "sirf,prima2-clkc" }, 484 {}, 485}; 486 487void __init sirfsoc_of_clk_init(void) 488{ 489 struct device_node *np; 490 struct resource res; 491 struct map_desc sirfsoc_clkc_iodesc = { 492 .virtual = SIRFSOC_CLOCK_VA_BASE, 493 .type = MT_DEVICE, 494 }; 495 496 np = of_find_matching_node(NULL, clkc_ids); 497 if (!np) 498 panic("unable to find compatible clkc node in dtb\n"); 499 500 if (of_address_to_resource(np, 0, &res)) 501 panic("unable to find clkc range in dtb"); 502 of_node_put(np); 503 504 sirfsoc_clkc_iodesc.pfn = __phys_to_pfn(res.start); 505 sirfsoc_clkc_iodesc.length = 1 + res.end - res.start; 506 507 iotable_init(&sirfsoc_clkc_iodesc, 1); 508 509 sirfsoc_clk_init(); 510} 511