Subject: PowerPC 750GX (FX?) PLL Settings - Getting it running at 1GHz!
To: None <,>
From: Francis Koclas <>
List: port-powerpc
Date: 10/29/2005 00:31:42
A couple months ago I posted to see if anyone has been able to run the 
PowerLogix 1GHz 750GX processor at 1GHz (defaults to 500MHz).
(and follow-ups)

Posts by John Klos on port-macppc were the first I had found on the same 
topic, so I promptly contacted him. I also found posts by Matthias 
Kretschmer on the same topic again on port-powerpc this time. So I 
contacted him as well and started working on this.

As recently as yesterday I was linked by a kind person on #netbsd to a 
patch submitted for the linux kernel 2.4.30 by Kevin Diggs. I contacted 
him and he gave me some valuable input on the work I had done until then.

It's too bad we mostly had conducted seperate efforts for the same task.

However, I'm glad to report that I have managed to get mine running at 1GHz!

cpu0 at mainbus0: 750 (Revision 2.3), ID 0 (primary)
cpu0: 1000.00 MHz, no-parity 1MB WB L2 cache (PB SRAM) at 1:1 ratio

A little php script which calculates 2,500,000 decimals of Pi runs twice 
as fast with this setting, so the CPU is indeed running at 1GHz.

Here is useful information on how to get this done :

Details about the HID1 register (IBM):

Procedure to use to set the processor PLLs (IBM):

Masks needed to set the HID1 register (myself):

I got the "result" (last line of that last link) with a very simple C 
program I made.

These are the changes I have done:

File: /usr/src/sys/arch/powerpc/oea/cpu_subr.c
Function: cpu_setup
What: everything inside the two boxes :-)

cpu_setup(self, ci)
	struct device *self;
	struct cpu_info *ci;
	u_int hid0, pvr, vers;
	char *bitmask, hidbuf[128];
	char model[80];
	u_int hid1;

	/* set HID1[PR1] */
	hid1 = mfspr(SPR_HID1);
	hid1 = hid1 | 0x00000002;
	mtspr(SPR_HID1, hid1);

	/* set HID1[PC1] */
	hid1 = hid1 | 0x000000F0;
	mtspr(SPR_HID1, hid1);

	/* set HID1[PS] */
	hid1 = hid1 | 0x00010000;
	mtspr(SPR_HID1, hid1);


John on his end started working on a way to control this using sysctl.

My code works, but its dirty right now. By this I mean I make no check 
to see if the CPU is of the right kind or anything. I just change the 
PLL1 bits and switch over to it (750FX and GX has two PLLs, PLL0 and 
PLL1, and both processors share the exact same HID1 register). I did 
some tests 2 days ago and the type of CPU (variable "vers" in cpu_setup) 
is reported as 8, so it technically it would work if it was treated in 
the MPC750 block, although I'm not exactly sure this is reported right 
in the first place as it is not a Motorola (Freescale) G3.

The code does not seem too big but it took a big effort of my part to 
get it right. I had zero powerpc assembler background, and never did any 
kernel work before. So use this at your own risk, and please be kind =)

Surprisingly, the code works without any sync or wait calls. When I did 
my initial testing I had some __asm__volatile("sync"); and some 
delay(1000); calls, but the code worked as well without them..

What remains to be done:

- checks for the CPU type

- tests on 750FX (and more 750GX!) processors

- determine if some sync/wait calls should be added

- a some function which would translate the clock multiplier to the 
corresponding PC1 code, and then generate a valid mask.

- control via sysctl, or via the kernel config, kind of like the L2CR 
settings right now. example:

- verifications on how this affects power saving settings, etc.