linux/arch/arm/mach-ep93xx/clock.c
<<
>>
Prefs
   1/*
   2 * arch/arm/mach-ep93xx/clock.c
   3 * Clock control for Cirrus EP93xx chips.
   4 *
   5 * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
   6 *
   7 * This program is free software; you can redistribute it and/or modify
   8 * it under the terms of the GNU General Public License as published by
   9 * the Free Software Foundation; either version 2 of the License, or (at
  10 * your option) any later version.
  11 */
  12
  13#include <linux/kernel.h>
  14#include <linux/clk.h>
  15#include <linux/err.h>
  16#include <linux/module.h>
  17#include <linux/string.h>
  18#include <linux/io.h>
  19#include <linux/spinlock.h>
  20
  21#include <mach/hardware.h>
  22
  23#include <asm/clkdev.h>
  24#include <asm/div64.h>
  25
  26
  27struct clk {
  28        struct clk      *parent;
  29        unsigned long   rate;
  30        int             users;
  31        int             sw_locked;
  32        void __iomem    *enable_reg;
  33        u32             enable_mask;
  34
  35        unsigned long   (*get_rate)(struct clk *clk);
  36        int             (*set_rate)(struct clk *clk, unsigned long rate);
  37};
  38
  39
  40static unsigned long get_uart_rate(struct clk *clk);
  41
  42static int set_keytchclk_rate(struct clk *clk, unsigned long rate);
  43static int set_div_rate(struct clk *clk, unsigned long rate);
  44
  45
  46static struct clk clk_xtali = {
  47        .rate           = EP93XX_EXT_CLK_RATE,
  48};
  49static struct clk clk_uart1 = {
  50        .parent         = &clk_xtali,
  51        .sw_locked      = 1,
  52        .enable_reg     = EP93XX_SYSCON_DEVCFG,
  53        .enable_mask    = EP93XX_SYSCON_DEVCFG_U1EN,
  54        .get_rate       = get_uart_rate,
  55};
  56static struct clk clk_uart2 = {
  57        .parent         = &clk_xtali,
  58        .sw_locked      = 1,
  59        .enable_reg     = EP93XX_SYSCON_DEVCFG,
  60        .enable_mask    = EP93XX_SYSCON_DEVCFG_U2EN,
  61        .get_rate       = get_uart_rate,
  62};
  63static struct clk clk_uart3 = {
  64        .parent         = &clk_xtali,
  65        .sw_locked      = 1,
  66        .enable_reg     = EP93XX_SYSCON_DEVCFG,
  67        .enable_mask    = EP93XX_SYSCON_DEVCFG_U3EN,
  68        .get_rate       = get_uart_rate,
  69};
  70static struct clk clk_pll1 = {
  71        .parent         = &clk_xtali,
  72};
  73static struct clk clk_f = {
  74        .parent         = &clk_pll1,
  75};
  76static struct clk clk_h = {
  77        .parent         = &clk_pll1,
  78};
  79static struct clk clk_p = {
  80        .parent         = &clk_pll1,
  81};
  82static struct clk clk_pll2 = {
  83        .parent         = &clk_xtali,
  84};
  85static struct clk clk_usb_host = {
  86        .parent         = &clk_pll2,
  87        .enable_reg     = EP93XX_SYSCON_PWRCNT,
  88        .enable_mask    = EP93XX_SYSCON_PWRCNT_USH_EN,
  89};
  90static struct clk clk_keypad = {
  91        .parent         = &clk_xtali,
  92        .sw_locked      = 1,
  93        .enable_reg     = EP93XX_SYSCON_KEYTCHCLKDIV,
  94        .enable_mask    = EP93XX_SYSCON_KEYTCHCLKDIV_KEN,
  95        .set_rate       = set_keytchclk_rate,
  96};
  97static struct clk clk_pwm = {
  98        .parent         = &clk_xtali,
  99        .rate           = EP93XX_EXT_CLK_RATE,
 100};
 101
 102static struct clk clk_video = {
 103        .sw_locked      = 1,
 104        .enable_reg     = EP93XX_SYSCON_VIDCLKDIV,
 105        .enable_mask    = EP93XX_SYSCON_CLKDIV_ENABLE,
 106        .set_rate       = set_div_rate,
 107};
 108
 109/* DMA Clocks */
 110static struct clk clk_m2p0 = {
 111        .parent         = &clk_h,
 112        .enable_reg     = EP93XX_SYSCON_PWRCNT,
 113        .enable_mask    = EP93XX_SYSCON_PWRCNT_DMA_M2P0,
 114};
 115static struct clk clk_m2p1 = {
 116        .parent         = &clk_h,
 117        .enable_reg     = EP93XX_SYSCON_PWRCNT,
 118        .enable_mask    = EP93XX_SYSCON_PWRCNT_DMA_M2P1,
 119};
 120static struct clk clk_m2p2 = {
 121        .parent         = &clk_h,
 122        .enable_reg     = EP93XX_SYSCON_PWRCNT,
 123        .enable_mask    = EP93XX_SYSCON_PWRCNT_DMA_M2P2,
 124};
 125static struct clk clk_m2p3 = {
 126        .parent         = &clk_h,
 127        .enable_reg     = EP93XX_SYSCON_PWRCNT,
 128        .enable_mask    = EP93XX_SYSCON_PWRCNT_DMA_M2P3,
 129};
 130static struct clk clk_m2p4 = {
 131        .parent         = &clk_h,
 132        .enable_reg     = EP93XX_SYSCON_PWRCNT,
 133        .enable_mask    = EP93XX_SYSCON_PWRCNT_DMA_M2P4,
 134};
 135static struct clk clk_m2p5 = {
 136        .parent         = &clk_h,
 137        .enable_reg     = EP93XX_SYSCON_PWRCNT,
 138        .enable_mask    = EP93XX_SYSCON_PWRCNT_DMA_M2P5,
 139};
 140static struct clk clk_m2p6 = {
 141        .parent         = &clk_h,
 142        .enable_reg     = EP93XX_SYSCON_PWRCNT,
 143        .enable_mask    = EP93XX_SYSCON_PWRCNT_DMA_M2P6,
 144};
 145static struct clk clk_m2p7 = {
 146        .parent         = &clk_h,
 147        .enable_reg     = EP93XX_SYSCON_PWRCNT,
 148        .enable_mask    = EP93XX_SYSCON_PWRCNT_DMA_M2P7,
 149};
 150static struct clk clk_m2p8 = {
 151        .parent         = &clk_h,
 152        .enable_reg     = EP93XX_SYSCON_PWRCNT,
 153        .enable_mask    = EP93XX_SYSCON_PWRCNT_DMA_M2P8,
 154};
 155static struct clk clk_m2p9 = {
 156        .parent         = &clk_h,
 157        .enable_reg     = EP93XX_SYSCON_PWRCNT,
 158        .enable_mask    = EP93XX_SYSCON_PWRCNT_DMA_M2P9,
 159};
 160static struct clk clk_m2m0 = {
 161        .parent         = &clk_h,
 162        .enable_reg     = EP93XX_SYSCON_PWRCNT,
 163        .enable_mask    = EP93XX_SYSCON_PWRCNT_DMA_M2M0,
 164};
 165static struct clk clk_m2m1 = {
 166        .parent         = &clk_h,
 167        .enable_reg     = EP93XX_SYSCON_PWRCNT,
 168        .enable_mask    = EP93XX_SYSCON_PWRCNT_DMA_M2M1,
 169};
 170
 171#define INIT_CK(dev,con,ck)                                     \
 172        { .dev_id = dev, .con_id = con, .clk = ck }
 173
 174static struct clk_lookup clocks[] = {
 175        INIT_CK(NULL,                   "xtali",        &clk_xtali),
 176        INIT_CK("apb:uart1",            NULL,           &clk_uart1),
 177        INIT_CK("apb:uart2",            NULL,           &clk_uart2),
 178        INIT_CK("apb:uart3",            NULL,           &clk_uart3),
 179        INIT_CK(NULL,                   "pll1",         &clk_pll1),
 180        INIT_CK(NULL,                   "fclk",         &clk_f),
 181        INIT_CK(NULL,                   "hclk",         &clk_h),
 182        INIT_CK(NULL,                   "pclk",         &clk_p),
 183        INIT_CK(NULL,                   "pll2",         &clk_pll2),
 184        INIT_CK("ep93xx-ohci",          NULL,           &clk_usb_host),
 185        INIT_CK("ep93xx-keypad",        NULL,           &clk_keypad),
 186        INIT_CK("ep93xx-fb",            NULL,           &clk_video),
 187        INIT_CK(NULL,                   "pwm_clk",      &clk_pwm),
 188        INIT_CK(NULL,                   "m2p0",         &clk_m2p0),
 189        INIT_CK(NULL,                   "m2p1",         &clk_m2p1),
 190        INIT_CK(NULL,                   "m2p2",         &clk_m2p2),
 191        INIT_CK(NULL,                   "m2p3",         &clk_m2p3),
 192        INIT_CK(NULL,                   "m2p4",         &clk_m2p4),
 193        INIT_CK(NULL,                   "m2p5",         &clk_m2p5),
 194        INIT_CK(NULL,                   "m2p6",         &clk_m2p6),
 195        INIT_CK(NULL,                   "m2p7",         &clk_m2p7),
 196        INIT_CK(NULL,                   "m2p8",         &clk_m2p8),
 197        INIT_CK(NULL,                   "m2p9",         &clk_m2p9),
 198        INIT_CK(NULL,                   "m2m0",         &clk_m2m0),
 199        INIT_CK(NULL,                   "m2m1",         &clk_m2m1),
 200};
 201
 202static DEFINE_SPINLOCK(clk_lock);
 203
 204static void __clk_enable(struct clk *clk)
 205{
 206        if (!clk->users++) {
 207                if (clk->parent)
 208                        __clk_enable(clk->parent);
 209
 210                if (clk->enable_reg) {
 211                        u32 v;
 212
 213                        v = __raw_readl(clk->enable_reg);
 214                        v |= clk->enable_mask;
 215                        if (clk->sw_locked)
 216                                ep93xx_syscon_swlocked_write(v, clk->enable_reg);
 217                        else
 218                                __raw_writel(v, clk->enable_reg);
 219                }
 220        }
 221}
 222
 223int clk_enable(struct clk *clk)
 224{
 225        unsigned long flags;
 226
 227        if (!clk)
 228                return -EINVAL;
 229
 230        spin_lock_irqsave(&clk_lock, flags);
 231        __clk_enable(clk);
 232        spin_unlock_irqrestore(&clk_lock, flags);
 233
 234        return 0;
 235}
 236EXPORT_SYMBOL(clk_enable);
 237
 238static void __clk_disable(struct clk *clk)
 239{
 240        if (!--clk->users) {
 241                if (clk->enable_reg) {
 242                        u32 v;
 243
 244                        v = __raw_readl(clk->enable_reg);
 245                        v &= ~clk->enable_mask;
 246                        if (clk->sw_locked)
 247                                ep93xx_syscon_swlocked_write(v, clk->enable_reg);
 248                        else
 249                                __raw_writel(v, clk->enable_reg);
 250                }
 251
 252                if (clk->parent)
 253                        __clk_disable(clk->parent);
 254        }
 255}
 256
 257void clk_disable(struct clk *clk)
 258{
 259        unsigned long flags;
 260
 261        if (!clk)
 262                return;
 263
 264        spin_lock_irqsave(&clk_lock, flags);
 265        __clk_disable(clk);
 266        spin_unlock_irqrestore(&clk_lock, flags);
 267}
 268EXPORT_SYMBOL(clk_disable);
 269
 270static unsigned long get_uart_rate(struct clk *clk)
 271{
 272        unsigned long rate = clk_get_rate(clk->parent);
 273        u32 value;
 274
 275        value = __raw_readl(EP93XX_SYSCON_PWRCNT);
 276        if (value & EP93XX_SYSCON_PWRCNT_UARTBAUD)
 277                return rate;
 278        else
 279                return rate / 2;
 280}
 281
 282unsigned long clk_get_rate(struct clk *clk)
 283{
 284        if (clk->get_rate)
 285                return clk->get_rate(clk);
 286
 287        return clk->rate;
 288}
 289EXPORT_SYMBOL(clk_get_rate);
 290
 291static int set_keytchclk_rate(struct clk *clk, unsigned long rate)
 292{
 293        u32 val;
 294        u32 div_bit;
 295
 296        val = __raw_readl(clk->enable_reg);
 297
 298        /*
 299         * The Key Matrix and ADC clocks are configured using the same
 300         * System Controller register.  The clock used will be either
 301         * 1/4 or 1/16 the external clock rate depending on the
 302         * EP93XX_SYSCON_KEYTCHCLKDIV_KDIV/EP93XX_SYSCON_KEYTCHCLKDIV_ADIV
 303         * bit being set or cleared.
 304         */
 305        div_bit = clk->enable_mask >> 15;
 306
 307        if (rate == EP93XX_KEYTCHCLK_DIV4)
 308                val |= div_bit;
 309        else if (rate == EP93XX_KEYTCHCLK_DIV16)
 310                val &= ~div_bit;
 311        else
 312                return -EINVAL;
 313
 314        ep93xx_syscon_swlocked_write(val, clk->enable_reg);
 315        clk->rate = rate;
 316        return 0;
 317}
 318
 319static int calc_clk_div(struct clk *clk, unsigned long rate,
 320                        int *psel, int *esel, int *pdiv, int *div)
 321{
 322        struct clk *mclk;
 323        unsigned long max_rate, actual_rate, mclk_rate, rate_err = -1;
 324        int i, found = 0, __div = 0, __pdiv = 0;
 325
 326        /* Don't exceed the maximum rate */
 327        max_rate = max(max(clk_pll1.rate / 4, clk_pll2.rate / 4),
 328                       clk_xtali.rate / 4);
 329        rate = min(rate, max_rate);
 330
 331        /*
 332         * Try the two pll's and the external clock
 333         * Because the valid predividers are 2, 2.5 and 3, we multiply
 334         * all the clocks by 2 to avoid floating point math.
 335         *
 336         * This is based on the algorithm in the ep93xx raster guide:
 337         * http://be-a-maverick.com/en/pubs/appNote/AN269REV1.pdf
 338         *
 339         */
 340        for (i = 0; i < 3; i++) {
 341                if (i == 0)
 342                        mclk = &clk_xtali;
 343                else if (i == 1)
 344                        mclk = &clk_pll1;
 345                else
 346                        mclk = &clk_pll2;
 347                mclk_rate = mclk->rate * 2;
 348
 349                /* Try each predivider value */
 350                for (__pdiv = 4; __pdiv <= 6; __pdiv++) {
 351                        __div = mclk_rate / (rate * __pdiv);
 352                        if (__div < 2 || __div > 127)
 353                                continue;
 354
 355                        actual_rate = mclk_rate / (__pdiv * __div);
 356
 357                        if (!found || abs(actual_rate - rate) < rate_err) {
 358                                *pdiv = __pdiv - 3;
 359                                *div = __div;
 360                                *psel = (i == 2);
 361                                *esel = (i != 0);
 362                                clk->parent = mclk;
 363                                clk->rate = actual_rate;
 364                                rate_err = abs(actual_rate - rate);
 365                                found = 1;
 366                        }
 367                }
 368        }
 369
 370        if (!found)
 371                return -EINVAL;
 372
 373        return 0;
 374}
 375
 376static int set_div_rate(struct clk *clk, unsigned long rate)
 377{
 378        int err, psel = 0, esel = 0, pdiv = 0, div = 0;
 379        u32 val;
 380
 381        err = calc_clk_div(clk, rate, &psel, &esel, &pdiv, &div);
 382        if (err)
 383                return err;
 384
 385        /* Clear the esel, psel, pdiv and div bits */
 386        val = __raw_readl(clk->enable_reg);
 387        val &= ~0x7fff;
 388
 389        /* Set the new esel, psel, pdiv and div bits for the new clock rate */
 390        val |= (esel ? EP93XX_SYSCON_CLKDIV_ESEL : 0) |
 391                (psel ? EP93XX_SYSCON_CLKDIV_PSEL : 0) |
 392                (pdiv << EP93XX_SYSCON_CLKDIV_PDIV_SHIFT) | div;
 393        ep93xx_syscon_swlocked_write(val, clk->enable_reg);
 394        return 0;
 395}
 396
 397int clk_set_rate(struct clk *clk, unsigned long rate)
 398{
 399        if (clk->set_rate)
 400                return clk->set_rate(clk, rate);
 401
 402        return -EINVAL;
 403}
 404EXPORT_SYMBOL(clk_set_rate);
 405
 406
 407static char fclk_divisors[] = { 1, 2, 4, 8, 16, 1, 1, 1 };
 408static char hclk_divisors[] = { 1, 2, 4, 5, 6, 8, 16, 32 };
 409static char pclk_divisors[] = { 1, 2, 4, 8 };
 410
 411/*
 412 * PLL rate = 14.7456 MHz * (X1FBD + 1) * (X2FBD + 1) / (X2IPD + 1) / 2^PS
 413 */
 414static unsigned long calc_pll_rate(u32 config_word)
 415{
 416        unsigned long long rate;
 417        int i;
 418
 419        rate = clk_xtali.rate;
 420        rate *= ((config_word >> 11) & 0x1f) + 1;               /* X1FBD */
 421        rate *= ((config_word >> 5) & 0x3f) + 1;                /* X2FBD */
 422        do_div(rate, (config_word & 0x1f) + 1);                 /* X2IPD */
 423        for (i = 0; i < ((config_word >> 16) & 3); i++)         /* PS */
 424                rate >>= 1;
 425
 426        return (unsigned long)rate;
 427}
 428
 429static void __init ep93xx_dma_clock_init(void)
 430{
 431        clk_m2p0.rate = clk_h.rate;
 432        clk_m2p1.rate = clk_h.rate;
 433        clk_m2p2.rate = clk_h.rate;
 434        clk_m2p3.rate = clk_h.rate;
 435        clk_m2p4.rate = clk_h.rate;
 436        clk_m2p5.rate = clk_h.rate;
 437        clk_m2p6.rate = clk_h.rate;
 438        clk_m2p7.rate = clk_h.rate;
 439        clk_m2p8.rate = clk_h.rate;
 440        clk_m2p9.rate = clk_h.rate;
 441        clk_m2m0.rate = clk_h.rate;
 442        clk_m2m1.rate = clk_h.rate;
 443}
 444
 445static int __init ep93xx_clock_init(void)
 446{
 447        u32 value;
 448        int i;
 449
 450        value = __raw_readl(EP93XX_SYSCON_CLOCK_SET1);
 451        if (!(value & 0x00800000)) {                    /* PLL1 bypassed?  */
 452                clk_pll1.rate = clk_xtali.rate;
 453        } else {
 454                clk_pll1.rate = calc_pll_rate(value);
 455        }
 456        clk_f.rate = clk_pll1.rate / fclk_divisors[(value >> 25) & 0x7];
 457        clk_h.rate = clk_pll1.rate / hclk_divisors[(value >> 20) & 0x7];
 458        clk_p.rate = clk_h.rate / pclk_divisors[(value >> 18) & 0x3];
 459        ep93xx_dma_clock_init();
 460
 461        value = __raw_readl(EP93XX_SYSCON_CLOCK_SET2);
 462        if (!(value & 0x00080000)) {                    /* PLL2 bypassed?  */
 463                clk_pll2.rate = clk_xtali.rate;
 464        } else if (value & 0x00040000) {                /* PLL2 enabled?  */
 465                clk_pll2.rate = calc_pll_rate(value);
 466        } else {
 467                clk_pll2.rate = 0;
 468        }
 469        clk_usb_host.rate = clk_pll2.rate / (((value >> 28) & 0xf) + 1);
 470
 471        printk(KERN_INFO "ep93xx: PLL1 running at %ld MHz, PLL2 at %ld MHz\n",
 472                clk_pll1.rate / 1000000, clk_pll2.rate / 1000000);
 473        printk(KERN_INFO "ep93xx: FCLK %ld MHz, HCLK %ld MHz, PCLK %ld MHz\n",
 474                clk_f.rate / 1000000, clk_h.rate / 1000000,
 475                clk_p.rate / 1000000);
 476
 477        for (i = 0; i < ARRAY_SIZE(clocks); i++)
 478                clkdev_add(&clocks[i]);
 479        return 0;
 480}
 481arch_initcall(ep93xx_clock_init);
 482