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