Path: blob/master/arch/powerpc/platforms/powermac/cpufreq_32.c
10818 views
/*1* Copyright (C) 2002 - 2005 Benjamin Herrenschmidt <[email protected]>2* Copyright (C) 2004 John Steele Scott <[email protected]>3*4* This program is free software; you can redistribute it and/or modify5* it under the terms of the GNU General Public License version 2 as6* published by the Free Software Foundation.7*8* TODO: Need a big cleanup here. Basically, we need to have different9* cpufreq_driver structures for the different type of HW instead of the10* current mess. We also need to better deal with the detection of the11* type of machine.12*13*/1415#include <linux/module.h>16#include <linux/types.h>17#include <linux/errno.h>18#include <linux/kernel.h>19#include <linux/delay.h>20#include <linux/sched.h>21#include <linux/adb.h>22#include <linux/pmu.h>23#include <linux/cpufreq.h>24#include <linux/init.h>25#include <linux/sysdev.h>26#include <linux/hardirq.h>27#include <asm/prom.h>28#include <asm/machdep.h>29#include <asm/irq.h>30#include <asm/pmac_feature.h>31#include <asm/mmu_context.h>32#include <asm/sections.h>33#include <asm/cputable.h>34#include <asm/time.h>35#include <asm/system.h>36#include <asm/mpic.h>37#include <asm/keylargo.h>3839/* WARNING !!! This will cause calibrate_delay() to be called,40* but this is an __init function ! So you MUST go edit41* init/main.c to make it non-init before enabling DEBUG_FREQ42*/43#undef DEBUG_FREQ4445extern void low_choose_7447a_dfs(int dfs);46extern void low_choose_750fx_pll(int pll);47extern void low_sleep_handler(void);4849/*50* Currently, PowerMac cpufreq supports only high & low frequencies51* that are set by the firmware52*/53static unsigned int low_freq;54static unsigned int hi_freq;55static unsigned int cur_freq;56static unsigned int sleep_freq;5758/*59* Different models uses different mechanisms to switch the frequency60*/61static int (*set_speed_proc)(int low_speed);62static unsigned int (*get_speed_proc)(void);6364/*65* Some definitions used by the various speedprocs66*/67static u32 voltage_gpio;68static u32 frequency_gpio;69static u32 slew_done_gpio;70static int no_schedule;71static int has_cpu_l2lve;72static int is_pmu_based;7374/* There are only two frequency states for each processor. Values75* are in kHz for the time being.76*/77#define CPUFREQ_HIGH 078#define CPUFREQ_LOW 17980static struct cpufreq_frequency_table pmac_cpu_freqs[] = {81{CPUFREQ_HIGH, 0},82{CPUFREQ_LOW, 0},83{0, CPUFREQ_TABLE_END},84};8586static struct freq_attr* pmac_cpu_freqs_attr[] = {87&cpufreq_freq_attr_scaling_available_freqs,88NULL,89};9091static inline void local_delay(unsigned long ms)92{93if (no_schedule)94mdelay(ms);95else96msleep(ms);97}9899#ifdef DEBUG_FREQ100static inline void debug_calc_bogomips(void)101{102/* This will cause a recalc of bogomips and display the103* result. We backup/restore the value to avoid affecting the104* core cpufreq framework's own calculation.105*/106unsigned long save_lpj = loops_per_jiffy;107calibrate_delay();108loops_per_jiffy = save_lpj;109}110#endif /* DEBUG_FREQ */111112/* Switch CPU speed under 750FX CPU control113*/114static int cpu_750fx_cpu_speed(int low_speed)115{116u32 hid2;117118if (low_speed == 0) {119/* ramping up, set voltage first */120pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x05);121/* Make sure we sleep for at least 1ms */122local_delay(10);123124/* tweak L2 for high voltage */125if (has_cpu_l2lve) {126hid2 = mfspr(SPRN_HID2);127hid2 &= ~0x2000;128mtspr(SPRN_HID2, hid2);129}130}131#ifdef CONFIG_6xx132low_choose_750fx_pll(low_speed);133#endif134if (low_speed == 1) {135/* tweak L2 for low voltage */136if (has_cpu_l2lve) {137hid2 = mfspr(SPRN_HID2);138hid2 |= 0x2000;139mtspr(SPRN_HID2, hid2);140}141142/* ramping down, set voltage last */143pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x04);144local_delay(10);145}146147return 0;148}149150static unsigned int cpu_750fx_get_cpu_speed(void)151{152if (mfspr(SPRN_HID1) & HID1_PS)153return low_freq;154else155return hi_freq;156}157158/* Switch CPU speed using DFS */159static int dfs_set_cpu_speed(int low_speed)160{161if (low_speed == 0) {162/* ramping up, set voltage first */163pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x05);164/* Make sure we sleep for at least 1ms */165local_delay(1);166}167168/* set frequency */169#ifdef CONFIG_6xx170low_choose_7447a_dfs(low_speed);171#endif172udelay(100);173174if (low_speed == 1) {175/* ramping down, set voltage last */176pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x04);177local_delay(1);178}179180return 0;181}182183static unsigned int dfs_get_cpu_speed(void)184{185if (mfspr(SPRN_HID1) & HID1_DFS)186return low_freq;187else188return hi_freq;189}190191192/* Switch CPU speed using slewing GPIOs193*/194static int gpios_set_cpu_speed(int low_speed)195{196int gpio, timeout = 0;197198/* If ramping up, set voltage first */199if (low_speed == 0) {200pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x05);201/* Delay is way too big but it's ok, we schedule */202local_delay(10);203}204205/* Set frequency */206gpio = pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, frequency_gpio, 0);207if (low_speed == ((gpio & 0x01) == 0))208goto skip;209210pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, frequency_gpio,211low_speed ? 0x04 : 0x05);212udelay(200);213do {214if (++timeout > 100)215break;216local_delay(1);217gpio = pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, slew_done_gpio, 0);218} while((gpio & 0x02) == 0);219skip:220/* If ramping down, set voltage last */221if (low_speed == 1) {222pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x04);223/* Delay is way too big but it's ok, we schedule */224local_delay(10);225}226227#ifdef DEBUG_FREQ228debug_calc_bogomips();229#endif230231return 0;232}233234/* Switch CPU speed under PMU control235*/236static int pmu_set_cpu_speed(int low_speed)237{238struct adb_request req;239unsigned long save_l2cr;240unsigned long save_l3cr;241unsigned int pic_prio;242unsigned long flags;243244preempt_disable();245246#ifdef DEBUG_FREQ247printk(KERN_DEBUG "HID1, before: %x\n", mfspr(SPRN_HID1));248#endif249pmu_suspend();250251/* Disable all interrupt sources on openpic */252pic_prio = mpic_cpu_get_priority();253mpic_cpu_set_priority(0xf);254255/* Make sure the decrementer won't interrupt us */256asm volatile("mtdec %0" : : "r" (0x7fffffff));257/* Make sure any pending DEC interrupt occurring while we did258* the above didn't re-enable the DEC */259mb();260asm volatile("mtdec %0" : : "r" (0x7fffffff));261262/* We can now disable MSR_EE */263local_irq_save(flags);264265/* Giveup the FPU & vec */266enable_kernel_fp();267268#ifdef CONFIG_ALTIVEC269if (cpu_has_feature(CPU_FTR_ALTIVEC))270enable_kernel_altivec();271#endif /* CONFIG_ALTIVEC */272273/* Save & disable L2 and L3 caches */274save_l3cr = _get_L3CR(); /* (returns -1 if not available) */275save_l2cr = _get_L2CR(); /* (returns -1 if not available) */276277/* Send the new speed command. My assumption is that this command278* will cause PLL_CFG[0..3] to be changed next time CPU goes to sleep279*/280pmu_request(&req, NULL, 6, PMU_CPU_SPEED, 'W', 'O', 'O', 'F', low_speed);281while (!req.complete)282pmu_poll();283284/* Prepare the northbridge for the speed transition */285pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,1,1);286287/* Call low level code to backup CPU state and recover from288* hardware reset289*/290low_sleep_handler();291292/* Restore the northbridge */293pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,1,0);294295/* Restore L2 cache */296if (save_l2cr != 0xffffffff && (save_l2cr & L2CR_L2E) != 0)297_set_L2CR(save_l2cr);298/* Restore L3 cache */299if (save_l3cr != 0xffffffff && (save_l3cr & L3CR_L3E) != 0)300_set_L3CR(save_l3cr);301302/* Restore userland MMU context */303switch_mmu_context(NULL, current->active_mm);304305#ifdef DEBUG_FREQ306printk(KERN_DEBUG "HID1, after: %x\n", mfspr(SPRN_HID1));307#endif308309/* Restore low level PMU operations */310pmu_unlock();311312/*313* Restore decrementer; we'll take a decrementer interrupt314* as soon as interrupts are re-enabled and the generic315* clockevents code will reprogram it with the right value.316*/317set_dec(1);318319/* Restore interrupts */320mpic_cpu_set_priority(pic_prio);321322/* Let interrupts flow again ... */323local_irq_restore(flags);324325#ifdef DEBUG_FREQ326debug_calc_bogomips();327#endif328329pmu_resume();330331preempt_enable();332333return 0;334}335336static int do_set_cpu_speed(int speed_mode, int notify)337{338struct cpufreq_freqs freqs;339unsigned long l3cr;340static unsigned long prev_l3cr;341342freqs.old = cur_freq;343freqs.new = (speed_mode == CPUFREQ_HIGH) ? hi_freq : low_freq;344freqs.cpu = smp_processor_id();345346if (freqs.old == freqs.new)347return 0;348349if (notify)350cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);351if (speed_mode == CPUFREQ_LOW &&352cpu_has_feature(CPU_FTR_L3CR)) {353l3cr = _get_L3CR();354if (l3cr & L3CR_L3E) {355prev_l3cr = l3cr;356_set_L3CR(0);357}358}359set_speed_proc(speed_mode == CPUFREQ_LOW);360if (speed_mode == CPUFREQ_HIGH &&361cpu_has_feature(CPU_FTR_L3CR)) {362l3cr = _get_L3CR();363if ((prev_l3cr & L3CR_L3E) && l3cr != prev_l3cr)364_set_L3CR(prev_l3cr);365}366if (notify)367cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);368cur_freq = (speed_mode == CPUFREQ_HIGH) ? hi_freq : low_freq;369370return 0;371}372373static unsigned int pmac_cpufreq_get_speed(unsigned int cpu)374{375return cur_freq;376}377378static int pmac_cpufreq_verify(struct cpufreq_policy *policy)379{380return cpufreq_frequency_table_verify(policy, pmac_cpu_freqs);381}382383static int pmac_cpufreq_target( struct cpufreq_policy *policy,384unsigned int target_freq,385unsigned int relation)386{387unsigned int newstate = 0;388int rc;389390if (cpufreq_frequency_table_target(policy, pmac_cpu_freqs,391target_freq, relation, &newstate))392return -EINVAL;393394rc = do_set_cpu_speed(newstate, 1);395396ppc_proc_freq = cur_freq * 1000ul;397return rc;398}399400static int pmac_cpufreq_cpu_init(struct cpufreq_policy *policy)401{402if (policy->cpu != 0)403return -ENODEV;404405policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;406policy->cur = cur_freq;407408cpufreq_frequency_table_get_attr(pmac_cpu_freqs, policy->cpu);409return cpufreq_frequency_table_cpuinfo(policy, pmac_cpu_freqs);410}411412static u32 read_gpio(struct device_node *np)413{414const u32 *reg = of_get_property(np, "reg", NULL);415u32 offset;416417if (reg == NULL)418return 0;419/* That works for all keylargos but shall be fixed properly420* some day... The problem is that it seems we can't rely421* on the "reg" property of the GPIO nodes, they are either422* relative to the base of KeyLargo or to the base of the423* GPIO space, and the device-tree doesn't help.424*/425offset = *reg;426if (offset < KEYLARGO_GPIO_LEVELS0)427offset += KEYLARGO_GPIO_LEVELS0;428return offset;429}430431static int pmac_cpufreq_suspend(struct cpufreq_policy *policy)432{433/* Ok, this could be made a bit smarter, but let's be robust for now. We434* always force a speed change to high speed before sleep, to make sure435* we have appropriate voltage and/or bus speed for the wakeup process,436* and to make sure our loops_per_jiffies are "good enough", that is will437* not cause too short delays if we sleep in low speed and wake in high438* speed..439*/440no_schedule = 1;441sleep_freq = cur_freq;442if (cur_freq == low_freq && !is_pmu_based)443do_set_cpu_speed(CPUFREQ_HIGH, 0);444return 0;445}446447static int pmac_cpufreq_resume(struct cpufreq_policy *policy)448{449/* If we resume, first check if we have a get() function */450if (get_speed_proc)451cur_freq = get_speed_proc();452else453cur_freq = 0;454455/* We don't, hrm... we don't really know our speed here, best456* is that we force a switch to whatever it was, which is457* probably high speed due to our suspend() routine458*/459do_set_cpu_speed(sleep_freq == low_freq ?460CPUFREQ_LOW : CPUFREQ_HIGH, 0);461462ppc_proc_freq = cur_freq * 1000ul;463464no_schedule = 0;465return 0;466}467468static struct cpufreq_driver pmac_cpufreq_driver = {469.verify = pmac_cpufreq_verify,470.target = pmac_cpufreq_target,471.get = pmac_cpufreq_get_speed,472.init = pmac_cpufreq_cpu_init,473.suspend = pmac_cpufreq_suspend,474.resume = pmac_cpufreq_resume,475.flags = CPUFREQ_PM_NO_WARN,476.attr = pmac_cpu_freqs_attr,477.name = "powermac",478.owner = THIS_MODULE,479};480481482static int pmac_cpufreq_init_MacRISC3(struct device_node *cpunode)483{484struct device_node *volt_gpio_np = of_find_node_by_name(NULL,485"voltage-gpio");486struct device_node *freq_gpio_np = of_find_node_by_name(NULL,487"frequency-gpio");488struct device_node *slew_done_gpio_np = of_find_node_by_name(NULL,489"slewing-done");490const u32 *value;491492/*493* Check to see if it's GPIO driven or PMU only494*495* The way we extract the GPIO address is slightly hackish, but it496* works well enough for now. We need to abstract the whole GPIO497* stuff sooner or later anyway498*/499500if (volt_gpio_np)501voltage_gpio = read_gpio(volt_gpio_np);502if (freq_gpio_np)503frequency_gpio = read_gpio(freq_gpio_np);504if (slew_done_gpio_np)505slew_done_gpio = read_gpio(slew_done_gpio_np);506507/* If we use the frequency GPIOs, calculate the min/max speeds based508* on the bus frequencies509*/510if (frequency_gpio && slew_done_gpio) {511int lenp, rc;512const u32 *freqs, *ratio;513514freqs = of_get_property(cpunode, "bus-frequencies", &lenp);515lenp /= sizeof(u32);516if (freqs == NULL || lenp != 2) {517printk(KERN_ERR "cpufreq: bus-frequencies incorrect or missing\n");518return 1;519}520ratio = of_get_property(cpunode, "processor-to-bus-ratio*2",521NULL);522if (ratio == NULL) {523printk(KERN_ERR "cpufreq: processor-to-bus-ratio*2 missing\n");524return 1;525}526527/* Get the min/max bus frequencies */528low_freq = min(freqs[0], freqs[1]);529hi_freq = max(freqs[0], freqs[1]);530531/* Grrrr.. It _seems_ that the device-tree is lying on the low bus532* frequency, it claims it to be around 84Mhz on some models while533* it appears to be approx. 101Mhz on all. Let's hack around here...534* fortunately, we don't need to be too precise535*/536if (low_freq < 98000000)537low_freq = 101000000;538539/* Convert those to CPU core clocks */540low_freq = (low_freq * (*ratio)) / 2000;541hi_freq = (hi_freq * (*ratio)) / 2000;542543/* Now we get the frequencies, we read the GPIO to see what is out current544* speed545*/546rc = pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, frequency_gpio, 0);547cur_freq = (rc & 0x01) ? hi_freq : low_freq;548549set_speed_proc = gpios_set_cpu_speed;550return 1;551}552553/* If we use the PMU, look for the min & max frequencies in the554* device-tree555*/556value = of_get_property(cpunode, "min-clock-frequency", NULL);557if (!value)558return 1;559low_freq = (*value) / 1000;560/* The PowerBook G4 12" (PowerBook6,1) has an error in the device-tree561* here */562if (low_freq < 100000)563low_freq *= 10;564565value = of_get_property(cpunode, "max-clock-frequency", NULL);566if (!value)567return 1;568hi_freq = (*value) / 1000;569set_speed_proc = pmu_set_cpu_speed;570is_pmu_based = 1;571572return 0;573}574575static int pmac_cpufreq_init_7447A(struct device_node *cpunode)576{577struct device_node *volt_gpio_np;578579if (of_get_property(cpunode, "dynamic-power-step", NULL) == NULL)580return 1;581582volt_gpio_np = of_find_node_by_name(NULL, "cpu-vcore-select");583if (volt_gpio_np)584voltage_gpio = read_gpio(volt_gpio_np);585if (!voltage_gpio){586printk(KERN_ERR "cpufreq: missing cpu-vcore-select gpio\n");587return 1;588}589590/* OF only reports the high frequency */591hi_freq = cur_freq;592low_freq = cur_freq/2;593594/* Read actual frequency from CPU */595cur_freq = dfs_get_cpu_speed();596set_speed_proc = dfs_set_cpu_speed;597get_speed_proc = dfs_get_cpu_speed;598599return 0;600}601602static int pmac_cpufreq_init_750FX(struct device_node *cpunode)603{604struct device_node *volt_gpio_np;605u32 pvr;606const u32 *value;607608if (of_get_property(cpunode, "dynamic-power-step", NULL) == NULL)609return 1;610611hi_freq = cur_freq;612value = of_get_property(cpunode, "reduced-clock-frequency", NULL);613if (!value)614return 1;615low_freq = (*value) / 1000;616617volt_gpio_np = of_find_node_by_name(NULL, "cpu-vcore-select");618if (volt_gpio_np)619voltage_gpio = read_gpio(volt_gpio_np);620621pvr = mfspr(SPRN_PVR);622has_cpu_l2lve = !((pvr & 0xf00) == 0x100);623624set_speed_proc = cpu_750fx_cpu_speed;625get_speed_proc = cpu_750fx_get_cpu_speed;626cur_freq = cpu_750fx_get_cpu_speed();627628return 0;629}630631/* Currently, we support the following machines:632*633* - Titanium PowerBook 1Ghz (PMU based, 667Mhz & 1Ghz)634* - Titanium PowerBook 800 (PMU based, 667Mhz & 800Mhz)635* - Titanium PowerBook 400 (PMU based, 300Mhz & 400Mhz)636* - Titanium PowerBook 500 (PMU based, 300Mhz & 500Mhz)637* - iBook2 500/600 (PMU based, 400Mhz & 500/600Mhz)638* - iBook2 700 (CPU based, 400Mhz & 700Mhz, support low voltage)639* - Recent MacRISC3 laptops640* - All new machines with 7447A CPUs641*/642static int __init pmac_cpufreq_setup(void)643{644struct device_node *cpunode;645const u32 *value;646647if (strstr(cmd_line, "nocpufreq"))648return 0;649650/* Assume only one CPU */651cpunode = of_find_node_by_type(NULL, "cpu");652if (!cpunode)653goto out;654655/* Get current cpu clock freq */656value = of_get_property(cpunode, "clock-frequency", NULL);657if (!value)658goto out;659cur_freq = (*value) / 1000;660661/* Check for 7447A based MacRISC3 */662if (of_machine_is_compatible("MacRISC3") &&663of_get_property(cpunode, "dynamic-power-step", NULL) &&664PVR_VER(mfspr(SPRN_PVR)) == 0x8003) {665pmac_cpufreq_init_7447A(cpunode);666/* Check for other MacRISC3 machines */667} else if (of_machine_is_compatible("PowerBook3,4") ||668of_machine_is_compatible("PowerBook3,5") ||669of_machine_is_compatible("MacRISC3")) {670pmac_cpufreq_init_MacRISC3(cpunode);671/* Else check for iBook2 500/600 */672} else if (of_machine_is_compatible("PowerBook4,1")) {673hi_freq = cur_freq;674low_freq = 400000;675set_speed_proc = pmu_set_cpu_speed;676is_pmu_based = 1;677}678/* Else check for TiPb 550 */679else if (of_machine_is_compatible("PowerBook3,3") && cur_freq == 550000) {680hi_freq = cur_freq;681low_freq = 500000;682set_speed_proc = pmu_set_cpu_speed;683is_pmu_based = 1;684}685/* Else check for TiPb 400 & 500 */686else if (of_machine_is_compatible("PowerBook3,2")) {687/* We only know about the 400 MHz and the 500Mhz model688* they both have 300 MHz as low frequency689*/690if (cur_freq < 350000 || cur_freq > 550000)691goto out;692hi_freq = cur_freq;693low_freq = 300000;694set_speed_proc = pmu_set_cpu_speed;695is_pmu_based = 1;696}697/* Else check for 750FX */698else if (PVR_VER(mfspr(SPRN_PVR)) == 0x7000)699pmac_cpufreq_init_750FX(cpunode);700out:701of_node_put(cpunode);702if (set_speed_proc == NULL)703return -ENODEV;704705pmac_cpu_freqs[CPUFREQ_LOW].frequency = low_freq;706pmac_cpu_freqs[CPUFREQ_HIGH].frequency = hi_freq;707ppc_proc_freq = cur_freq * 1000ul;708709printk(KERN_INFO "Registering PowerMac CPU frequency driver\n");710printk(KERN_INFO "Low: %d Mhz, High: %d Mhz, Boot: %d Mhz\n",711low_freq/1000, hi_freq/1000, cur_freq/1000);712713return cpufreq_register_driver(&pmac_cpufreq_driver);714}715716module_init(pmac_cpufreq_setup);717718719720