linux/drivers/cpufreq/pmac32-cpufreq.c
<<
>>
Prefs
   1/*
   2 *  Copyright (C) 2002 - 2005 Benjamin Herrenschmidt <benh@kernel.crashing.org>
   3 *  Copyright (C) 2004        John Steele Scott <toojays@toojays.net>
   4 *
   5 * This program is free software; you can redistribute it and/or modify
   6 * it under the terms of the GNU General Public License version 2 as
   7 * published by the Free Software Foundation.
   8 *
   9 * TODO: Need a big cleanup here. Basically, we need to have different
  10 * cpufreq_driver structures for the different type of HW instead of the
  11 * current mess. We also need to better deal with the detection of the
  12 * type of machine.
  13 *
  14 */
  15
  16#include <linux/module.h>
  17#include <linux/types.h>
  18#include <linux/errno.h>
  19#include <linux/kernel.h>
  20#include <linux/delay.h>
  21#include <linux/sched.h>
  22#include <linux/adb.h>
  23#include <linux/pmu.h>
  24#include <linux/cpufreq.h>
  25#include <linux/init.h>
  26#include <linux/device.h>
  27#include <linux/hardirq.h>
  28#include <linux/of_device.h>
  29#include <asm/prom.h>
  30#include <asm/machdep.h>
  31#include <asm/irq.h>
  32#include <asm/pmac_feature.h>
  33#include <asm/mmu_context.h>
  34#include <asm/sections.h>
  35#include <asm/cputable.h>
  36#include <asm/time.h>
  37#include <asm/mpic.h>
  38#include <asm/keylargo.h>
  39#include <asm/switch_to.h>
  40
  41/* WARNING !!! This will cause calibrate_delay() to be called,
  42 * but this is an __init function ! So you MUST go edit
  43 * init/main.c to make it non-init before enabling DEBUG_FREQ
  44 */
  45#undef DEBUG_FREQ
  46
  47extern void low_choose_7447a_dfs(int dfs);
  48extern void low_choose_750fx_pll(int pll);
  49extern void low_sleep_handler(void);
  50
  51/*
  52 * Currently, PowerMac cpufreq supports only high & low frequencies
  53 * that are set by the firmware
  54 */
  55static unsigned int low_freq;
  56static unsigned int hi_freq;
  57static unsigned int cur_freq;
  58static unsigned int sleep_freq;
  59static unsigned long transition_latency;
  60
  61/*
  62 * Different models uses different mechanisms to switch the frequency
  63 */
  64static int (*set_speed_proc)(int low_speed);
  65static unsigned int (*get_speed_proc)(void);
  66
  67/*
  68 * Some definitions used by the various speedprocs
  69 */
  70static u32 voltage_gpio;
  71static u32 frequency_gpio;
  72static u32 slew_done_gpio;
  73static int no_schedule;
  74static int has_cpu_l2lve;
  75static int is_pmu_based;
  76
  77/* There are only two frequency states for each processor. Values
  78 * are in kHz for the time being.
  79 */
  80#define CPUFREQ_HIGH                  0
  81#define CPUFREQ_LOW                   1
  82
  83static struct cpufreq_frequency_table pmac_cpu_freqs[] = {
  84        {CPUFREQ_HIGH,          0},
  85        {CPUFREQ_LOW,           0},
  86        {0,                     CPUFREQ_TABLE_END},
  87};
  88
  89static struct freq_attr* pmac_cpu_freqs_attr[] = {
  90        &cpufreq_freq_attr_scaling_available_freqs,
  91        NULL,
  92};
  93
  94static inline void local_delay(unsigned long ms)
  95{
  96        if (no_schedule)
  97                mdelay(ms);
  98        else
  99                msleep(ms);
 100}
 101
 102#ifdef DEBUG_FREQ
 103static inline void debug_calc_bogomips(void)
 104{
 105        /* This will cause a recalc of bogomips and display the
 106         * result. We backup/restore the value to avoid affecting the
 107         * core cpufreq framework's own calculation.
 108         */
 109        unsigned long save_lpj = loops_per_jiffy;
 110        calibrate_delay();
 111        loops_per_jiffy = save_lpj;
 112}
 113#endif /* DEBUG_FREQ */
 114
 115/* Switch CPU speed under 750FX CPU control
 116 */
 117static int cpu_750fx_cpu_speed(int low_speed)
 118{
 119        u32 hid2;
 120
 121        if (low_speed == 0) {
 122                /* ramping up, set voltage first */
 123                pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x05);
 124                /* Make sure we sleep for at least 1ms */
 125                local_delay(10);
 126
 127                /* tweak L2 for high voltage */
 128                if (has_cpu_l2lve) {
 129                        hid2 = mfspr(SPRN_HID2);
 130                        hid2 &= ~0x2000;
 131                        mtspr(SPRN_HID2, hid2);
 132                }
 133        }
 134#ifdef CONFIG_6xx
 135        low_choose_750fx_pll(low_speed);
 136#endif
 137        if (low_speed == 1) {
 138                /* tweak L2 for low voltage */
 139                if (has_cpu_l2lve) {
 140                        hid2 = mfspr(SPRN_HID2);
 141                        hid2 |= 0x2000;
 142                        mtspr(SPRN_HID2, hid2);
 143                }
 144
 145                /* ramping down, set voltage last */
 146                pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x04);
 147                local_delay(10);
 148        }
 149
 150        return 0;
 151}
 152
 153static unsigned int cpu_750fx_get_cpu_speed(void)
 154{
 155        if (mfspr(SPRN_HID1) & HID1_PS)
 156                return low_freq;
 157        else
 158                return hi_freq;
 159}
 160
 161/* Switch CPU speed using DFS */
 162static int dfs_set_cpu_speed(int low_speed)
 163{
 164        if (low_speed == 0) {
 165                /* ramping up, set voltage first */
 166                pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x05);
 167                /* Make sure we sleep for at least 1ms */
 168                local_delay(1);
 169        }
 170
 171        /* set frequency */
 172#ifdef CONFIG_6xx
 173        low_choose_7447a_dfs(low_speed);
 174#endif
 175        udelay(100);
 176
 177        if (low_speed == 1) {
 178                /* ramping down, set voltage last */
 179                pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x04);
 180                local_delay(1);
 181        }
 182
 183        return 0;
 184}
 185
 186static unsigned int dfs_get_cpu_speed(void)
 187{
 188        if (mfspr(SPRN_HID1) & HID1_DFS)
 189                return low_freq;
 190        else
 191                return hi_freq;
 192}
 193
 194
 195/* Switch CPU speed using slewing GPIOs
 196 */
 197static int gpios_set_cpu_speed(int low_speed)
 198{
 199        int gpio, timeout = 0;
 200
 201        /* If ramping up, set voltage first */
 202        if (low_speed == 0) {
 203                pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x05);
 204                /* Delay is way too big but it's ok, we schedule */
 205                local_delay(10);
 206        }
 207
 208        /* Set frequency */
 209        gpio =  pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, frequency_gpio, 0);
 210        if (low_speed == ((gpio & 0x01) == 0))
 211                goto skip;
 212
 213        pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, frequency_gpio,
 214                          low_speed ? 0x04 : 0x05);
 215        udelay(200);
 216        do {
 217                if (++timeout > 100)
 218                        break;
 219                local_delay(1);
 220                gpio = pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, slew_done_gpio, 0);
 221        } while((gpio & 0x02) == 0);
 222 skip:
 223        /* If ramping down, set voltage last */
 224        if (low_speed == 1) {
 225                pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x04);
 226                /* Delay is way too big but it's ok, we schedule */
 227                local_delay(10);
 228        }
 229
 230#ifdef DEBUG_FREQ
 231        debug_calc_bogomips();
 232#endif
 233
 234        return 0;
 235}
 236
 237/* Switch CPU speed under PMU control
 238 */
 239static int pmu_set_cpu_speed(int low_speed)
 240{
 241        struct adb_request req;
 242        unsigned long save_l2cr;
 243        unsigned long save_l3cr;
 244        unsigned int pic_prio;
 245        unsigned long flags;
 246
 247        preempt_disable();
 248
 249#ifdef DEBUG_FREQ
 250        printk(KERN_DEBUG "HID1, before: %x\n", mfspr(SPRN_HID1));
 251#endif
 252        pmu_suspend();
 253
 254        /* Disable all interrupt sources on openpic */
 255        pic_prio = mpic_cpu_get_priority();
 256        mpic_cpu_set_priority(0xf);
 257
 258        /* Make sure the decrementer won't interrupt us */
 259        asm volatile("mtdec %0" : : "r" (0x7fffffff));
 260        /* Make sure any pending DEC interrupt occurring while we did
 261         * the above didn't re-enable the DEC */
 262        mb();
 263        asm volatile("mtdec %0" : : "r" (0x7fffffff));
 264
 265        /* We can now disable MSR_EE */
 266        local_irq_save(flags);
 267
 268        /* Giveup the FPU & vec */
 269        enable_kernel_fp();
 270
 271#ifdef CONFIG_ALTIVEC
 272        if (cpu_has_feature(CPU_FTR_ALTIVEC))
 273                enable_kernel_altivec();
 274#endif /* CONFIG_ALTIVEC */
 275
 276        /* Save & disable L2 and L3 caches */
 277        save_l3cr = _get_L3CR();        /* (returns -1 if not available) */
 278        save_l2cr = _get_L2CR();        /* (returns -1 if not available) */
 279
 280        /* Send the new speed command. My assumption is that this command
 281         * will cause PLL_CFG[0..3] to be changed next time CPU goes to sleep
 282         */
 283        pmu_request(&req, NULL, 6, PMU_CPU_SPEED, 'W', 'O', 'O', 'F', low_speed);
 284        while (!req.complete)
 285                pmu_poll();
 286
 287        /* Prepare the northbridge for the speed transition */
 288        pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,1,1);
 289
 290        /* Call low level code to backup CPU state and recover from
 291         * hardware reset
 292         */
 293        low_sleep_handler();
 294
 295        /* Restore the northbridge */
 296        pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,1,0);
 297
 298        /* Restore L2 cache */
 299        if (save_l2cr != 0xffffffff && (save_l2cr & L2CR_L2E) != 0)
 300                _set_L2CR(save_l2cr);
 301        /* Restore L3 cache */
 302        if (save_l3cr != 0xffffffff && (save_l3cr & L3CR_L3E) != 0)
 303                _set_L3CR(save_l3cr);
 304
 305        /* Restore userland MMU context */
 306        switch_mmu_context(NULL, current->active_mm);
 307
 308#ifdef DEBUG_FREQ
 309        printk(KERN_DEBUG "HID1, after: %x\n", mfspr(SPRN_HID1));
 310#endif
 311
 312        /* Restore low level PMU operations */
 313        pmu_unlock();
 314
 315        /*
 316         * Restore decrementer; we'll take a decrementer interrupt
 317         * as soon as interrupts are re-enabled and the generic
 318         * clockevents code will reprogram it with the right value.
 319         */
 320        set_dec(1);
 321
 322        /* Restore interrupts */
 323        mpic_cpu_set_priority(pic_prio);
 324
 325        /* Let interrupts flow again ... */
 326        local_irq_restore(flags);
 327
 328#ifdef DEBUG_FREQ
 329        debug_calc_bogomips();
 330#endif
 331
 332        pmu_resume();
 333
 334        preempt_enable();
 335
 336        return 0;
 337}
 338
 339static int do_set_cpu_speed(struct cpufreq_policy *policy, int speed_mode,
 340                int notify)
 341{
 342        struct cpufreq_freqs freqs;
 343        unsigned long l3cr;
 344        static unsigned long prev_l3cr;
 345
 346        freqs.old = cur_freq;
 347        freqs.new = (speed_mode == CPUFREQ_HIGH) ? hi_freq : low_freq;
 348
 349        if (freqs.old == freqs.new)
 350                return 0;
 351
 352        if (notify)
 353                cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
 354        if (speed_mode == CPUFREQ_LOW &&
 355            cpu_has_feature(CPU_FTR_L3CR)) {
 356                l3cr = _get_L3CR();
 357                if (l3cr & L3CR_L3E) {
 358                        prev_l3cr = l3cr;
 359                        _set_L3CR(0);
 360                }
 361        }
 362        set_speed_proc(speed_mode == CPUFREQ_LOW);
 363        if (speed_mode == CPUFREQ_HIGH &&
 364            cpu_has_feature(CPU_FTR_L3CR)) {
 365                l3cr = _get_L3CR();
 366                if ((prev_l3cr & L3CR_L3E) && l3cr != prev_l3cr)
 367                        _set_L3CR(prev_l3cr);
 368        }
 369        if (notify)
 370                cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
 371        cur_freq = (speed_mode == CPUFREQ_HIGH) ? hi_freq : low_freq;
 372
 373        return 0;
 374}
 375
 376static unsigned int pmac_cpufreq_get_speed(unsigned int cpu)
 377{
 378        return cur_freq;
 379}
 380
 381static int pmac_cpufreq_verify(struct cpufreq_policy *policy)
 382{
 383        return cpufreq_frequency_table_verify(policy, pmac_cpu_freqs);
 384}
 385
 386static int pmac_cpufreq_target( struct cpufreq_policy *policy,
 387                                        unsigned int target_freq,
 388                                        unsigned int relation)
 389{
 390        unsigned int    newstate = 0;
 391        int             rc;
 392
 393        if (cpufreq_frequency_table_target(policy, pmac_cpu_freqs,
 394                        target_freq, relation, &newstate))
 395                return -EINVAL;
 396
 397        rc = do_set_cpu_speed(policy, newstate, 1);
 398
 399        ppc_proc_freq = cur_freq * 1000ul;
 400        return rc;
 401}
 402
 403static int pmac_cpufreq_cpu_init(struct cpufreq_policy *policy)
 404{
 405        if (policy->cpu != 0)
 406                return -ENODEV;
 407
 408        policy->cpuinfo.transition_latency      = transition_latency;
 409        policy->cur = cur_freq;
 410
 411        cpufreq_frequency_table_get_attr(pmac_cpu_freqs, policy->cpu);
 412        return cpufreq_frequency_table_cpuinfo(policy, pmac_cpu_freqs);
 413}
 414
 415static u32 read_gpio(struct device_node *np)
 416{
 417        const u32 *reg = of_get_property(np, "reg", NULL);
 418        u32 offset;
 419
 420        if (reg == NULL)
 421                return 0;
 422        /* That works for all keylargos but shall be fixed properly
 423         * some day... The problem is that it seems we can't rely
 424         * on the "reg" property of the GPIO nodes, they are either
 425         * relative to the base of KeyLargo or to the base of the
 426         * GPIO space, and the device-tree doesn't help.
 427         */
 428        offset = *reg;
 429        if (offset < KEYLARGO_GPIO_LEVELS0)
 430                offset += KEYLARGO_GPIO_LEVELS0;
 431        return offset;
 432}
 433
 434static int pmac_cpufreq_suspend(struct cpufreq_policy *policy)
 435{
 436        /* Ok, this could be made a bit smarter, but let's be robust for now. We
 437         * always force a speed change to high speed before sleep, to make sure
 438         * we have appropriate voltage and/or bus speed for the wakeup process,
 439         * and to make sure our loops_per_jiffies are "good enough", that is will
 440         * not cause too short delays if we sleep in low speed and wake in high
 441         * speed..
 442         */
 443        no_schedule = 1;
 444        sleep_freq = cur_freq;
 445        if (cur_freq == low_freq && !is_pmu_based)
 446                do_set_cpu_speed(policy, CPUFREQ_HIGH, 0);
 447        return 0;
 448}
 449
 450static int pmac_cpufreq_resume(struct cpufreq_policy *policy)
 451{
 452        /* If we resume, first check if we have a get() function */
 453        if (get_speed_proc)
 454                cur_freq = get_speed_proc();
 455        else
 456                cur_freq = 0;
 457
 458        /* We don't, hrm... we don't really know our speed here, best
 459         * is that we force a switch to whatever it was, which is
 460         * probably high speed due to our suspend() routine
 461         */
 462        do_set_cpu_speed(policy, sleep_freq == low_freq ?
 463                         CPUFREQ_LOW : CPUFREQ_HIGH, 0);
 464
 465        ppc_proc_freq = cur_freq * 1000ul;
 466
 467        no_schedule = 0;
 468        return 0;
 469}
 470
 471static struct cpufreq_driver pmac_cpufreq_driver = {
 472        .verify         = pmac_cpufreq_verify,
 473        .target         = pmac_cpufreq_target,
 474        .get            = pmac_cpufreq_get_speed,
 475        .init           = pmac_cpufreq_cpu_init,
 476        .suspend        = pmac_cpufreq_suspend,
 477        .resume         = pmac_cpufreq_resume,
 478        .flags          = CPUFREQ_PM_NO_WARN,
 479        .attr           = pmac_cpu_freqs_attr,
 480        .name           = "powermac",
 481};
 482
 483
 484static int pmac_cpufreq_init_MacRISC3(struct device_node *cpunode)
 485{
 486        struct device_node *volt_gpio_np = of_find_node_by_name(NULL,
 487                                                                "voltage-gpio");
 488        struct device_node *freq_gpio_np = of_find_node_by_name(NULL,
 489                                                                "frequency-gpio");
 490        struct device_node *slew_done_gpio_np = of_find_node_by_name(NULL,
 491                                                                     "slewing-done");
 492        const u32 *value;
 493
 494        /*
 495         * Check to see if it's GPIO driven or PMU only
 496         *
 497         * The way we extract the GPIO address is slightly hackish, but it
 498         * works well enough for now. We need to abstract the whole GPIO
 499         * stuff sooner or later anyway
 500         */
 501
 502        if (volt_gpio_np)
 503                voltage_gpio = read_gpio(volt_gpio_np);
 504        if (freq_gpio_np)
 505                frequency_gpio = read_gpio(freq_gpio_np);
 506        if (slew_done_gpio_np)
 507                slew_done_gpio = read_gpio(slew_done_gpio_np);
 508
 509        /* If we use the frequency GPIOs, calculate the min/max speeds based
 510         * on the bus frequencies
 511         */
 512        if (frequency_gpio && slew_done_gpio) {
 513                int lenp, rc;
 514                const u32 *freqs, *ratio;
 515
 516                freqs = of_get_property(cpunode, "bus-frequencies", &lenp);
 517                lenp /= sizeof(u32);
 518                if (freqs == NULL || lenp != 2) {
 519                        printk(KERN_ERR "cpufreq: bus-frequencies incorrect or missing\n");
 520                        return 1;
 521                }
 522                ratio = of_get_property(cpunode, "processor-to-bus-ratio*2",
 523                                                NULL);
 524                if (ratio == NULL) {
 525                        printk(KERN_ERR "cpufreq: processor-to-bus-ratio*2 missing\n");
 526                        return 1;
 527                }
 528
 529                /* Get the min/max bus frequencies */
 530                low_freq = min(freqs[0], freqs[1]);
 531                hi_freq = max(freqs[0], freqs[1]);
 532
 533                /* Grrrr.. It _seems_ that the device-tree is lying on the low bus
 534                 * frequency, it claims it to be around 84Mhz on some models while
 535                 * it appears to be approx. 101Mhz on all. Let's hack around here...
 536                 * fortunately, we don't need to be too precise
 537                 */
 538                if (low_freq < 98000000)
 539                        low_freq = 101000000;
 540
 541                /* Convert those to CPU core clocks */
 542                low_freq = (low_freq * (*ratio)) / 2000;
 543                hi_freq = (hi_freq * (*ratio)) / 2000;
 544
 545                /* Now we get the frequencies, we read the GPIO to see what is out current
 546                 * speed
 547                 */
 548                rc = pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, frequency_gpio, 0);
 549                cur_freq = (rc & 0x01) ? hi_freq : low_freq;
 550
 551                set_speed_proc = gpios_set_cpu_speed;
 552                return 1;
 553        }
 554
 555        /* If we use the PMU, look for the min & max frequencies in the
 556         * device-tree
 557         */
 558        value = of_get_property(cpunode, "min-clock-frequency", NULL);
 559        if (!value)
 560                return 1;
 561        low_freq = (*value) / 1000;
 562        /* The PowerBook G4 12" (PowerBook6,1) has an error in the device-tree
 563         * here */
 564        if (low_freq < 100000)
 565                low_freq *= 10;
 566
 567        value = of_get_property(cpunode, "max-clock-frequency", NULL);
 568        if (!value)
 569                return 1;
 570        hi_freq = (*value) / 1000;
 571        set_speed_proc = pmu_set_cpu_speed;
 572        is_pmu_based = 1;
 573
 574        return 0;
 575}
 576
 577static int pmac_cpufreq_init_7447A(struct device_node *cpunode)
 578{
 579        struct device_node *volt_gpio_np;
 580
 581        if (of_get_property(cpunode, "dynamic-power-step", NULL) == NULL)
 582                return 1;
 583
 584        volt_gpio_np = of_find_node_by_name(NULL, "cpu-vcore-select");
 585        if (volt_gpio_np)
 586                voltage_gpio = read_gpio(volt_gpio_np);
 587        if (!voltage_gpio){
 588                printk(KERN_ERR "cpufreq: missing cpu-vcore-select gpio\n");
 589                return 1;
 590        }
 591
 592        /* OF only reports the high frequency */
 593        hi_freq = cur_freq;
 594        low_freq = cur_freq/2;
 595
 596        /* Read actual frequency from CPU */
 597        cur_freq = dfs_get_cpu_speed();
 598        set_speed_proc = dfs_set_cpu_speed;
 599        get_speed_proc = dfs_get_cpu_speed;
 600
 601        return 0;
 602}
 603
 604static int pmac_cpufreq_init_750FX(struct device_node *cpunode)
 605{
 606        struct device_node *volt_gpio_np;
 607        u32 pvr;
 608        const u32 *value;
 609
 610        if (of_get_property(cpunode, "dynamic-power-step", NULL) == NULL)
 611                return 1;
 612
 613        hi_freq = cur_freq;
 614        value = of_get_property(cpunode, "reduced-clock-frequency", NULL);
 615        if (!value)
 616                return 1;
 617        low_freq = (*value) / 1000;
 618
 619        volt_gpio_np = of_find_node_by_name(NULL, "cpu-vcore-select");
 620        if (volt_gpio_np)
 621                voltage_gpio = read_gpio(volt_gpio_np);
 622
 623        pvr = mfspr(SPRN_PVR);
 624        has_cpu_l2lve = !((pvr & 0xf00) == 0x100);
 625
 626        set_speed_proc = cpu_750fx_cpu_speed;
 627        get_speed_proc = cpu_750fx_get_cpu_speed;
 628        cur_freq = cpu_750fx_get_cpu_speed();
 629
 630        return 0;
 631}
 632
 633/* Currently, we support the following machines:
 634 *
 635 *  - Titanium PowerBook 1Ghz (PMU based, 667Mhz & 1Ghz)
 636 *  - Titanium PowerBook 800 (PMU based, 667Mhz & 800Mhz)
 637 *  - Titanium PowerBook 400 (PMU based, 300Mhz & 400Mhz)
 638 *  - Titanium PowerBook 500 (PMU based, 300Mhz & 500Mhz)
 639 *  - iBook2 500/600 (PMU based, 400Mhz & 500/600Mhz)
 640 *  - iBook2 700 (CPU based, 400Mhz & 700Mhz, support low voltage)
 641 *  - Recent MacRISC3 laptops
 642 *  - All new machines with 7447A CPUs
 643 */
 644static int __init pmac_cpufreq_setup(void)
 645{
 646        struct device_node      *cpunode;
 647        const u32               *value;
 648
 649        if (strstr(cmd_line, "nocpufreq"))
 650                return 0;
 651
 652        /* Get first CPU node */
 653        cpunode = of_cpu_device_node_get(0);
 654        if (!cpunode)
 655                goto out;
 656
 657        /* Get current cpu clock freq */
 658        value = of_get_property(cpunode, "clock-frequency", NULL);
 659        if (!value)
 660                goto out;
 661        cur_freq = (*value) / 1000;
 662        transition_latency = CPUFREQ_ETERNAL;
 663
 664        /*  Check for 7447A based MacRISC3 */
 665        if (of_machine_is_compatible("MacRISC3") &&
 666            of_get_property(cpunode, "dynamic-power-step", NULL) &&
 667            PVR_VER(mfspr(SPRN_PVR)) == 0x8003) {
 668                pmac_cpufreq_init_7447A(cpunode);
 669                transition_latency = 8000000;
 670        /* Check for other MacRISC3 machines */
 671        } else if (of_machine_is_compatible("PowerBook3,4") ||
 672                   of_machine_is_compatible("PowerBook3,5") ||
 673                   of_machine_is_compatible("MacRISC3")) {
 674                pmac_cpufreq_init_MacRISC3(cpunode);
 675        /* Else check for iBook2 500/600 */
 676        } else if (of_machine_is_compatible("PowerBook4,1")) {
 677                hi_freq = cur_freq;
 678                low_freq = 400000;
 679                set_speed_proc = pmu_set_cpu_speed;
 680                is_pmu_based = 1;
 681        }
 682        /* Else check for TiPb 550 */
 683        else if (of_machine_is_compatible("PowerBook3,3") && cur_freq == 550000) {
 684                hi_freq = cur_freq;
 685                low_freq = 500000;
 686                set_speed_proc = pmu_set_cpu_speed;
 687                is_pmu_based = 1;
 688        }
 689        /* Else check for TiPb 400 & 500 */
 690        else if (of_machine_is_compatible("PowerBook3,2")) {
 691                /* We only know about the 400 MHz and the 500Mhz model
 692                 * they both have 300 MHz as low frequency
 693                 */
 694                if (cur_freq < 350000 || cur_freq > 550000)
 695                        goto out;
 696                hi_freq = cur_freq;
 697                low_freq = 300000;
 698                set_speed_proc = pmu_set_cpu_speed;
 699                is_pmu_based = 1;
 700        }
 701        /* Else check for 750FX */
 702        else if (PVR_VER(mfspr(SPRN_PVR)) == 0x7000)
 703                pmac_cpufreq_init_750FX(cpunode);
 704out:
 705        of_node_put(cpunode);
 706        if (set_speed_proc == NULL)
 707                return -ENODEV;
 708
 709        pmac_cpu_freqs[CPUFREQ_LOW].frequency = low_freq;
 710        pmac_cpu_freqs[CPUFREQ_HIGH].frequency = hi_freq;
 711        ppc_proc_freq = cur_freq * 1000ul;
 712
 713        printk(KERN_INFO "Registering PowerMac CPU frequency driver\n");
 714        printk(KERN_INFO "Low: %d Mhz, High: %d Mhz, Boot: %d Mhz\n",
 715               low_freq/1000, hi_freq/1000, cur_freq/1000);
 716
 717        return cpufreq_register_driver(&pmac_cpufreq_driver);
 718}
 719
 720module_init(pmac_cpufreq_setup);
 721
 722
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.