linux/arch/mips/ar7/clock.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2007 Felix Fietkau <nbd@openwrt.org>
   3 * Copyright (C) 2007 Eugene Konev <ejka@openwrt.org>
   4 * Copyright (C) 2009 Florian Fainelli <florian@openwrt.org>
   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 * This program is distributed in the hope that it will be useful,
  12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14 * GNU General Public License for more details.
  15 *
  16 * You should have received a copy of the GNU General Public License
  17 * along with this program; if not, write to the Free Software
  18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  19 */
  20
  21#include <linux/kernel.h>
  22#include <linux/init.h>
  23#include <linux/types.h>
  24#include <linux/module.h>
  25#include <linux/delay.h>
  26#include <linux/gcd.h>
  27#include <linux/io.h>
  28#include <linux/err.h>
  29#include <linux/clk.h>
  30
  31#include <asm/addrspace.h>
  32#include <asm/mach-ar7/ar7.h>
  33
  34#define BOOT_PLL_SOURCE_MASK    0x3
  35#define CPU_PLL_SOURCE_SHIFT    16
  36#define BUS_PLL_SOURCE_SHIFT    14
  37#define USB_PLL_SOURCE_SHIFT    18
  38#define DSP_PLL_SOURCE_SHIFT    22
  39#define BOOT_PLL_SOURCE_AFE     0
  40#define BOOT_PLL_SOURCE_BUS     0
  41#define BOOT_PLL_SOURCE_REF     1
  42#define BOOT_PLL_SOURCE_XTAL    2
  43#define BOOT_PLL_SOURCE_CPU     3
  44#define BOOT_PLL_BYPASS         0x00000020
  45#define BOOT_PLL_ASYNC_MODE     0x02000000
  46#define BOOT_PLL_2TO1_MODE      0x00008000
  47
  48#define TNETD7200_CLOCK_ID_CPU  0
  49#define TNETD7200_CLOCK_ID_DSP  1
  50#define TNETD7200_CLOCK_ID_USB  2
  51
  52#define TNETD7200_DEF_CPU_CLK   211000000
  53#define TNETD7200_DEF_DSP_CLK   125000000
  54#define TNETD7200_DEF_USB_CLK   48000000
  55
  56struct tnetd7300_clock {
  57        u32 ctrl;
  58#define PREDIV_MASK     0x001f0000
  59#define PREDIV_SHIFT    16
  60#define POSTDIV_MASK    0x0000001f
  61        u32 unused1[3];
  62        u32 pll;
  63#define MUL_MASK        0x0000f000
  64#define MUL_SHIFT       12
  65#define PLL_MODE_MASK   0x00000001
  66#define PLL_NDIV        0x00000800
  67#define PLL_DIV         0x00000002
  68#define PLL_STATUS      0x00000001
  69        u32 unused2[3];
  70};
  71
  72struct tnetd7300_clocks {
  73        struct tnetd7300_clock bus;
  74        struct tnetd7300_clock cpu;
  75        struct tnetd7300_clock usb;
  76        struct tnetd7300_clock dsp;
  77};
  78
  79struct tnetd7200_clock {
  80        u32 ctrl;
  81        u32 unused1[3];
  82#define DIVISOR_ENABLE_MASK 0x00008000
  83        u32 mul;
  84        u32 prediv;
  85        u32 postdiv;
  86        u32 postdiv2;
  87        u32 unused2[6];
  88        u32 cmd;
  89        u32 status;
  90        u32 cmden;
  91        u32 padding[15];
  92};
  93
  94struct tnetd7200_clocks {
  95        struct tnetd7200_clock cpu;
  96        struct tnetd7200_clock dsp;
  97        struct tnetd7200_clock usb;
  98};
  99
 100static struct clk bus_clk = {
 101        .rate   = 125000000,
 102};
 103
 104static struct clk cpu_clk = {
 105        .rate   = 150000000,
 106};
 107
 108static struct clk dsp_clk;
 109static struct clk vbus_clk;
 110
 111static void approximate(int base, int target, int *prediv,
 112                        int *postdiv, int *mul)
 113{
 114        int i, j, k, freq, res = target;
 115        for (i = 1; i <= 16; i++)
 116                for (j = 1; j <= 32; j++)
 117                        for (k = 1; k <= 32; k++) {
 118                                freq = abs(base / j * i / k - target);
 119                                if (freq < res) {
 120                                        res = freq;
 121                                        *mul = i;
 122                                        *prediv = j;
 123                                        *postdiv = k;
 124                                }
 125                        }
 126}
 127
 128static void calculate(int base, int target, int *prediv, int *postdiv,
 129        int *mul)
 130{
 131        int tmp_gcd, tmp_base, tmp_freq;
 132
 133        for (*prediv = 1; *prediv <= 32; (*prediv)++) {
 134                tmp_base = base / *prediv;
 135                tmp_gcd = gcd(target, tmp_base);
 136                *mul = target / tmp_gcd;
 137                *postdiv = tmp_base / tmp_gcd;
 138                if ((*mul < 1) || (*mul >= 16))
 139                        continue;
 140                if ((*postdiv > 0) & (*postdiv <= 32))
 141                        break;
 142        }
 143
 144        if (base / *prediv * *mul / *postdiv != target) {
 145                approximate(base, target, prediv, postdiv, mul);
 146                tmp_freq = base / *prediv * *mul / *postdiv;
 147                printk(KERN_WARNING
 148                       "Adjusted requested frequency %d to %d\n",
 149                       target, tmp_freq);
 150        }
 151
 152        printk(KERN_DEBUG "Clocks: prediv: %d, postdiv: %d, mul: %d\n",
 153               *prediv, *postdiv, *mul);
 154}
 155
 156static int tnetd7300_dsp_clock(void)
 157{
 158        u32 didr1, didr2;
 159        u8 rev = ar7_chip_rev();
 160        didr1 = readl((void *)KSEG1ADDR(AR7_REGS_GPIO + 0x18));
 161        didr2 = readl((void *)KSEG1ADDR(AR7_REGS_GPIO + 0x1c));
 162        if (didr2 & (1 << 23))
 163                return 0;
 164        if ((rev >= 0x23) && (rev != 0x57))
 165                return 250000000;
 166        if ((((didr2 & 0x1fff) << 10) | ((didr1 & 0xffc00000) >> 22))
 167            > 4208000)
 168                return 250000000;
 169        return 0;
 170}
 171
 172static int tnetd7300_get_clock(u32 shift, struct tnetd7300_clock *clock,
 173        u32 *bootcr, u32 bus_clock)
 174{
 175        int product;
 176        int base_clock = AR7_REF_CLOCK;
 177        u32 ctrl = readl(&clock->ctrl);
 178        u32 pll = readl(&clock->pll);
 179        int prediv = ((ctrl & PREDIV_MASK) >> PREDIV_SHIFT) + 1;
 180        int postdiv = (ctrl & POSTDIV_MASK) + 1;
 181        int divisor = prediv * postdiv;
 182        int mul = ((pll & MUL_MASK) >> MUL_SHIFT) + 1;
 183
 184        switch ((*bootcr & (BOOT_PLL_SOURCE_MASK << shift)) >> shift) {
 185        case BOOT_PLL_SOURCE_BUS:
 186                base_clock = bus_clock;
 187                break;
 188        case BOOT_PLL_SOURCE_REF:
 189                base_clock = AR7_REF_CLOCK;
 190                break;
 191        case BOOT_PLL_SOURCE_XTAL:
 192                base_clock = AR7_XTAL_CLOCK;
 193                break;
 194        case BOOT_PLL_SOURCE_CPU:
 195                base_clock = cpu_clk.rate;
 196                break;
 197        }
 198
 199        if (*bootcr & BOOT_PLL_BYPASS)
 200                return base_clock / divisor;
 201
 202        if ((pll & PLL_MODE_MASK) == 0)
 203                return (base_clock >> (mul / 16 + 1)) / divisor;
 204
 205        if ((pll & (PLL_NDIV | PLL_DIV)) == (PLL_NDIV | PLL_DIV)) {
 206                product = (mul & 1) ?
 207                        (base_clock * mul) >> 1 :
 208                        (base_clock * (mul - 1)) >> 2;
 209                return product / divisor;
 210        }
 211
 212        if (mul == 16)
 213                return base_clock / divisor;
 214
 215        return base_clock * mul / divisor;
 216}
 217
 218static void tnetd7300_set_clock(u32 shift, struct tnetd7300_clock *clock,
 219        u32 *bootcr, u32 frequency)
 220{
 221        int prediv, postdiv, mul;
 222        int base_clock = bus_clk.rate;
 223
 224        switch ((*bootcr & (BOOT_PLL_SOURCE_MASK << shift)) >> shift) {
 225        case BOOT_PLL_SOURCE_BUS:
 226                base_clock = bus_clk.rate;
 227                break;
 228        case BOOT_PLL_SOURCE_REF:
 229                base_clock = AR7_REF_CLOCK;
 230                break;
 231        case BOOT_PLL_SOURCE_XTAL:
 232                base_clock = AR7_XTAL_CLOCK;
 233                break;
 234        case BOOT_PLL_SOURCE_CPU:
 235                base_clock = cpu_clk.rate;
 236                break;
 237        }
 238
 239        calculate(base_clock, frequency, &prediv, &postdiv, &mul);
 240
 241        writel(((prediv - 1) << PREDIV_SHIFT) | (postdiv - 1), &clock->ctrl);
 242        mdelay(1);
 243        writel(4, &clock->pll);
 244        while (readl(&clock->pll) & PLL_STATUS)
 245                ;
 246        writel(((mul - 1) << MUL_SHIFT) | (0xff << 3) | 0x0e, &clock->pll);
 247        mdelay(75);
 248}
 249
 250static void __init tnetd7300_init_clocks(void)
 251{
 252        u32 *bootcr = (u32 *)ioremap_nocache(AR7_REGS_DCL, 4);
 253        struct tnetd7300_clocks *clocks =
 254                                        ioremap_nocache(UR8_REGS_CLOCKS,
 255                                        sizeof(struct tnetd7300_clocks));
 256
 257        bus_clk.rate = tnetd7300_get_clock(BUS_PLL_SOURCE_SHIFT,
 258                &clocks->bus, bootcr, AR7_AFE_CLOCK);
 259
 260        if (*bootcr & BOOT_PLL_ASYNC_MODE)
 261                cpu_clk.rate = tnetd7300_get_clock(CPU_PLL_SOURCE_SHIFT,
 262                        &clocks->cpu, bootcr, AR7_AFE_CLOCK);
 263        else
 264                cpu_clk.rate = bus_clk.rate;
 265
 266        if (dsp_clk.rate == 250000000)
 267                tnetd7300_set_clock(DSP_PLL_SOURCE_SHIFT, &clocks->dsp,
 268                        bootcr, dsp_clk.rate);
 269
 270        iounmap(clocks);
 271        iounmap(bootcr);
 272}
 273
 274static void tnetd7200_set_clock(int base, struct tnetd7200_clock *clock,
 275        int prediv, int postdiv, int postdiv2, int mul, u32 frequency)
 276{
 277        printk(KERN_INFO
 278                "Clocks: base = %d, frequency = %u, prediv = %d, "
 279                "postdiv = %d, postdiv2 = %d, mul = %d\n",
 280                base, frequency, prediv, postdiv, postdiv2, mul);
 281
 282        writel(0, &clock->ctrl);
 283        writel(DIVISOR_ENABLE_MASK | ((prediv - 1) & 0x1F), &clock->prediv);
 284        writel((mul - 1) & 0xF, &clock->mul);
 285
 286        while (readl(&clock->status) & 0x1)
 287                ; /* nop */
 288
 289        writel(DIVISOR_ENABLE_MASK | ((postdiv - 1) & 0x1F), &clock->postdiv);
 290
 291        writel(readl(&clock->cmden) | 1, &clock->cmden);
 292        writel(readl(&clock->cmd) | 1, &clock->cmd);
 293
 294        while (readl(&clock->status) & 0x1)
 295                ; /* nop */
 296
 297        writel(DIVISOR_ENABLE_MASK | ((postdiv2 - 1) & 0x1F), &clock->postdiv2);
 298
 299        writel(readl(&clock->cmden) | 1, &clock->cmden);
 300        writel(readl(&clock->cmd) | 1, &clock->cmd);
 301
 302        while (readl(&clock->status) & 0x1)
 303                ; /* nop */
 304
 305        writel(readl(&clock->ctrl) | 1, &clock->ctrl);
 306}
 307
 308static int tnetd7200_get_clock_base(int clock_id, u32 *bootcr)
 309{
 310        if (*bootcr & BOOT_PLL_ASYNC_MODE)
 311                /* Async */
 312                switch (clock_id) {
 313                case TNETD7200_CLOCK_ID_DSP:
 314                        return AR7_REF_CLOCK;
 315                default:
 316                        return AR7_AFE_CLOCK;
 317                }
 318        else
 319                /* Sync */
 320                if (*bootcr & BOOT_PLL_2TO1_MODE)
 321                        /* 2:1 */
 322                        switch (clock_id) {
 323                        case TNETD7200_CLOCK_ID_DSP:
 324                                return AR7_REF_CLOCK;
 325                        default:
 326                                return AR7_AFE_CLOCK;
 327                        }
 328                else
 329                        /* 1:1 */
 330                        return AR7_REF_CLOCK;
 331}
 332
 333
 334static void __init tnetd7200_init_clocks(void)
 335{
 336        u32 *bootcr = (u32 *)ioremap_nocache(AR7_REGS_DCL, 4);
 337        struct tnetd7200_clocks *clocks =
 338                                        ioremap_nocache(AR7_REGS_CLOCKS,
 339                                        sizeof(struct tnetd7200_clocks));
 340        int cpu_base, cpu_mul, cpu_prediv, cpu_postdiv;
 341        int dsp_base, dsp_mul, dsp_prediv, dsp_postdiv;
 342        int usb_base, usb_mul, usb_prediv, usb_postdiv;
 343
 344        cpu_base = tnetd7200_get_clock_base(TNETD7200_CLOCK_ID_CPU, bootcr);
 345        dsp_base = tnetd7200_get_clock_base(TNETD7200_CLOCK_ID_DSP, bootcr);
 346
 347        if (*bootcr & BOOT_PLL_ASYNC_MODE) {
 348                printk(KERN_INFO "Clocks: Async mode\n");
 349
 350                printk(KERN_INFO "Clocks: Setting DSP clock\n");
 351                calculate(dsp_base, TNETD7200_DEF_DSP_CLK,
 352                        &dsp_prediv, &dsp_postdiv, &dsp_mul);
 353                bus_clk.rate =
 354                        ((dsp_base / dsp_prediv) * dsp_mul) / dsp_postdiv;
 355                tnetd7200_set_clock(dsp_base, &clocks->dsp,
 356                        dsp_prediv, dsp_postdiv * 2, dsp_postdiv, dsp_mul * 2,
 357                        bus_clk.rate);
 358
 359                printk(KERN_INFO "Clocks: Setting CPU clock\n");
 360                calculate(cpu_base, TNETD7200_DEF_CPU_CLK, &cpu_prediv,
 361                        &cpu_postdiv, &cpu_mul);
 362                cpu_clk.rate =
 363                        ((cpu_base / cpu_prediv) * cpu_mul) / cpu_postdiv;
 364                tnetd7200_set_clock(cpu_base, &clocks->cpu,
 365                        cpu_prediv, cpu_postdiv, -1, cpu_mul,
 366                        cpu_clk.rate);
 367
 368        } else
 369                if (*bootcr & BOOT_PLL_2TO1_MODE) {
 370                        printk(KERN_INFO "Clocks: Sync 2:1 mode\n");
 371
 372                        printk(KERN_INFO "Clocks: Setting CPU clock\n");
 373                        calculate(cpu_base, TNETD7200_DEF_CPU_CLK, &cpu_prediv,
 374                                &cpu_postdiv, &cpu_mul);
 375                        cpu_clk.rate = ((cpu_base / cpu_prediv) * cpu_mul)
 376                                                                / cpu_postdiv;
 377                        tnetd7200_set_clock(cpu_base, &clocks->cpu,
 378                                cpu_prediv, cpu_postdiv, -1, cpu_mul,
 379                                cpu_clk.rate);
 380
 381                        printk(KERN_INFO "Clocks: Setting DSP clock\n");
 382                        calculate(dsp_base, TNETD7200_DEF_DSP_CLK, &dsp_prediv,
 383                                &dsp_postdiv, &dsp_mul);
 384                        bus_clk.rate = cpu_clk.rate / 2;
 385                        tnetd7200_set_clock(dsp_base, &clocks->dsp,
 386                                dsp_prediv, dsp_postdiv * 2, dsp_postdiv,
 387                                dsp_mul * 2, bus_clk.rate);
 388                } else {
 389                        printk(KERN_INFO "Clocks: Sync 1:1 mode\n");
 390
 391                        printk(KERN_INFO "Clocks: Setting DSP clock\n");
 392                        calculate(dsp_base, TNETD7200_DEF_DSP_CLK, &dsp_prediv,
 393                                &dsp_postdiv, &dsp_mul);
 394                        bus_clk.rate = ((dsp_base / dsp_prediv) * dsp_mul)
 395                                                                / dsp_postdiv;
 396                        tnetd7200_set_clock(dsp_base, &clocks->dsp,
 397                                dsp_prediv, dsp_postdiv * 2, dsp_postdiv,
 398                                dsp_mul * 2, bus_clk.rate);
 399
 400                        cpu_clk.rate = bus_clk.rate;
 401                }
 402
 403        printk(KERN_INFO "Clocks: Setting USB clock\n");
 404        usb_base = bus_clk.rate;
 405        calculate(usb_base, TNETD7200_DEF_USB_CLK, &usb_prediv,
 406                &usb_postdiv, &usb_mul);
 407        tnetd7200_set_clock(usb_base, &clocks->usb,
 408                usb_prediv, usb_postdiv, -1, usb_mul,
 409                TNETD7200_DEF_USB_CLK);
 410
 411        dsp_clk.rate = cpu_clk.rate;
 412
 413        iounmap(clocks);
 414        iounmap(bootcr);
 415}
 416
 417/*
 418 * Linux clock API
 419 */
 420int clk_enable(struct clk *clk)
 421{
 422        return 0;
 423}
 424EXPORT_SYMBOL(clk_enable);
 425
 426void clk_disable(struct clk *clk)
 427{
 428}
 429EXPORT_SYMBOL(clk_disable);
 430
 431unsigned long clk_get_rate(struct clk *clk)
 432{
 433        return clk->rate;
 434}
 435EXPORT_SYMBOL(clk_get_rate);
 436
 437struct clk *clk_get(struct device *dev, const char *id)
 438{
 439        if (!strcmp(id, "bus"))
 440                return &bus_clk;
 441        /* cpmac and vbus share the same rate */
 442        if (!strcmp(id, "cpmac"))
 443                return &vbus_clk;
 444        if (!strcmp(id, "cpu"))
 445                return &cpu_clk;
 446        if (!strcmp(id, "dsp"))
 447                return &dsp_clk;
 448        if (!strcmp(id, "vbus"))
 449                return &vbus_clk;
 450        return ERR_PTR(-ENOENT);
 451}
 452EXPORT_SYMBOL(clk_get);
 453
 454void clk_put(struct clk *clk)
 455{
 456}
 457EXPORT_SYMBOL(clk_put);
 458
 459void __init ar7_init_clocks(void)
 460{
 461        switch (ar7_chip_id()) {
 462        case AR7_CHIP_7100:
 463        case AR7_CHIP_7200:
 464                tnetd7200_init_clocks();
 465                break;
 466        case AR7_CHIP_7300:
 467                dsp_clk.rate = tnetd7300_dsp_clock();
 468                tnetd7300_init_clocks();
 469                break;
 470        default:
 471                break;
 472        }
 473        /* adjust vbus clock rate */
 474        vbus_clk.rate = bus_clk.rate / 2;
 475}
 476