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