linux/arch/unicore32/kernel/clock.c
<<
>>
Prefs
   1/*
   2 * linux/arch/unicore32/kernel/clock.c
   3 *
   4 * Code specific to PKUnity SoC and UniCore ISA
   5 *
   6 *      Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn>
   7 *      Copyright (C) 2001-2010 Guan Xuetao
   8 *
   9 * This program is free software; you can redistribute it and/or modify
  10 * it under the terms of the GNU General Public License version 2 as
  11 * published by the Free Software Foundation.
  12 */
  13#include <linux/module.h>
  14#include <linux/kernel.h>
  15#include <linux/device.h>
  16#include <linux/list.h>
  17#include <linux/errno.h>
  18#include <linux/err.h>
  19#include <linux/string.h>
  20#include <linux/clk.h>
  21#include <linux/mutex.h>
  22#include <linux/delay.h>
  23#include <linux/io.h>
  24
  25#include <mach/hardware.h>
  26
  27/*
  28 * Very simple clock implementation
  29 */
  30struct clk {
  31        struct list_head        node;
  32        unsigned long           rate;
  33        const char              *name;
  34};
  35
  36static struct clk clk_ost_clk = {
  37        .name           = "OST_CLK",
  38        .rate           = CLOCK_TICK_RATE,
  39};
  40
  41static struct clk clk_mclk_clk = {
  42        .name           = "MAIN_CLK",
  43};
  44
  45static struct clk clk_bclk32_clk = {
  46        .name           = "BUS32_CLK",
  47};
  48
  49static struct clk clk_ddr_clk = {
  50        .name           = "DDR_CLK",
  51};
  52
  53static struct clk clk_vga_clk = {
  54        .name           = "VGA_CLK",
  55};
  56
  57static LIST_HEAD(clocks);
  58static DEFINE_MUTEX(clocks_mutex);
  59
  60struct clk *clk_get(struct device *dev, const char *id)
  61{
  62        struct clk *p, *clk = ERR_PTR(-ENOENT);
  63
  64        mutex_lock(&clocks_mutex);
  65        list_for_each_entry(p, &clocks, node) {
  66                if (strcmp(id, p->name) == 0) {
  67                        clk = p;
  68                        break;
  69                }
  70        }
  71        mutex_unlock(&clocks_mutex);
  72
  73        return clk;
  74}
  75EXPORT_SYMBOL(clk_get);
  76
  77void clk_put(struct clk *clk)
  78{
  79}
  80EXPORT_SYMBOL(clk_put);
  81
  82int clk_enable(struct clk *clk)
  83{
  84        return 0;
  85}
  86EXPORT_SYMBOL(clk_enable);
  87
  88void clk_disable(struct clk *clk)
  89{
  90}
  91EXPORT_SYMBOL(clk_disable);
  92
  93unsigned long clk_get_rate(struct clk *clk)
  94{
  95        return clk->rate;
  96}
  97EXPORT_SYMBOL(clk_get_rate);
  98
  99struct {
 100        unsigned long rate;
 101        unsigned long cfg;
 102        unsigned long div;
 103} vga_clk_table[] = {
 104        {.rate =  25175000, .cfg = 0x00002001, .div = 0x9},
 105        {.rate =  31500000, .cfg = 0x00002001, .div = 0x7},
 106        {.rate =  40000000, .cfg = 0x00003801, .div = 0x9},
 107        {.rate =  49500000, .cfg = 0x00003801, .div = 0x7},
 108        {.rate =  65000000, .cfg = 0x00002c01, .div = 0x4},
 109        {.rate =  78750000, .cfg = 0x00002400, .div = 0x7},
 110        {.rate = 108000000, .cfg = 0x00002c01, .div = 0x2},
 111        {.rate = 106500000, .cfg = 0x00003c01, .div = 0x3},
 112        {.rate =  50650000, .cfg = 0x00106400, .div = 0x9},
 113        {.rate =  61500000, .cfg = 0x00106400, .div = 0xa},
 114        {.rate =  85500000, .cfg = 0x00002800, .div = 0x6},
 115};
 116
 117struct {
 118        unsigned long mrate;
 119        unsigned long prate;
 120} mclk_clk_table[] = {
 121        {.mrate = 500000000, .prate = 0x00109801},
 122        {.mrate = 525000000, .prate = 0x00104C00},
 123        {.mrate = 550000000, .prate = 0x00105000},
 124        {.mrate = 575000000, .prate = 0x00105400},
 125        {.mrate = 600000000, .prate = 0x00105800},
 126        {.mrate = 625000000, .prate = 0x00105C00},
 127        {.mrate = 650000000, .prate = 0x00106000},
 128        {.mrate = 675000000, .prate = 0x00106400},
 129        {.mrate = 700000000, .prate = 0x00106800},
 130        {.mrate = 725000000, .prate = 0x00106C00},
 131        {.mrate = 750000000, .prate = 0x00107000},
 132        {.mrate = 775000000, .prate = 0x00107400},
 133        {.mrate = 800000000, .prate = 0x00107800},
 134};
 135
 136int clk_set_rate(struct clk *clk, unsigned long rate)
 137{
 138        if (clk == &clk_vga_clk) {
 139                unsigned long pll_vgacfg, pll_vgadiv;
 140                int ret, i;
 141
 142                /* lookup vga_clk_table */
 143                ret = -EINVAL;
 144                for (i = 0; i < ARRAY_SIZE(vga_clk_table); i++) {
 145                        if (rate == vga_clk_table[i].rate) {
 146                                pll_vgacfg = vga_clk_table[i].cfg;
 147                                pll_vgadiv = vga_clk_table[i].div;
 148                                ret = 0;
 149                                break;
 150                        }
 151                }
 152
 153                if (ret)
 154                        return ret;
 155
 156                if (readl(PM_PLLVGACFG) == pll_vgacfg)
 157                        return 0;
 158
 159                /* set pll vga cfg reg. */
 160                writel(pll_vgacfg, PM_PLLVGACFG);
 161
 162                writel(PM_PMCR_CFBVGA, PM_PMCR);
 163                while ((readl(PM_PLLDFCDONE) & PM_PLLDFCDONE_VGADFC)
 164                                != PM_PLLDFCDONE_VGADFC)
 165                        udelay(100); /* about 1ms */
 166
 167                /* set div cfg reg. */
 168                writel(readl(PM_PCGR) | PM_PCGR_VGACLK, PM_PCGR);
 169
 170                writel((readl(PM_DIVCFG) & ~PM_DIVCFG_VGACLK_MASK)
 171                                | PM_DIVCFG_VGACLK(pll_vgadiv), PM_DIVCFG);
 172
 173                writel(readl(PM_SWRESET) | PM_SWRESET_VGADIV, PM_SWRESET);
 174                while ((readl(PM_SWRESET) & PM_SWRESET_VGADIV)
 175                                == PM_SWRESET_VGADIV)
 176                        udelay(100); /* 65536 bclk32, about 320us */
 177
 178                writel(readl(PM_PCGR) & ~PM_PCGR_VGACLK, PM_PCGR);
 179        }
 180#ifdef CONFIG_CPU_FREQ
 181        if (clk == &clk_mclk_clk) {
 182                u32 pll_rate, divstatus = PM_DIVSTATUS;
 183                int ret, i;
 184
 185                /* lookup mclk_clk_table */
 186                ret = -EINVAL;
 187                for (i = 0; i < ARRAY_SIZE(mclk_clk_table); i++) {
 188                        if (rate == mclk_clk_table[i].mrate) {
 189                                pll_rate = mclk_clk_table[i].prate;
 190                                clk_mclk_clk.rate = mclk_clk_table[i].mrate;
 191                                ret = 0;
 192                                break;
 193                        }
 194                }
 195
 196                if (ret)
 197                        return ret;
 198
 199                if (clk_mclk_clk.rate)
 200                        clk_bclk32_clk.rate = clk_mclk_clk.rate
 201                                / (((divstatus & 0x0000f000) >> 12) + 1);
 202
 203                /* set pll sys cfg reg. */
 204                PM_PLLSYSCFG = pll_rate;
 205
 206                PM_PMCR = PM_PMCR_CFBSYS;
 207                while ((PM_PLLDFCDONE & PM_PLLDFCDONE_SYSDFC)
 208                                != PM_PLLDFCDONE_SYSDFC)
 209                        udelay(100);
 210                        /* about 1ms */
 211        }
 212#endif
 213        return 0;
 214}
 215EXPORT_SYMBOL(clk_set_rate);
 216
 217int clk_register(struct clk *clk)
 218{
 219        mutex_lock(&clocks_mutex);
 220        list_add(&clk->node, &clocks);
 221        mutex_unlock(&clocks_mutex);
 222        printk(KERN_DEFAULT "PKUnity PM: %s %lu.%02luM\n", clk->name,
 223                (clk->rate)/1000000, (clk->rate)/10000 % 100);
 224        return 0;
 225}
 226EXPORT_SYMBOL(clk_register);
 227
 228void clk_unregister(struct clk *clk)
 229{
 230        mutex_lock(&clocks_mutex);
 231        list_del(&clk->node);
 232        mutex_unlock(&clocks_mutex);
 233}
 234EXPORT_SYMBOL(clk_unregister);
 235
 236struct {
 237        unsigned long prate;
 238        unsigned long rate;
 239} pllrate_table[] = {
 240        {.prate = 0x00002001, .rate = 250000000},
 241        {.prate = 0x00104801, .rate = 250000000},
 242        {.prate = 0x00104C01, .rate = 262500000},
 243        {.prate = 0x00002401, .rate = 275000000},
 244        {.prate = 0x00105001, .rate = 275000000},
 245        {.prate = 0x00105401, .rate = 287500000},
 246        {.prate = 0x00002801, .rate = 300000000},
 247        {.prate = 0x00105801, .rate = 300000000},
 248        {.prate = 0x00105C01, .rate = 312500000},
 249        {.prate = 0x00002C01, .rate = 325000000},
 250        {.prate = 0x00106001, .rate = 325000000},
 251        {.prate = 0x00106401, .rate = 337500000},
 252        {.prate = 0x00003001, .rate = 350000000},
 253        {.prate = 0x00106801, .rate = 350000000},
 254        {.prate = 0x00106C01, .rate = 362500000},
 255        {.prate = 0x00003401, .rate = 375000000},
 256        {.prate = 0x00107001, .rate = 375000000},
 257        {.prate = 0x00107401, .rate = 387500000},
 258        {.prate = 0x00003801, .rate = 400000000},
 259        {.prate = 0x00107801, .rate = 400000000},
 260        {.prate = 0x00107C01, .rate = 412500000},
 261        {.prate = 0x00003C01, .rate = 425000000},
 262        {.prate = 0x00108001, .rate = 425000000},
 263        {.prate = 0x00108401, .rate = 437500000},
 264        {.prate = 0x00004001, .rate = 450000000},
 265        {.prate = 0x00108801, .rate = 450000000},
 266        {.prate = 0x00108C01, .rate = 462500000},
 267        {.prate = 0x00004401, .rate = 475000000},
 268        {.prate = 0x00109001, .rate = 475000000},
 269        {.prate = 0x00109401, .rate = 487500000},
 270        {.prate = 0x00004801, .rate = 500000000},
 271        {.prate = 0x00109801, .rate = 500000000},
 272        {.prate = 0x00104C00, .rate = 525000000},
 273        {.prate = 0x00002400, .rate = 550000000},
 274        {.prate = 0x00105000, .rate = 550000000},
 275        {.prate = 0x00105400, .rate = 575000000},
 276        {.prate = 0x00002800, .rate = 600000000},
 277        {.prate = 0x00105800, .rate = 600000000},
 278        {.prate = 0x00105C00, .rate = 625000000},
 279        {.prate = 0x00002C00, .rate = 650000000},
 280        {.prate = 0x00106000, .rate = 650000000},
 281        {.prate = 0x00106400, .rate = 675000000},
 282        {.prate = 0x00003000, .rate = 700000000},
 283        {.prate = 0x00106800, .rate = 700000000},
 284        {.prate = 0x00106C00, .rate = 725000000},
 285        {.prate = 0x00003400, .rate = 750000000},
 286        {.prate = 0x00107000, .rate = 750000000},
 287        {.prate = 0x00107400, .rate = 775000000},
 288        {.prate = 0x00003800, .rate = 800000000},
 289        {.prate = 0x00107800, .rate = 800000000},
 290        {.prate = 0x00107C00, .rate = 825000000},
 291        {.prate = 0x00003C00, .rate = 850000000},
 292        {.prate = 0x00108000, .rate = 850000000},
 293        {.prate = 0x00108400, .rate = 875000000},
 294        {.prate = 0x00004000, .rate = 900000000},
 295        {.prate = 0x00108800, .rate = 900000000},
 296        {.prate = 0x00108C00, .rate = 925000000},
 297        {.prate = 0x00004400, .rate = 950000000},
 298        {.prate = 0x00109000, .rate = 950000000},
 299        {.prate = 0x00109400, .rate = 975000000},
 300        {.prate = 0x00004800, .rate = 1000000000},
 301        {.prate = 0x00109800, .rate = 1000000000},
 302};
 303
 304struct {
 305        unsigned long prate;
 306        unsigned long drate;
 307} pddr_table[] = {
 308        {.prate = 0x00100800, .drate = 44236800},
 309        {.prate = 0x00100C00, .drate = 66355200},
 310        {.prate = 0x00101000, .drate = 88473600},
 311        {.prate = 0x00101400, .drate = 110592000},
 312        {.prate = 0x00101800, .drate = 132710400},
 313        {.prate = 0x00101C01, .drate = 154828800},
 314        {.prate = 0x00102001, .drate = 176947200},
 315        {.prate = 0x00102401, .drate = 199065600},
 316        {.prate = 0x00102801, .drate = 221184000},
 317        {.prate = 0x00102C01, .drate = 243302400},
 318        {.prate = 0x00103001, .drate = 265420800},
 319        {.prate = 0x00103401, .drate = 287539200},
 320        {.prate = 0x00103801, .drate = 309657600},
 321        {.prate = 0x00103C01, .drate = 331776000},
 322        {.prate = 0x00104001, .drate = 353894400},
 323};
 324
 325static int __init clk_init(void)
 326{
 327#ifdef CONFIG_PUV3_PM
 328        u32 pllrate, divstatus = readl(PM_DIVSTATUS);
 329        u32 pcgr_val = readl(PM_PCGR);
 330        int i;
 331
 332        pcgr_val |= PM_PCGR_BCLKMME | PM_PCGR_BCLKH264E | PM_PCGR_BCLKH264D
 333                        | PM_PCGR_HECLK | PM_PCGR_HDCLK;
 334        writel(pcgr_val, PM_PCGR);
 335
 336        pllrate = readl(PM_PLLSYSSTATUS);
 337
 338        /* lookup pmclk_table */
 339        clk_mclk_clk.rate = 0;
 340        for (i = 0; i < ARRAY_SIZE(pllrate_table); i++) {
 341                if (pllrate == pllrate_table[i].prate) {
 342                        clk_mclk_clk.rate = pllrate_table[i].rate;
 343                        break;
 344                }
 345        }
 346
 347        if (clk_mclk_clk.rate)
 348                clk_bclk32_clk.rate = clk_mclk_clk.rate /
 349                        (((divstatus & 0x0000f000) >> 12) + 1);
 350
 351        pllrate = readl(PM_PLLDDRSTATUS);
 352
 353        /* lookup pddr_table */
 354        clk_ddr_clk.rate = 0;
 355        for (i = 0; i < ARRAY_SIZE(pddr_table); i++) {
 356                if (pllrate == pddr_table[i].prate) {
 357                        clk_ddr_clk.rate = pddr_table[i].drate;
 358                        break;
 359                }
 360        }
 361
 362        pllrate = readl(PM_PLLVGASTATUS);
 363
 364        /* lookup pvga_table */
 365        clk_vga_clk.rate = 0;
 366        for (i = 0; i < ARRAY_SIZE(pllrate_table); i++) {
 367                if (pllrate == pllrate_table[i].prate) {
 368                        clk_vga_clk.rate = pllrate_table[i].rate;
 369                        break;
 370                }
 371        }
 372
 373        if (clk_vga_clk.rate)
 374                clk_vga_clk.rate = clk_vga_clk.rate /
 375                        (((divstatus & 0x00f00000) >> 20) + 1);
 376
 377        clk_register(&clk_vga_clk);
 378#endif
 379#ifdef CONFIG_ARCH_FPGA
 380        clk_ddr_clk.rate = 33000000;
 381        clk_mclk_clk.rate = 33000000;
 382        clk_bclk32_clk.rate = 33000000;
 383#endif
 384        clk_register(&clk_ddr_clk);
 385        clk_register(&clk_mclk_clk);
 386        clk_register(&clk_bclk32_clk);
 387        clk_register(&clk_ost_clk);
 388        return 0;
 389}
 390core_initcall(clk_init);
 391