how to setup PLL1 on 750FX
Chris Studholme
cvs at cs.utoronto.ca
Sat Jun 28 13:05:57 EST 2003
On Fri, 27 Jun 2003, Benjamin Herrenschmidt wrote:
> Well... I may have a bug making my low-speed-during-idle code not work
> ... Or maybe the PLL1 beeing off means the CPU will just continue
> locking on PLL0...
Maybe the latter. When I first started playing with this, I had hacked
cpufreq to change to low speed when PLL1 wasn't set. It neither changed
the frequency (obviously), nor locked up the machine.
> Another place where you want the real PVR is the CPU save/restore state
> code in cpu_setup_6xx.S. That code is used for example to save the CPU
> state before sleep and restore it on wakeup.
I'll look into this a little more.
My patch is now working quite well for me. I've got cpufreq working and
I've verified that the cpu speed actually drops to about half when low
speed is selected. I've also modified the patch so the bulk of the code
is selectable by a config option (CONFIG_BLUECHIP_750FX). I've included
the full patch below. Let me know if you would like any changes to make
this patch more acceptable for the main linuxppc trees. Thanks for all
the help getting this working.
Chris.
diff -b -c -r linux-2.4-benh.orig/Documentation/Configure.help linux-2.4-benh/Documentation/Configure.help
*** linux-2.4-benh.orig/Documentation/Configure.help Mon Jun 16 04:32:31 2003
--- linux-2.4-benh/Documentation/Configure.help Thu Jun 26 22:15:43 2003
***************
*** 22440,22445 ****
--- 22440,22456 ----
If in doubt, say N.
+ BlueChip 750FX Support
+ CONFIG_BLUECHIP_750FX
+ If you have purchased a PowerLogix BlueChip G3 processor upgarde
+ for your machine, enabling this option will allow your IBM 750FX
+ processor to be correctly detected and allows you to use the
+ advanced features of your processor (namely, the variable clock
+ speed feature). If you don't have this type of upgrade, this
+ option has no effect.
+
+ If in doubt, say N.
+
# Choice: ppc4xxtype
Oak
CONFIG_OAK
diff -b -c -r linux-2.4-benh.orig/arch/ppc/config.in linux-2.4-benh/arch/ppc/config.in
*** linux-2.4-benh.orig/arch/ppc/config.in Fri May 16 09:27:13 2003
--- linux-2.4-benh/arch/ppc/config.in Thu Jun 26 22:04:18 2003
***************
*** 38,43 ****
--- 38,47 ----
bool 'MPC8260 CPM Support' CONFIG_8260
fi
+ if [ "$CONFIG_6xx" = "y" ]; then
+ bool 'BlueChip 750FX Support' CONFIG_BLUECHIP_750FX
+ fi
+
if [ "$CONFIG_POWER3" = "y" -o "$CONFIG_POWER4" = "y" ]; then
define_bool CONFIG_PPC64BRIDGE y
define_bool CONFIG_ALL_PPC y
diff -b -c -r linux-2.4-benh.orig/arch/ppc/configs/pmac_defconfig linux-2.4-benh/arch/ppc/configs/pmac_defconfig
*** linux-2.4-benh.orig/arch/ppc/configs/pmac_defconfig Mon Jun 16 04:40:40 2003
--- linux-2.4-benh/arch/ppc/configs/pmac_defconfig Thu Jun 26 22:05:46 2003
***************
*** 29,34 ****
--- 29,35 ----
# CONFIG_POWER4 is not set
# CONFIG_8xx is not set
# CONFIG_8260 is not set
+ # CONFIG_BLUECHIP_750FX is not set
CONFIG_PPC_STD_MMU=y
CONFIG_CPU_FREQ=y
# CONFIG_CPU_FREQ_24_API is not set
diff -b -c -r linux-2.4-benh.orig/arch/ppc/defconfig linux-2.4-benh/arch/ppc/defconfig
*** linux-2.4-benh.orig/arch/ppc/defconfig Mon Jun 16 04:40:40 2003
--- linux-2.4-benh/arch/ppc/defconfig Thu Jun 26 22:06:51 2003
***************
*** 29,34 ****
--- 29,35 ----
# CONFIG_POWER4 is not set
# CONFIG_8xx is not set
# CONFIG_8260 is not set
+ # CONFIG_BLUECHIP_750FX is not set
CONFIG_PPC_STD_MMU=y
CONFIG_ALL_PPC=y
# CONFIG_APUS is not set
diff -b -c -r linux-2.4-benh.orig/arch/ppc/kernel/cputable.c linux-2.4-benh/arch/ppc/kernel/cputable.c
*** linux-2.4-benh.orig/arch/ppc/kernel/cputable.c Mon Jun 16 04:40:40 2003
--- linux-2.4-benh/arch/ppc/kernel/cputable.c Thu Jun 26 17:38:35 2003
***************
*** 18,23 ****
--- 18,25 ----
struct cpu_spec* cur_cpu_spec[NR_CPUS];
+ unsigned int real_pvr;
+
extern void __setup_cpu_601(unsigned long offset, int cpu_nr, struct cpu_spec* spec);
extern void __setup_cpu_603(unsigned long offset, int cpu_nr, struct cpu_spec* spec);
extern void __setup_cpu_604(unsigned long offset, int cpu_nr, struct cpu_spec* spec);
diff -b -c -r linux-2.4-benh.orig/arch/ppc/kernel/misc.S linux-2.4-benh/arch/ppc/kernel/misc.S
*** linux-2.4-benh.orig/arch/ppc/kernel/misc.S Thu Mar 27 05:43:31 2003
--- linux-2.4-benh/arch/ppc/kernel/misc.S Fri Jun 27 11:52:30 2003
***************
*** 110,118 ****
* doesn't change r3
*/
_GLOBAL(identify_cpu)
addis r8,r3,cpu_specs at ha
addi r8,r8,cpu_specs at l
! mfpvr r7
1:
lwz r5,CPU_SPEC_PVR_MASK(r8)
and r5,r5,r7
--- 110,131 ----
* doesn't change r3
*/
_GLOBAL(identify_cpu)
+ mfpvr r7
+
+ #ifdef CONFIG_BLUECHIP_750FX
+ /* if pvr reports 750, check for 750fx */
+ srwi r6,r7,16
+ cmpli 0,r6,8
+ bne 2f
+ mflr r8
+ bl identify_cpu_750fx
+ mtlr r8
+ 2:
+ #endif /* CONFIG_BLUECHIP_750FX */
+
addis r8,r3,cpu_specs at ha
addi r8,r8,cpu_specs at l
!
1:
lwz r5,CPU_SPEC_PVR_MASK(r8)
and r5,r5,r7
***************
*** 127,133 ****
--- 140,186 ----
slwi r4,r4,2
sub r8,r8,r3
stwx r8,r4,r6
+ addis r6,r3,real_pvr at ha
+ stw r7,real_pvr at l(r6)
+ blr
+
+ #ifdef CONFIG_BLUECHIP_750FX
+ /* Check for 750fx cpu strapped on as a 750. Also, if 750fx and PLL1 is not
+ * in use, set PLL1 to 4x and delay as needed to lock pll.
+ * Called with pvr in r7 (assumed to be 0x0008nnnn).
+ * Returns new pvr in r7.
+ * r5,r6 are changed.
+ */
+ identify_cpu_750fx:
+ mfspr r5,SPRN_HID1
+ andis. r6,r5,0x0001
+ xori r6,r5,0x0002
+ beq 1f
+ xori r6,r5,0x0200
+ 1:
+ mtspr SPRN_HID1,r6
+ mfspr r6,SPRN_HID1
+ cmplw 0,r5,r6
+ beqlr
+
+ /* pvr is actually 0x7000nnnn, not 0x0008nnnn */
+ xoris r7,r7,0x7008
+ mtspr SPRN_HID1,r5
+
+ andis. r6,r5,0x0001
+ bnelr
+
+ li r6,0x00FE
+ andc r5,r5,r6
+ ori r5,r5,4+(DEFAULT_PLL1_CONFIG<<3)
+ mtspr SPRN_HID1,r5
+
+ /* delay for at least 0.5sec (on 1GHz or slower cpu) */
+ lis r6,0x1DCE
+ mtctr r6
+ 2: bdnz 2b
blr
+ #endif /* CONFIG_BLUECHIP_750FX */
/*
* do_cpu_ftr_fixups - goes through the list of CPU feature fixups
diff -b -c -r linux-2.4-benh.orig/arch/ppc/kernel/prom.c linux-2.4-benh/arch/ppc/kernel/prom.c
*** linux-2.4-benh.orig/arch/ppc/kernel/prom.c Thu Feb 27 10:14:49 2003
--- linux-2.4-benh/arch/ppc/kernel/prom.c Fri Jun 27 11:52:00 2003
***************
*** 78,83 ****
--- 78,90 ----
extern boot_infos_t *boot_infos;
unsigned long dev_tree_size;
+ #ifdef CONFIG_BLUECHIP_750FX
+ /* extra properties for 750fx */
+ unsigned int reduced_clock_frequency;
+ struct property reduced_clock_frequency_prop;
+ struct property dynamic_power_step_prop;
+ #endif /* CONFIG_BLUECHIP_750FX */
+
void __openfirmware
phys_call_rtas(int service, int nargs, int nret, ...)
{
***************
*** 101,106 ****
--- 108,214 ----
rtas(&u, rtas_data);
}
+ #ifdef CONFIG_BLUECHIP_750FX
+ /* Fix device tree (cpu-frequency and L2 cache size) for 750FX.
+ */
+ static void __init
+ prom_fixup_for_750fx(void)
+ {
+ struct device_node *cpunode, *cachenode;
+ u32 *value;
+ unsigned int busfreq,hid1,multiplier,cpufreq=0;
+ unsigned int cachesize, cacheline;
+
+ /* cache size */
+ cachesize = 0x00080000;
+ cacheline = 64;
+
+ /* assume only one CPU */
+ cpunode = find_type_devices("cpu");
+ if (!cpunode)
+ return;
+
+ value = (u32*)get_property(cpunode, "cpu-version", NULL);
+ if (value)
+ *value = real_pvr;
+
+ /* calculate cpu clock frequency */
+ value = (u32*)get_property(cpunode, "bus-frequency", NULL);
+ if (value) {
+ busfreq = *value;
+ if (66000000<busfreq && busfreq<67000000)
+ busfreq=66666667;
+ else if (99000000<busfreq && busfreq<101000000)
+ busfreq=100000000;
+ else if (132000000<busfreq && busfreq<134000000)
+ busfreq=133333334;
+
+ /* get cpu frequency multiplier */
+ hid1 = mfspr(HID1);
+ if (hid1&0x00010000)
+ multiplier = (hid1>>3)&0x1F;
+ else if (hid1&0x00020000)
+ multiplier = (hid1>>11)&0x1F;
+ else
+ multiplier = (hid1>>27)&0x1F;
+ if (multiplier==0x1F)
+ multiplier=0;
+ else if (multiplier>20)
+ multiplier=(multiplier-10)*2;
+ else if (multiplier==3)
+ multiplier=2;
+ if (multiplier>=2)
+ cpufreq = busfreq * multiplier / 2;
+
+ /* PLL1 is configured in identify_cpu_750fx (in misc.S) */
+ reduced_clock_frequency = busfreq * DEFAULT_PLL1_CONFIG / 2;
+ memset(&reduced_clock_frequency_prop,-1,
+ sizeof(struct property));
+ reduced_clock_frequency_prop.name = "reduced-clock-frequency";
+ reduced_clock_frequency_prop.length = 4;
+ reduced_clock_frequency_prop.value =
+ (unsigned char*)&reduced_clock_frequency;
+ prom_add_property(cpunode,&reduced_clock_frequency_prop);
+
+ memset(&dynamic_power_step_prop,-1,sizeof(struct property));
+ dynamic_power_step_prop.name = "dynamic-power-step";
+ dynamic_power_step_prop.length = 0;
+ dynamic_power_step_prop.value =
+ (unsigned char*)&dynamic_power_step_prop;
+ prom_add_property(cpunode,&dynamic_power_step_prop);
+ }
+
+ value = (u32*)get_property(cpunode, "clock-frequency", NULL);
+ if (value && cpufreq)
+ *value = cpufreq;
+
+ /* correct L2 cache size and clock frequency */
+ cachenode = find_type_devices("cache");
+ if (!cachenode)
+ return;
+
+ value = (u32*)get_property(cachenode, "clock-frequency", NULL);
+ if (value && cpufreq)
+ *value = cpufreq;
+
+ value = (u32*)get_property(cachenode, "d-cache-size", NULL);
+ if (value)
+ *value = cachesize;
+
+ value = (u32*)get_property(cachenode, "d-cache-line-size", NULL);
+ if (value)
+ *value = cacheline;
+
+ value = (u32*)get_property(cachenode, "i-cache-size", NULL);
+ if (value)
+ *value = cachesize;
+
+ value = (u32*)get_property(cachenode, "i-cache-line-size", NULL);
+ if (value)
+ *value = cacheline;
+ }
+ #endif /* CONFIG_BLUECHIP_750FX */
+
/*
* finish_device_tree is called once things are running normally
* (i.e. with text and data mapped to the address they were linked at).
***************
*** 161,166 ****
--- 269,279 ----
mem = finish_node(allnodes, mem, NULL, 1, 1);
dev_tree_size = mem - (unsigned long) allnodes;
klimit = (char *) mem;
+
+ #ifdef CONFIG_BLUECHIP_750FX
+ if ((PVR_VER(real_pvr)==0x7000) && (PVR_VER(mfspr(PVR))==8))
+ prom_fixup_for_750fx();
+ #endif /* CONFIG_BLUECHIP_750FX */
}
static unsigned long __init
diff -b -c -r linux-2.4-benh.orig/arch/ppc/kernel/setup.c linux-2.4-benh/arch/ppc/kernel/setup.c
*** linux-2.4-benh.orig/arch/ppc/kernel/setup.c Mon Jun 16 04:40:41 2003
--- linux-2.4-benh/arch/ppc/kernel/setup.c Thu Jun 26 18:54:25 2003
***************
*** 155,161 ****
lpj = cpu_data[i].loops_per_jiffy;
seq_printf(m, "processor\t: %u\n", i);
#else
! pvr = mfspr(PVR);
lpj = loops_per_jiffy;
#endif
--- 155,161 ----
lpj = cpu_data[i].loops_per_jiffy;
seq_printf(m, "processor\t: %u\n", i);
#else
! pvr = real_pvr;
lpj = loops_per_jiffy;
#endif
diff -b -c -r linux-2.4-benh.orig/arch/ppc/platforms/pmac_cpufreq.c linux-2.4-benh/arch/ppc/platforms/pmac_cpufreq.c
*** linux-2.4-benh.orig/arch/ppc/platforms/pmac_cpufreq.c Wed Apr 30 10:29:25 2003
--- linux-2.4-benh/arch/ppc/platforms/pmac_cpufreq.c Thu Jun 26 18:58:46 2003
***************
*** 238,243 ****
--- 238,244 ----
* - Titanium PowerBook 500 (PMU based, 300Mhz & 500Mhz)
* - iBook2 500 (PMU based, 400Mhz & 500Mhz)
* - iBook2 700 (CPU based, 400Mhz & 700Mhz, support low voltage)
+ * - BlueChip G3 upgraded Pismo PowerBook (CPU based)
*/
static int __init
pmac_cpufreq_setup(void)
***************
*** 302,308 ****
cpufreq_uses_pmu = 1;
}
/* Else check for 750FX */
! else if (PVR_VER(mfspr(PVR)) == 0x7000) {
if (get_property(cpunode, "dynamic-power-step", NULL) == NULL)
goto out;
hi_freq = cur_freq;
--- 303,309 ----
cpufreq_uses_pmu = 1;
}
/* Else check for 750FX */
! else if (PVR_VER(real_pvr) == 0x7000) {
if (get_property(cpunode, "dynamic-power-step", NULL) == NULL)
goto out;
hi_freq = cur_freq;
diff -b -c -r linux-2.4-benh.orig/include/asm-ppc/processor.h linux-2.4-benh/include/asm-ppc/processor.h
*** linux-2.4-benh.orig/include/asm-ppc/processor.h Thu Jun 26 17:19:10 2003
--- linux-2.4-benh/include/asm-ppc/processor.h Fri Jun 27 11:51:29 2003
***************
*** 559,564 ****
--- 559,567 ----
#define _CHRP_Motorola 0x04 /* motorola chrp, the cobra */
#define _CHRP_IBM 0x05 /* IBM chrp, the longtrail and longtrail 2 */
+ /* default low speed config for cases where we set PLL1 ourselves */
+ #define DEFAULT_PLL1_CONFIG 8 /* for 4x bus-speed */
+
#define _GLOBAL(n)\
.globl n;\
n:
***************
*** 616,621 ****
--- 619,629 ----
#define _machine 0
#endif /* CONFIG_ALL_PPC */
+ /* Some machines report incorrect version with mfspr(PVR). Use this global
+ * instead.
+ */
+ extern unsigned int real_pvr;
+
struct task_struct;
void start_thread(struct pt_regs *regs, unsigned long nip, unsigned long sp);
void release_thread(struct task_struct *);
** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/
More information about the Linuxppc-dev
mailing list