1
2
3
4
5
6
7
8
9
10
11
12
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 <asm/prom.h>
29#include <asm/machdep.h>
30#include <asm/irq.h>
31#include <asm/pmac_feature.h>
32#include <asm/mmu_context.h>
33#include <asm/sections.h>
34#include <asm/cputable.h>
35#include <asm/time.h>
36#include <asm/mpic.h>
37#include <asm/keylargo.h>
38#include <asm/switch_to.h>
39
40
41
42
43
44#undef DEBUG_FREQ
45
46extern void low_choose_7447a_dfs(int dfs);
47extern void low_choose_750fx_pll(int pll);
48extern void low_sleep_handler(void);
49
50
51
52
53
54static unsigned int low_freq;
55static unsigned int hi_freq;
56static unsigned int cur_freq;
57static unsigned int sleep_freq;
58static unsigned long transition_latency;
59
60
61
62
63static int (*set_speed_proc)(int low_speed);
64static unsigned int (*get_speed_proc)(void);
65
66
67
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
77
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
105
106
107
108 unsigned long save_lpj = loops_per_jiffy;
109 calibrate_delay();
110 loops_per_jiffy = save_lpj;
111}
112#endif
113
114
115
116static int cpu_750fx_cpu_speed(int low_speed)
117{
118 u32 hid2;
119
120 if (low_speed == 0) {
121
122 pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x05);
123
124 local_delay(10);
125
126
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
138 if (has_cpu_l2lve) {
139 hid2 = mfspr(SPRN_HID2);
140 hid2 |= 0x2000;
141 mtspr(SPRN_HID2, hid2);
142 }
143
144
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
161static int dfs_set_cpu_speed(int low_speed)
162{
163 if (low_speed == 0) {
164
165 pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x05);
166
167 local_delay(1);
168 }
169
170
171#ifdef CONFIG_6xx
172 low_choose_7447a_dfs(low_speed);
173#endif
174 udelay(100);
175
176 if (low_speed == 1) {
177
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
195
196static int gpios_set_cpu_speed(int low_speed)
197{
198 int gpio, timeout = 0;
199
200
201 if (low_speed == 0) {
202 pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x05);
203
204 local_delay(10);
205 }
206
207
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
223 if (low_speed == 1) {
224 pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x04);
225
226 local_delay(10);
227 }
228
229#ifdef DEBUG_FREQ
230 debug_calc_bogomips();
231#endif
232
233 return 0;
234}
235
236
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
254 pic_prio = mpic_cpu_get_priority();
255 mpic_cpu_set_priority(0xf);
256
257
258 asm volatile("mtdec %0" : : "r" (0x7fffffff));
259
260
261 mb();
262 asm volatile("mtdec %0" : : "r" (0x7fffffff));
263
264
265 local_irq_save(flags);
266
267
268 enable_kernel_fp();
269
270#ifdef CONFIG_ALTIVEC
271 if (cpu_has_feature(CPU_FTR_ALTIVEC))
272 enable_kernel_altivec();
273#endif
274
275
276 save_l3cr = _get_L3CR();
277 save_l2cr = _get_L2CR();
278
279
280
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
287 pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,1,1);
288
289
290
291
292 low_sleep_handler();
293
294
295 pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,1,0);
296
297
298 if (save_l2cr != 0xffffffff && (save_l2cr & L2CR_L2E) != 0)
299 _set_L2CR(save_l2cr);
300
301 if (save_l3cr != 0xffffffff && (save_l3cr & L3CR_L3E) != 0)
302 _set_L3CR(save_l3cr);
303
304
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
312 pmu_unlock();
313
314
315
316
317
318
319 set_dec(1);
320
321
322 mpic_cpu_set_priority(pic_prio);
323
324
325 local_irq_restore(flags);
326
327#ifdef DEBUG_FREQ
328 debug_calc_bogomips();
329#endif
330
331 pmu_resume();
332
333 preempt_enable();
334
335 return 0;
336}
337
338static int do_set_cpu_speed(struct cpufreq_policy *policy, int speed_mode,
339 int notify)
340{
341 struct cpufreq_freqs freqs;
342 unsigned long l3cr;
343 static unsigned long prev_l3cr;
344
345 freqs.old = cur_freq;
346 freqs.new = (speed_mode == CPUFREQ_HIGH) ? hi_freq : low_freq;
347
348 if (freqs.old == freqs.new)
349 return 0;
350
351 if (notify)
352 cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
353 if (speed_mode == CPUFREQ_LOW &&
354 cpu_has_feature(CPU_FTR_L3CR)) {
355 l3cr = _get_L3CR();
356 if (l3cr & L3CR_L3E) {
357 prev_l3cr = l3cr;
358 _set_L3CR(0);
359 }
360 }
361 set_speed_proc(speed_mode == CPUFREQ_LOW);
362 if (speed_mode == CPUFREQ_HIGH &&
363 cpu_has_feature(CPU_FTR_L3CR)) {
364 l3cr = _get_L3CR();
365 if ((prev_l3cr & L3CR_L3E) && l3cr != prev_l3cr)
366 _set_L3CR(prev_l3cr);
367 }
368 if (notify)
369 cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
370 cur_freq = (speed_mode == CPUFREQ_HIGH) ? hi_freq : low_freq;
371
372 return 0;
373}
374
375static unsigned int pmac_cpufreq_get_speed(unsigned int cpu)
376{
377 return cur_freq;
378}
379
380static int pmac_cpufreq_verify(struct cpufreq_policy *policy)
381{
382 return cpufreq_frequency_table_verify(policy, pmac_cpu_freqs);
383}
384
385static int pmac_cpufreq_target( struct cpufreq_policy *policy,
386 unsigned int target_freq,
387 unsigned int relation)
388{
389 unsigned int newstate = 0;
390 int rc;
391
392 if (cpufreq_frequency_table_target(policy, pmac_cpu_freqs,
393 target_freq, relation, &newstate))
394 return -EINVAL;
395
396 rc = do_set_cpu_speed(policy, newstate, 1);
397
398 ppc_proc_freq = cur_freq * 1000ul;
399 return rc;
400}
401
402static int pmac_cpufreq_cpu_init(struct cpufreq_policy *policy)
403{
404 if (policy->cpu != 0)
405 return -ENODEV;
406
407 policy->cpuinfo.transition_latency = transition_latency;
408 policy->cur = cur_freq;
409
410 cpufreq_frequency_table_get_attr(pmac_cpu_freqs, policy->cpu);
411 return cpufreq_frequency_table_cpuinfo(policy, pmac_cpu_freqs);
412}
413
414static u32 read_gpio(struct device_node *np)
415{
416 const u32 *reg = of_get_property(np, "reg", NULL);
417 u32 offset;
418
419 if (reg == NULL)
420 return 0;
421
422
423
424
425
426
427 offset = *reg;
428 if (offset < KEYLARGO_GPIO_LEVELS0)
429 offset += KEYLARGO_GPIO_LEVELS0;
430 return offset;
431}
432
433static int pmac_cpufreq_suspend(struct cpufreq_policy *policy)
434{
435
436
437
438
439
440
441
442 no_schedule = 1;
443 sleep_freq = cur_freq;
444 if (cur_freq == low_freq && !is_pmu_based)
445 do_set_cpu_speed(policy, CPUFREQ_HIGH, 0);
446 return 0;
447}
448
449static int pmac_cpufreq_resume(struct cpufreq_policy *policy)
450{
451
452 if (get_speed_proc)
453 cur_freq = get_speed_proc();
454 else
455 cur_freq = 0;
456
457
458
459
460
461 do_set_cpu_speed(policy, sleep_freq == low_freq ?
462 CPUFREQ_LOW : CPUFREQ_HIGH, 0);
463
464 ppc_proc_freq = cur_freq * 1000ul;
465
466 no_schedule = 0;
467 return 0;
468}
469
470static struct cpufreq_driver pmac_cpufreq_driver = {
471 .verify = pmac_cpufreq_verify,
472 .target = pmac_cpufreq_target,
473 .get = pmac_cpufreq_get_speed,
474 .init = pmac_cpufreq_cpu_init,
475 .suspend = pmac_cpufreq_suspend,
476 .resume = pmac_cpufreq_resume,
477 .flags = CPUFREQ_PM_NO_WARN,
478 .attr = pmac_cpu_freqs_attr,
479 .name = "powermac",
480 .owner = THIS_MODULE,
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
496
497
498
499
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
510
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
530 low_freq = min(freqs[0], freqs[1]);
531 hi_freq = max(freqs[0], freqs[1]);
532
533
534
535
536
537
538 if (low_freq < 98000000)
539 low_freq = 101000000;
540
541
542 low_freq = (low_freq * (*ratio)) / 2000;
543 hi_freq = (hi_freq * (*ratio)) / 2000;
544
545
546
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
556
557
558 value = of_get_property(cpunode, "min-clock-frequency", NULL);
559 if (!value)
560 return 1;
561 low_freq = (*value) / 1000;
562
563
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
593 hi_freq = cur_freq;
594 low_freq = cur_freq/2;
595
596
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
634
635
636
637
638
639
640
641
642
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
653 cpunode = of_find_node_by_type(NULL, "cpu");
654 if (!cpunode)
655 goto out;
656
657
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
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
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
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
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
690 else if (of_machine_is_compatible("PowerBook3,2")) {
691
692
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
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