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#define pr_fmt(fmt) "ep93xx " KBUILD_MODNAME ": " fmt
  14
  15#include <linux/kernel.h>
  16#include <linux/clk.h>
  17#include <linux/err.h>
  18#include <linux/module.h>
  19#include <linux/string.h>
  20#include <linux/io.h>
  21#include <linux/spinlock.h>
  22#include <linux/clkdev.h>
  23
  24#include <mach/hardware.h>
  25
  26#include <asm/div64.h>
  27
  28#include "soc.h"
  29
  30struct clk {
  31        struct clk      *parent;
  32        unsigned long   rate;
  33        int             users;
  34        int             sw_locked;
  35        void __iomem    *enable_reg;
  36        u32             enable_mask;
  37
  38        unsigned long   (*get_rate)(struct clk *clk);
  39        int             (*set_rate)(struct clk *clk, unsigned long rate);
  40};
  41
  42
  43static unsigned long get_uart_rate(struct clk *clk);
  44
  45static int set_keytchclk_rate(struct clk *clk, unsigned long rate);
  46static int set_div_rate(struct clk *clk, unsigned long rate);
  47static int set_i2s_sclk_rate(struct clk *clk, unsigned long rate);
  48static int set_i2s_lrclk_rate(struct clk *clk, unsigned long rate);
  49
  50static struct clk clk_xtali = {
  51        .rate           = EP93XX_EXT_CLK_RATE,
  52};
  53static struct clk clk_uart1 = {
  54        .parent         = &clk_xtali,
  55        .sw_locked      = 1,
  56        .enable_reg     = EP93XX_SYSCON_DEVCFG,
  57        .enable_mask    = EP93XX_SYSCON_DEVCFG_U1EN,
  58        .get_rate       = get_uart_rate,
  59};
  60static struct clk clk_uart2 = {
  61        .parent         = &clk_xtali,
  62        .sw_locked      = 1,
  63        .enable_reg     = EP93XX_SYSCON_DEVCFG,
  64        .enable_mask    = EP93XX_SYSCON_DEVCFG_U2EN,
  65        .get_rate       = get_uart_rate,
  66};
  67static struct clk clk_uart3 = {
  68        .parent         = &clk_xtali,
  69        .sw_locked      = 1,
  70        .enable_reg     = EP93XX_SYSCON_DEVCFG,
  71        .enable_mask    = EP93XX_SYSCON_DEVCFG_U3EN,
  72        .get_rate       = get_uart_rate,
  73};
  74static struct clk clk_pll1 = {
  75        .parent         = &clk_xtali,
  76};
  77static struct clk clk_f = {
  78        .parent         = &clk_pll1,
  79};
  80static struct clk clk_h = {
  81        .parent         = &clk_pll1,
  82};
  83static struct clk clk_p = {
  84        .parent         = &clk_pll1,
  85};
  86static struct clk clk_pll2 = {
  87        .parent         = &clk_xtali,
  88};
  89static struct clk clk_usb_host = {
  90        .parent         = &clk_pll2,
  91        .enable_reg     = EP93XX_SYSCON_PWRCNT,
  92        .enable_mask    = EP93XX_SYSCON_PWRCNT_USH_EN,
  93};
  94static struct clk clk_keypad = {
  95        .parent         = &clk_xtali,
  96        .sw_locked      = 1,
  97        .enable_reg     = EP93XX_SYSCON_KEYTCHCLKDIV,
  98        .enable_mask    = EP93XX_SYSCON_KEYTCHCLKDIV_KEN,
  99        .set_rate       = set_keytchclk_rate,
 100};
 101static struct clk clk_spi = {
 102        .parent         = &clk_xtali,
 103        .rate           = EP93XX_EXT_CLK_RATE,
 104};
 105static struct clk clk_pwm = {
 106        .parent         = &clk_xtali,
 107        .rate           = EP93XX_EXT_CLK_RATE,
 108};
 109
 110static struct clk clk_video = {
 111        .sw_locked      = 1,
 112        .enable_reg     = EP93XX_SYSCON_VIDCLKDIV,
 113        .enable_mask    = EP93XX_SYSCON_CLKDIV_ENABLE,
 114        .set_rate       = set_div_rate,
 115};
 116
 117static struct clk clk_i2s_mclk = {
 118        .sw_locked      = 1,
 119        .enable_reg     = EP93XX_SYSCON_I2SCLKDIV,
 120        .enable_mask    = EP93XX_SYSCON_CLKDIV_ENABLE,
 121        .set_rate       = set_div_rate,
 122};
 123
 124static struct clk clk_i2s_sclk = {
 125        .sw_locked      = 1,
 126        .parent         = &clk_i2s_mclk,
 127        .enable_reg     = EP93XX_SYSCON_I2SCLKDIV,
 128        .enable_mask    = EP93XX_SYSCON_I2SCLKDIV_SENA,
 129        .set_rate       = set_i2s_sclk_rate,
 130};
 131
 132static struct clk clk_i2s_lrclk = {
 133        .sw_locked      = 1,
 134        .parent         = &clk_i2s_sclk,
 135        .enable_reg     = EP93XX_SYSCON_I2SCLKDIV,
 136        .enable_mask    = EP93XX_SYSCON_I2SCLKDIV_SENA,
 137        .set_rate       = set_i2s_lrclk_rate,
 138};
 139
 140/* DMA Clocks */
 141static struct clk clk_m2p0 = {
 142        .parent         = &clk_h,
 143        .enable_reg     = EP93XX_SYSCON_PWRCNT,
 144        .enable_mask    = EP93XX_SYSCON_PWRCNT_DMA_M2P0,
 145};
 146static struct clk clk_m2p1 = {
 147        .parent         = &clk_h,
 148        .enable_reg     = EP93XX_SYSCON_PWRCNT,
 149        .enable_mask    = EP93XX_SYSCON_PWRCNT_DMA_M2P1,
 150};
 151static struct clk clk_m2p2 = {
 152        .parent         = &clk_h,
 153        .enable_reg     = EP93XX_SYSCON_PWRCNT,
 154        .enable_mask    = EP93XX_SYSCON_PWRCNT_DMA_M2P2,
 155};
 156static struct clk clk_m2p3 = {
 157        .parent         = &clk_h,
 158        .enable_reg     = EP93XX_SYSCON_PWRCNT,
 159        .enable_mask    = EP93XX_SYSCON_PWRCNT_DMA_M2P3,
 160};
 161static struct clk clk_m2p4 = {
 162        .parent         = &clk_h,
 163        .enable_reg     = EP93XX_SYSCON_PWRCNT,
 164        .enable_mask    = EP93XX_SYSCON_PWRCNT_DMA_M2P4,
 165};
 166static struct clk clk_m2p5 = {
 167        .parent         = &clk_h,
 168        .enable_reg     = EP93XX_SYSCON_PWRCNT,
 169        .enable_mask    = EP93XX_SYSCON_PWRCNT_DMA_M2P5,
 170};
 171static struct clk clk_m2p6 = {
 172        .parent         = &clk_h,
 173        .enable_reg     = EP93XX_SYSCON_PWRCNT,
 174        .enable_mask    = EP93XX_SYSCON_PWRCNT_DMA_M2P6,
 175};
 176static struct clk clk_m2p7 = {
 177        .parent         = &clk_h,
 178        .enable_reg     = EP93XX_SYSCON_PWRCNT,
 179        .enable_mask    = EP93XX_SYSCON_PWRCNT_DMA_M2P7,
 180};
 181static struct clk clk_m2p8 = {
 182        .parent         = &clk_h,
 183        .enable_reg     = EP93XX_SYSCON_PWRCNT,
 184        .enable_mask    = EP93XX_SYSCON_PWRCNT_DMA_M2P8,
 185};
 186static struct clk clk_m2p9 = {
 187        .parent         = &clk_h,
 188        .enable_reg     = EP93XX_SYSCON_PWRCNT,
 189        .enable_mask    = EP93XX_SYSCON_PWRCNT_DMA_M2P9,
 190};
 191static struct clk clk_m2m0 = {
 192        .parent         = &clk_h,
 193        .enable_reg     = EP93XX_SYSCON_PWRCNT,
 194        .enable_mask    = EP93XX_SYSCON_PWRCNT_DMA_M2M0,
 195};
 196static struct clk clk_m2m1 = {
 197        .parent         = &clk_h,
 198        .enable_reg     = EP93XX_SYSCON_PWRCNT,
 199        .enable_mask    = EP93XX_SYSCON_PWRCNT_DMA_M2M1,
 200};
 201
 202#define INIT_CK(dev,con,ck)                                     \
 203        { .dev_id = dev, .con_id = con, .clk = ck }
 204
 205static struct clk_lookup clocks[] = {
 206        INIT_CK(NULL,                   "xtali",        &clk_xtali),
 207        INIT_CK("apb:uart1",            NULL,           &clk_uart1),
 208        INIT_CK("apb:uart2",            NULL,           &clk_uart2),
 209        INIT_CK("apb:uart3",            NULL,           &clk_uart3),
 210        INIT_CK(NULL,                   "pll1",         &clk_pll1),
 211        INIT_CK(NULL,                   "fclk",         &clk_f),
 212        INIT_CK(NULL,                   "hclk",         &clk_h),
 213        INIT_CK(NULL,                   "apb_pclk",     &clk_p),
 214        INIT_CK(NULL,                   "pll2",         &clk_pll2),
 215        INIT_CK("ohci-platform",        NULL,           &clk_usb_host),
 216        INIT_CK("ep93xx-keypad",        NULL,           &clk_keypad),
 217        INIT_CK("ep93xx-fb",            NULL,           &clk_video),
 218        INIT_CK("ep93xx-spi.0",         NULL,           &clk_spi),
 219        INIT_CK("ep93xx-i2s",           "mclk",         &clk_i2s_mclk),
 220        INIT_CK("ep93xx-i2s",           "sclk",         &clk_i2s_sclk),
 221        INIT_CK("ep93xx-i2s",           "lrclk",        &clk_i2s_lrclk),
 222        INIT_CK(NULL,                   "pwm_clk",      &clk_pwm),
 223        INIT_CK(NULL,                   "m2p0",         &clk_m2p0),
 224        INIT_CK(NULL,                   "m2p1",         &clk_m2p1),
 225        INIT_CK(NULL,                   "m2p2",         &clk_m2p2),
 226        INIT_CK(NULL,                   "m2p3",         &clk_m2p3),
 227        INIT_CK(NULL,                   "m2p4",         &clk_m2p4),
 228        INIT_CK(NULL,                   "m2p5",         &clk_m2p5),
 229        INIT_CK(NULL,                   "m2p6",         &clk_m2p6),
 230        INIT_CK(NULL,                   "m2p7",         &clk_m2p7),
 231        INIT_CK(NULL,                   "m2p8",         &clk_m2p8),
 232        INIT_CK(NULL,                   "m2p9",         &clk_m2p9),
 233        INIT_CK(NULL,                   "m2m0",         &clk_m2m0),
 234        INIT_CK(NULL,                   "m2m1",         &clk_m2m1),
 235};
 236
 237static DEFINE_SPINLOCK(clk_lock);
 238
 239static void __clk_enable(struct clk *clk)
 240{
 241        if (!clk->users++) {
 242                if (clk->parent)
 243                        __clk_enable(clk->parent);
 244
 245                if (clk->enable_reg) {
 246                        u32 v;
 247
 248                        v = __raw_readl(clk->enable_reg);
 249                        v |= clk->enable_mask;
 250                        if (clk->sw_locked)
 251                                ep93xx_syscon_swlocked_write(v, clk->enable_reg);
 252                        else
 253                                __raw_writel(v, clk->enable_reg);
 254                }
 255        }
 256}
 257
 258int clk_enable(struct clk *clk)
 259{
 260        unsigned long flags;
 261
 262        if (!clk)
 263                return -EINVAL;
 264
 265        spin_lock_irqsave(&clk_lock, flags);
 266        __clk_enable(clk);
 267        spin_unlock_irqrestore(&clk_lock, flags);
 268
 269        return 0;
 270}
 271EXPORT_SYMBOL(clk_enable);
 272
 273static void __clk_disable(struct clk *clk)
 274{
 275        if (!--clk->users) {
 276                if (clk->enable_reg) {
 277                        u32 v;
 278
 279                        v = __raw_readl(clk->enable_reg);
 280                        v &= ~clk->enable_mask;
 281                        if (clk->sw_locked)
 282                                ep93xx_syscon_swlocked_write(v, clk->enable_reg);
 283                        else
 284                                __raw_writel(v, clk->enable_reg);
 285                }
 286
 287                if (clk->parent)
 288                        __clk_disable(clk->parent);
 289        }
 290}
 291
 292void clk_disable(struct clk *clk)
 293{
 294        unsigned long flags;
 295
 296        if (!clk)
 297                return;
 298
 299        spin_lock_irqsave(&clk_lock, flags);
 300        __clk_disable(clk);
 301        spin_unlock_irqrestore(&clk_lock, flags);
 302}
 303EXPORT_SYMBOL(clk_disable);
 304
 305static unsigned long get_uart_rate(struct clk *clk)
 306{
 307        unsigned long rate = clk_get_rate(clk->parent);
 308        u32 value;
 309
 310        value = __raw_readl(EP93XX_SYSCON_PWRCNT);
 311        if (value & EP93XX_SYSCON_PWRCNT_UARTBAUD)
 312                return rate;
 313        else
 314                return rate / 2;
 315}
 316
 317unsigned long clk_get_rate(struct clk *clk)
 318{
 319        if (clk->get_rate)
 320                return clk->get_rate(clk);
 321
 322        return clk->rate;
 323}
 324EXPORT_SYMBOL(clk_get_rate);
 325
 326static int set_keytchclk_rate(struct clk *clk, unsigned long rate)
 327{
 328        u32 val;
 329        u32 div_bit;
 330
 331        val = __raw_readl(clk->enable_reg);
 332
 333        /*
 334         * The Key Matrix and ADC clocks are configured using the same
 335         * System Controller register.  The clock used will be either
 336         * 1/4 or 1/16 the external clock rate depending on the
 337         * EP93XX_SYSCON_KEYTCHCLKDIV_KDIV/EP93XX_SYSCON_KEYTCHCLKDIV_ADIV
 338         * bit being set or cleared.
 339         */
 340        div_bit = clk->enable_mask >> 15;
 341
 342        if (rate == EP93XX_KEYTCHCLK_DIV4)
 343                val |= div_bit;
 344        else if (rate == EP93XX_KEYTCHCLK_DIV16)
 345                val &= ~div_bit;
 346        else
 347                return -EINVAL;
 348
 349        ep93xx_syscon_swlocked_write(val, clk->enable_reg);
 350        clk->rate = rate;
 351        return 0;
 352}
 353
 354static int calc_clk_div(struct clk *clk, unsigned long rate,
 355                        int *psel, int *esel, int *pdiv, int *div)
 356{
 357        struct clk *mclk;
 358        unsigned long max_rate, actual_rate, mclk_rate, rate_err = -1;
 359        int i, found = 0, __div = 0, __pdiv = 0;
 360
 361        /* Don't exceed the maximum rate */
 362        max_rate = max3(clk_pll1.rate / 4, clk_pll2.rate / 4, clk_xtali.rate / 4);
 363        rate = min(rate, max_rate);
 364
 365        /*
 366         * Try the two pll's and the external clock
 367         * Because the valid predividers are 2, 2.5 and 3, we multiply
 368         * all the clocks by 2 to avoid floating point math.
 369         *
 370         * This is based on the algorithm in the ep93xx raster guide:
 371         * http://be-a-maverick.com/en/pubs/appNote/AN269REV1.pdf
 372         *
 373         */
 374        for (i = 0; i < 3; i++) {
 375                if (i == 0)
 376                        mclk = &clk_xtali;
 377                else if (i == 1)
 378                        mclk = &clk_pll1;
 379                else
 380                        mclk = &clk_pll2;
 381                mclk_rate = mclk->rate * 2;
 382
 383                /* Try each predivider value */
 384                for (__pdiv = 4; __pdiv <= 6; __pdiv++) {
 385                        __div = mclk_rate / (rate * __pdiv);
 386                        if (__div < 2 || __div > 127)
 387                                continue;
 388
 389                        actual_rate = mclk_rate / (__pdiv * __div);
 390
 391                        if (!found || abs(actual_rate - rate) < rate_err) {
 392                                *pdiv = __pdiv - 3;
 393                                *div = __div;
 394                                *psel = (i == 2);
 395                                *esel = (i != 0);
 396                                clk->parent = mclk;
 397                                clk->rate = actual_rate;
 398                                rate_err = abs(actual_rate - rate);
 399                                found = 1;
 400                        }
 401                }
 402        }
 403
 404        if (!found)
 405                return -EINVAL;
 406
 407        return 0;
 408}
 409
 410static int set_div_rate(struct clk *clk, unsigned long rate)
 411{
 412        int err, psel = 0, esel = 0, pdiv = 0, div = 0;
 413        u32 val;
 414
 415        err = calc_clk_div(clk, rate, &psel, &esel, &pdiv, &div);
 416        if (err)
 417                return err;
 418
 419        /* Clear the esel, psel, pdiv and div bits */
 420        val = __raw_readl(clk->enable_reg);
 421        val &= ~0x7fff;
 422
 423        /* Set the new esel, psel, pdiv and div bits for the new clock rate */
 424        val |= (esel ? EP93XX_SYSCON_CLKDIV_ESEL : 0) |
 425                (psel ? EP93XX_SYSCON_CLKDIV_PSEL : 0) |
 426                (pdiv << EP93XX_SYSCON_CLKDIV_PDIV_SHIFT) | div;
 427        ep93xx_syscon_swlocked_write(val, clk->enable_reg);
 428        return 0;
 429}
 430
 431static int set_i2s_sclk_rate(struct clk *clk, unsigned long rate)
 432{
 433        unsigned val = __raw_readl(clk->enable_reg);
 434
 435        if (rate == clk_i2s_mclk.rate / 2)
 436                ep93xx_syscon_swlocked_write(val & ~EP93XX_I2SCLKDIV_SDIV, 
 437                                             clk->enable_reg);
 438        else if (rate == clk_i2s_mclk.rate / 4)
 439                ep93xx_syscon_swlocked_write(val | EP93XX_I2SCLKDIV_SDIV, 
 440                                             clk->enable_reg);
 441        else
 442                return -EINVAL;
 443
 444        clk_i2s_sclk.rate = rate;
 445        return 0;
 446}
 447
 448static int set_i2s_lrclk_rate(struct clk *clk, unsigned long rate)
 449{
 450        unsigned val = __raw_readl(clk->enable_reg) & 
 451                ~EP93XX_I2SCLKDIV_LRDIV_MASK;
 452        
 453        if (rate == clk_i2s_sclk.rate / 32)
 454                ep93xx_syscon_swlocked_write(val | EP93XX_I2SCLKDIV_LRDIV32,
 455                                             clk->enable_reg);
 456        else if (rate == clk_i2s_sclk.rate / 64)
 457                ep93xx_syscon_swlocked_write(val | EP93XX_I2SCLKDIV_LRDIV64,
 458                                             clk->enable_reg);
 459        else if (rate == clk_i2s_sclk.rate / 128)
 460                ep93xx_syscon_swlocked_write(val | EP93XX_I2SCLKDIV_LRDIV128,
 461                                             clk->enable_reg);
 462        else
 463                return -EINVAL;
 464
 465        clk_i2s_lrclk.rate = rate;
 466        return 0;
 467}
 468
 469int clk_set_rate(struct clk *clk, unsigned long rate)
 470{
 471        if (clk->set_rate)
 472                return clk->set_rate(clk, rate);
 473
 474        return -EINVAL;
 475}
 476EXPORT_SYMBOL(clk_set_rate);
 477
 478long clk_round_rate(struct clk *clk, unsigned long rate)
 479{
 480        WARN_ON(clk);
 481        return 0;
 482}
 483EXPORT_SYMBOL(clk_round_rate);
 484
 485int clk_set_parent(struct clk *clk, struct clk *parent)
 486{
 487        WARN_ON(clk);
 488        return 0;
 489}
 490EXPORT_SYMBOL(clk_set_parent);
 491
 492struct clk *clk_get_parent(struct clk *clk)
 493{
 494        return clk->parent;
 495}
 496EXPORT_SYMBOL(clk_get_parent);
 497
 498
 499static char fclk_divisors[] = { 1, 2, 4, 8, 16, 1, 1, 1 };
 500static char hclk_divisors[] = { 1, 2, 4, 5, 6, 8, 16, 32 };
 501static char pclk_divisors[] = { 1, 2, 4, 8 };
 502
 503/*
 504 * PLL rate = 14.7456 MHz * (X1FBD + 1) * (X2FBD + 1) / (X2IPD + 1) / 2^PS
 505 */
 506static unsigned long calc_pll_rate(u32 config_word)
 507{
 508        unsigned long long rate;
 509        int i;
 510
 511        rate = clk_xtali.rate;
 512        rate *= ((config_word >> 11) & 0x1f) + 1;               /* X1FBD */
 513        rate *= ((config_word >> 5) & 0x3f) + 1;                /* X2FBD */
 514        do_div(rate, (config_word & 0x1f) + 1);                 /* X2IPD */
 515        for (i = 0; i < ((config_word >> 16) & 3); i++)         /* PS */
 516                rate >>= 1;
 517
 518        return (unsigned long)rate;
 519}
 520
 521static void __init ep93xx_dma_clock_init(void)
 522{
 523        clk_m2p0.rate = clk_h.rate;
 524        clk_m2p1.rate = clk_h.rate;
 525        clk_m2p2.rate = clk_h.rate;
 526        clk_m2p3.rate = clk_h.rate;
 527        clk_m2p4.rate = clk_h.rate;
 528        clk_m2p5.rate = clk_h.rate;
 529        clk_m2p6.rate = clk_h.rate;
 530        clk_m2p7.rate = clk_h.rate;
 531        clk_m2p8.rate = clk_h.rate;
 532        clk_m2p9.rate = clk_h.rate;
 533        clk_m2m0.rate = clk_h.rate;
 534        clk_m2m1.rate = clk_h.rate;
 535}
 536
 537static int __init ep93xx_clock_init(void)
 538{
 539        u32 value;
 540
 541        /* Determine the bootloader configured pll1 rate */
 542        value = __raw_readl(EP93XX_SYSCON_CLKSET1);
 543        if (!(value & EP93XX_SYSCON_CLKSET1_NBYP1))
 544                clk_pll1.rate = clk_xtali.rate;
 545        else
 546                clk_pll1.rate = calc_pll_rate(value);
 547
 548        /* Initialize the pll1 derived clocks */
 549        clk_f.rate = clk_pll1.rate / fclk_divisors[(value >> 25) & 0x7];
 550        clk_h.rate = clk_pll1.rate / hclk_divisors[(value >> 20) & 0x7];
 551        clk_p.rate = clk_h.rate / pclk_divisors[(value >> 18) & 0x3];
 552        ep93xx_dma_clock_init();
 553
 554        /* Determine the bootloader configured pll2 rate */
 555        value = __raw_readl(EP93XX_SYSCON_CLKSET2);
 556        if (!(value & EP93XX_SYSCON_CLKSET2_NBYP2))
 557                clk_pll2.rate = clk_xtali.rate;
 558        else if (value & EP93XX_SYSCON_CLKSET2_PLL2_EN)
 559                clk_pll2.rate = calc_pll_rate(value);
 560        else
 561                clk_pll2.rate = 0;
 562
 563        /* Initialize the pll2 derived clocks */
 564        clk_usb_host.rate = clk_pll2.rate / (((value >> 28) & 0xf) + 1);
 565
 566        /*
 567         * EP93xx SSP clock rate was doubled in version E2. For more information
 568         * see:
 569         *     http://www.cirrus.com/en/pubs/appNote/AN273REV4.pdf
 570         */
 571        if (ep93xx_chip_revision() < EP93XX_CHIP_REV_E2)
 572                clk_spi.rate /= 2;
 573
 574        pr_info("PLL1 running at %ld MHz, PLL2 at %ld MHz\n",
 575                clk_pll1.rate / 1000000, clk_pll2.rate / 1000000);
 576        pr_info("FCLK %ld MHz, HCLK %ld MHz, PCLK %ld MHz\n",
 577                clk_f.rate / 1000000, clk_h.rate / 1000000,
 578                clk_p.rate / 1000000);
 579
 580        clkdev_add_table(clocks, ARRAY_SIZE(clocks));
 581        return 0;
 582}
 583postcore_initcall(ep93xx_clock_init);
 584